<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Tom Clarkson</title>
    <description>High end full stack developer in Sydney, Australia.</description>
    <link>http://tqclarkson.com/</link>
    <atom:link href="http://tqclarkson.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 14 Jul 2021 04:08:29 +0000</pubDate>
    <lastBuildDate>Wed, 14 Jul 2021 04:08:29 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
        
         
      <item>
        <title>Reducing React / Redux boilerplate with ES.Next</title>
        <description>&lt;p&gt;&lt;img src=&quot;/images/squash-code.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I’ve been working with React and Redux for a while now. To start with I was mostly working from the standard React/Redux example, which meant I ended up with rather a lot of components that look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class SomeComponent extends React.Component {
    render() {
        return (
            &amp;lt;div&amp;gt;...&amp;lt;/div&amp;gt;
        );
    }
}

SomeComponent.propTypes = {
    children: React.PropTypes.node,
    items: React.PropTypes.object
};

export default connect(
    (state, props) =&amp;gt; ({
        items: state.items
    }),
    (dispatch) =&amp;gt; ({
        fetchSomething: (title) =&amp;gt; dispatch(Actions.fetchSomething())
    })
)(SomeComponent);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It works, but I have a pathological dislike of long boilerplate code, and defining the parameters of a component at the end of the file just doesn’t feel right. Ending up with twenty components all named “StartPage” didn’t exactly help with debugging either. Fortunately, it can be significantly improved by enabling some not yet standard javascript features.&lt;/p&gt;

&lt;h2 id=&quot;static-properties&quot;&gt;Static properties&lt;/h2&gt;

&lt;p&gt;Adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transform-class-properties&lt;/code&gt; babel plugin allows defining properties as well as methods on a class - perfect for propTypes, which I can  move to a more visible position, and I no longer have to remember to update the class name in two places when I use the component as a template.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class SomeComponent extends React.Component {
    static propTypes = {
        children: React.PropTypes.node,
        items: React.PropTypes.object
    };
    render() {
        return (
            &amp;lt;div&amp;gt;...&amp;lt;/div&amp;gt;
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;decorators&quot;&gt;Decorators&lt;/h2&gt;

&lt;p&gt;Decorators are enabled with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transform-decorators-legacy&lt;/code&gt; plugin. The syntax below is equivalent to later calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connect()(SomeComponent)&lt;/code&gt;, but the decorated class can now be exported directly, and the class name is only needed in one place.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@connect(mapStateToProps, mapDispatchToProps)
export default class SomeComponent extends React.Component {
    static propTypes = {
        children: React.PropTypes.node,
        items: React.PropTypes.object
    };
    render() {
        return (
            &amp;lt;div&amp;gt;...&amp;lt;/div&amp;gt;
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much cleaner, though that does leave out the property mappings. To further simplify things, I ended up making a custom decorator that checks for a static method on the class before calling connect.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@page
export default class SomeComponent extends React.Component {
    static propTypes = {
        children: React.PropTypes.node,
        items: React.PropTypes.object
    };
    static mapStateToProps(state, props) { 
        return {
            items: state.items
        };
    }
    static mapDispatchToProps(dispatch) =&amp;gt; {
        return {
            fetchSomething: (title) =&amp;gt; dispatch(Actions.fetchSomething())
        };
    }
    render() {
        return (
            &amp;lt;div&amp;gt;...&amp;lt;/div&amp;gt;
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok, so technically this is the same length as the original, but it works much better when the code gets longer than a page, and no repeated renaming is needed when copying it as a new component. There’s also a lot of other common functionality that can be hidden in the decorator beyond the scope of this example - I’m not sure if a universal component extension makes sense yet, but certainly at the app level there is always a bunch of stuff that needs to be applied on every page.&lt;/p&gt;

</description>
        <pubDate>Wed, 18 Jan 2017 12:00:00 +0000</pubDate>
        <link>http://tqclarkson.com/2017/01/18/reducing-react-redux-boilerplate-esnext/</link>
        <guid isPermaLink="true">http://tqclarkson.com/2017/01/18/reducing-react-redux-boilerplate-esnext/</guid>
        
        
      </item>
      
    
        
         
      <item>
        <title>Sharing Web Code with React Native</title>
        <description>&lt;p&gt;&lt;img src=&quot;/images/react-multiplatform.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One of my current projects involves building much the same thing as both web and native apps. As a result, I have spent a fair bit of time thinking about how best to share code between the different platforms.&lt;/p&gt;

&lt;h2 id=&quot;front-end-logic&quot;&gt;Front end logic&lt;/h2&gt;

&lt;p&gt;This is the easy one - Redux works out of the box with both React and React native. You just need to make sure the actions/reducers don’t directly do anything that won’t be shared. So far that seems to mostly be routing (react native uses a completely different navigation model) and web api calls - even if the app still calls the web api, the authentication process is completely different.&lt;/p&gt;

&lt;h2 id=&quot;data-access&quot;&gt;Data access&lt;/h2&gt;

&lt;p&gt;The final version of the app has quite different requirements for working with data - local storage is available, and the whole thing should work offline. Eventually I expect that only the interface connecting it to redux will be shared, but as a first step it turns out to be really useful to be able to use the web api as is. An important part of my development process is being able to use the app myself, and this lets me start using the app before writing any native code. The app isn’t releasable like this, but it feels like the real thing for testing. It also means that only one implementation is needed during early development when stuff is changing a lot.&lt;/p&gt;

&lt;p&gt;Although I initially had the API set up as an ES6 module with exported functions, I’ve found the best approach to be a class that can be initialized in the non-shared entry point. It makes little difference for the final implementation, but makes early development much easier - initially only the url and authentication will be different, with more specialized implementations added gradually.&lt;/p&gt;

&lt;p&gt;Splitting the API into multiple parts is probably useful here - most likely the app will need to continue connecting to some parts of the api after the core is implemented locally, so make sure it is easy to remove the login / connectivity handling for only half the api calls.&lt;/p&gt;

&lt;h2 id=&quot;ui-code&quot;&gt;UI code&lt;/h2&gt;

&lt;p&gt;As far as I can tell, UI code is rarely shared between web and React Native apps. On a certain level this makes sense - native components usually look better - but it comes with some disadvantages as well. Building a full set of native components is a significant chunk of work before the app does anything, and keeping all platforms up to date can be challenging in the experimental stage of development.&lt;/p&gt;

&lt;p&gt;My approach is to use the page level components from the web version as either final implementation or at least placeholders for the native pages. Redux makes it relatively easy to pipe property updates and actions through the webview bridge. The framework I set up for this, react-native-web-components, is available on github. It’s still somewhat a work in progress and has some limitations, but works well enough for now.&lt;/p&gt;

&lt;p&gt;Navigation and page transitions stay as native code and are not shared - this covers 90% of the places where a hybrid app doesn’t look like a real native app, but requires minimal effort when all the pages use the same navbar component. In the past I have built apps using native transitions with cordova, but react-native makes it way easier to mix web and native components.&lt;/p&gt;

&lt;p&gt;Differences in the overall app structure are somewhat inevitable anyway - login / connectivity ui in particular is completely different, with the web app requiring authentication on startup, and the native app needing authentication to be optional and only used for some functions.&lt;/p&gt;

&lt;h2 id=&quot;routing&quot;&gt;Routing&lt;/h2&gt;

&lt;p&gt;Routing and app structure seem to be fundamentally unsharable. I am currently using react-router and react-native-router-flux, which are quite different, but I haven’t found any that are significantly more similar and I don’t really want to write my own. Web routes are based on a url for each page in the app, with the option to work out an appropriate transition based on link settings or the current route. Native routes are linked directly to a transition, and are not necessarily valid from all starting routes.&lt;/p&gt;

&lt;p&gt;However, in most cases transitioning to a new page requires the same kind of input, so it was reasonably easy to set up a wrapper as part of react-native-web-components which converts a common redux action into an appropriate router action. So far the connection is one way - both routers offer some sort of bidirectional integration with redux, but that hasn’t seemed worthwhile to set up yet.&lt;/p&gt;

&lt;h2 id=&quot;project-structure&quot;&gt;Project structure&lt;/h2&gt;

&lt;p&gt;My current setup involves three main git repos / npm packages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;app-client - a private npm package which contains most of the react / redux code. It can include some react-native components, but they must be sufficiently separate to not accidentally get imported into a web only package.&lt;/li&gt;
  &lt;li&gt;app-web - implements the server side api and hosts the web version of the app.&lt;/li&gt;
  &lt;li&gt;app-native - The native app. The only js code is in index.ios.js, which calls most of the same code from app-client but with different settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I usually use more pieces than that; I’d prefer to have a separate package for client code that is shared across multiple similar apps. However, the fact that the react packager doesn’t support npm link (or anything involving symlinks) makes that severely annoying. I have a watchman task that calls rsync to copy changes from app-client to app-native/node_modules/app-client, but it’s still annoying. I’m even considering using multiple targets rather than multiple app projects for some similar apps to further reduce the number of pieces.&lt;/p&gt;

</description>
        <pubDate>Tue, 13 Dec 2016 22:00:00 +0000</pubDate>
        <link>http://tqclarkson.com/2016/12/13/sharing-web-code-react-native/</link>
        <guid isPermaLink="true">http://tqclarkson.com/2016/12/13/sharing-web-code-react-native/</guid>
        
        
      </item>
      
    
        
         
      <item>
        <title>What the internet won't tell you about setting up mongo replica sets</title>
        <description>&lt;p&gt;&lt;img src=&quot;/images/ghost-mongo.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Over the last week or so I have been working on designing a simple autoscalable MongoDB cluster for hosting various projects. Seems like it should be easy, but a couple of details took way too much searching to figure out.&lt;/p&gt;

&lt;h2 id=&quot;single-node-replica-sets&quot;&gt;Single node replica sets&lt;/h2&gt;

&lt;h3 id=&quot;common-knowledge&quot;&gt;Common knowledge&lt;/h3&gt;
&lt;p&gt;A quick search turns up the fact that a replica set requires at least two servers and is entirely different from standalone mode. Tutorials on setting up a replica set typically start with setting up three empty servers then calling rs.initialize() with three addresses.&lt;/p&gt;

&lt;h3 id=&quot;the-truth&quot;&gt;The truth&lt;/h3&gt;
&lt;p&gt;A replica set will work just fine with a single node.&lt;/p&gt;

&lt;h3 id=&quot;why-everyone-says-you-cant&quot;&gt;Why everyone says you can’t&lt;/h3&gt;
&lt;p&gt;In normal operation, a single node replica set would be a bit silly - it uses more resources than standalone mode, but without the benefit of having a replacement server available, which is the whole point of replica sets.&lt;/p&gt;

&lt;h3 id=&quot;why-it-matters&quot;&gt;Why it matters&lt;/h3&gt;
&lt;p&gt;Automating setup of the replica set is far easier if all nodes after the first are identical:&lt;/p&gt;

&lt;p&gt;On server 1:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Call rs.initialize with only one node configured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On server 2..n&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Connect to server 1&lt;/li&gt;
  &lt;li&gt;Call rs.add with own address&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;even-number-of-nodes&quot;&gt;Even number of nodes&lt;/h2&gt;

&lt;h3 id=&quot;common-knowledge-1&quot;&gt;Common knowledge&lt;/h3&gt;
&lt;p&gt;There is no shortage of sources saying that a replica set should have an odd number of nodes, and that if you have an even number you need to add an arbiter to get back to odd numbers.&lt;/p&gt;

&lt;h3 id=&quot;the-truth-1&quot;&gt;The truth&lt;/h3&gt;
&lt;p&gt;Having an even number of nodes will not cause any problems - The issue is not the possibility of deadlocked elections or something similarly catastrophic, but that adding a fourth server does not usually provide any value until you add the fifth.&lt;/p&gt;

&lt;h3 id=&quot;why-everyone-says-you-cant-1&quot;&gt;Why everyone says you can’t&lt;/h3&gt;
&lt;p&gt;The primary purpose of a mongo replica set is to be able to tolerate failing servers. This only works when more than half the replica set survives the failure.&lt;/p&gt;

&lt;p&gt;If you have two servers and one fails, there is no way to tell the difference between the primary failing (secondary should become primary) and the secondary becoming disconnected from a functioning primary (secondary should wait for reconnection). The cluster becomes read only, which is far better than potentially allowing both servers to think they are the survivor and start writing inconsistent data.&lt;/p&gt;

&lt;p&gt;If you have 3 servers configured, you need 2 surviving servers to form a majority, so the replica set can survive a single server failing.&lt;/p&gt;

&lt;p&gt;Add a fourth server, and you need three survivors to make a majority - you can still only tolerate a single failure.&lt;/p&gt;

&lt;p&gt;Adding a fifth server to get back to odd numbers, the majority requirement stays at three, so you gain the ability to handle an additional server failing.&lt;/p&gt;

&lt;p&gt;Note that the probablity of 2/4 servers failing is slightly higher than the probabilty of 2/3 servers failing, so technically you are worse off with four than with three. However, your individual servers would have to be extremely flaky for this to become a significant problem.&lt;/p&gt;

&lt;h3 id=&quot;why-it-matters-1&quot;&gt;Why it matters&lt;/h3&gt;
&lt;p&gt;Scaling. My AWS setup treats all servers as disposable - they are never rebooted, only terminated and replaced. Deciding that there will normally be three servers in the cluster is easy. Ensuring that there will never be two or four is much harder.&lt;/p&gt;
</description>
        <pubDate>Sun, 10 Jan 2016 10:41:00 +0000</pubDate>
        <link>http://tqclarkson.com/2016/01/10/mongo-replica-sets/</link>
        <guid isPermaLink="true">http://tqclarkson.com/2016/01/10/mongo-replica-sets/</guid>
        
        
      </item>
      
    
        
         
      <item>
        <title>Reducing friction</title>
        <description>&lt;p&gt;&lt;img src=&quot;/images/tech-blender.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I always have too many projects on, and switching between them can be a problem. If I go back to a project I haven’t worked on in a while, I end up spending all the available time thinking things like “Is this really the same code as the live version?” and “How did I end up with ninety-three unpushed commits here?”&lt;/p&gt;

&lt;p&gt;Reducing the number of projects is never likely to work for me, so clearly it is time to improve my development setup to make it all managable.&lt;/p&gt;

&lt;h2 id=&quot;switching-between-projects-should-be-easy&quot;&gt;Switching between projects should be easy&lt;/h2&gt;
&lt;p&gt;Consistency is key here. It may not be possible to have everything work the same way, but I can come close.&lt;/p&gt;

&lt;p&gt;I already have most things set up so that running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gulp watch&lt;/code&gt; starts a development web server and automatically builds all changes. That can be extended to also start up a database or anything else that may be needed.&lt;/p&gt;

&lt;p&gt;If I don’t have a development environment already set up, I should be able to get everything I need with just git clone and npm install, and maybe npm link if I’m working on dependencies at the same time. No custom database setup or environment variables I can never remember.&lt;/p&gt;

&lt;h2 id=&quot;i-should-not-have-to-think-how-to-deploy-a-new-version&quot;&gt;I should not have to think how to deploy a new version&lt;/h2&gt;
&lt;p&gt;This means everything on a CI server for a start. In some ways that would be enough, but since I don’t want to spend a lot of time setting up scripts for each project, they should all deploy the same way as much as possible.&lt;/p&gt;

&lt;p&gt;Something like heroku with hosted mongodb would work for a lot of my projects, but other stuff is more experimental, and needs more than a basic web server and database. That should not require setting up a completely new system. Also, with a large number of small projects, hosting them seperately could get expensive.&lt;/p&gt;

&lt;p&gt;A previous attempt involved setting up git deployment on an EC2 instance, but that meant dealing with complex git commit hooks and a puppet script that needed complicated updates for each new app. And only using it for a few projects made it easy to forget how it worked.&lt;/p&gt;

&lt;p&gt;Shared autoscalable EC2 instances with CodeDeploy for individual apps looks like being a good solution, though I’ll need to make sure that after the initial setup it is no more effort to work with than a fully managed system.&lt;/p&gt;

&lt;h2 id=&quot;unreleased-apps-should-be-usable-with-real-data&quot;&gt;Unreleased apps should be usable with real data&lt;/h2&gt;
&lt;p&gt;Actually using an app is by far the best way to test its usability.&lt;/p&gt;

&lt;p&gt;I have tried a few different approaches to this in the past, none ideal. Connecting to the development server is fast and easy, but it means having local data that can’t be deleted. Having the dev server connect to an online database solves that, but having the session store thousands of miles away from the app server isn’t exactly great for performance. In either case, nothing works when not on the local network. Using the deployed version of the app solves that, but makes it harder to test the latest updates.&lt;/p&gt;

&lt;p&gt;This time I’m going to try making my continuous deployment setup good enough that there are never any significant features missing from the deployed version - test isolated functionality locally with test data while writing code, but any actual use is on the live environment.&lt;/p&gt;

&lt;h2 id=&quot;all-environments-should-be-disposable&quot;&gt;All environments should be disposable&lt;/h2&gt;
&lt;p&gt;Keeping any system working requires effort, so I’d rather not need to - in both development and live environments I should be able to delete everything and rebuild from scripts. My git folder should be a lot easier to navigate if it contains only active projects rather than everything I have worked on in the last few years.&lt;/p&gt;

&lt;p&gt;Live environments do require keeping the database up, but with a sufficiently automated replica set, individual servers can be disposable. I should not have to think about managing server patches or fixing a failed server - if something goes wrong or an update is needed, just shut it down and start a new instance.&lt;/p&gt;

&lt;p&gt;I have a couple of projects which store data on local disk, which doesn’t fit too well with this. I think I can replace that with NFS - still a single point of failure that has to be maintained, but at least it is kept separate from everything else and unlikely to need much management compared to a full web server.&lt;/p&gt;

&lt;p&gt;Anything with authentication or certificate requirements becomes a bit challenging when you disallow manually entering a password or uploading certificates. For the live setup, an encrypted write only S3 bucket with IAM instance roles should work. That won’t help with a local development environment, but it may be possible to avoid the requirement altogether there.&lt;/p&gt;

&lt;h2 id=&quot;tests-should-be-easy-to-set-up&quot;&gt;Tests should be easy to set up&lt;/h2&gt;
&lt;p&gt;I know I should use more unit tests, but getting the first one in place tends to be enough effort that I don’t get around to it. Test setup definitely needs to be part of my standard project template - Something that says “0/0 tests passed” isn’t all that useful in itself, but changing it to “0/1” is very easy.&lt;/p&gt;

&lt;p&gt;Including ESLint as part of the basic test setup is also a good idea - it catches a lot of errors for something that takes almost no effort to set up.&lt;/p&gt;
</description>
        <pubDate>Sat, 05 Sep 2015 23:30:00 +0000</pubDate>
        <link>http://tqclarkson.com/2015/09/05/reducing-friction/</link>
        <guid isPermaLink="true">http://tqclarkson.com/2015/09/05/reducing-friction/</guid>
        
        
      </item>
      
    
        
         
      <item>
        <title>Reboot</title>
        <description>&lt;p&gt;&lt;img src=&quot;/images/scribble.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It seems to have been a while since I updated my blog. No idea why.&lt;/p&gt;
</description>
        <pubDate>Thu, 27 Aug 2015 08:46:00 +0000</pubDate>
        <link>http://tqclarkson.com/2015/08/27/reboot/</link>
        <guid isPermaLink="true">http://tqclarkson.com/2015/08/27/reboot/</guid>
        
        
      </item>
      
    
        
         
    
        
         
    
        
         
    
        
         
    
        
         
    
  </channel>
</rss>
