<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Philip Beel, Software Engineer]]></title><description><![CDATA[music, movies, microcode]]></description><link>https://theodin.co.uk/</link><image><url>https://theodin.co.uk/favicon.png</url><title>Philip Beel, Software Engineer</title><link>https://theodin.co.uk/</link></image><generator>Ghost 3.2</generator><lastBuildDate>Thu, 27 Aug 2020 13:50:26 GMT</lastBuildDate><atom:link href="https://theodin.co.uk/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Better React app architectures]]></title><description><![CDATA[Reacts 'batteries not included' philosophy has empowered front-end engineering teams to make informed decisions on how to compose their apps, and  whilst empowering, there are architectural anti-patterns to be mindful of.]]></description><link>https://theodin.co.uk/better-react-app-architectures/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f28</guid><category><![CDATA[react]]></category><category><![CDATA[javascript]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Fri, 07 Aug 2020 14:06:47 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://s3.amazonaws.com/theodin.co.uk/posts/general/web_development_.svg" alt="react-application-architectures"></p>
<!--kg-card-end: markdown--><p>Since its debut in 2013, <a href="https://reactjs.org/">React JS</a> has been widely adopted as a technology favourite for web application development. JSX and by extension the virtual DOM have fundamentally shifted the way developers reason about building responsive interfaces. A '<a href="https://create-react-app.dev/">batteries not included</a>' philosophy has empowered front-end engineering teams to make the decisions about how to compose apps, however, there are architectural anti-patterns to be avoided when laying out a codebase. Applying simple principles will help build foundations that will last as technologies evolve.</p><h2 id="decoupled-concerns">Decoupled concerns  </h2><p>React JS is popular, so too is <a href="https://svelte.dev/">Svelte</a>, as is <a href="https://vuejs.org/">VueJS</a>. What would happen if your team decided to pivot from one solution to another? Do you have a suitable separation of concerns that means you can refactor a portion of your app, or are you likely to find a wholesale rewrite is necessary?</p><p>Defining boundaries around the various concerns of your application will help isolate what needs to import React. Take for example interacting with an API surface, does this need to be achieved with a React import statement?  An <a href="https://blog.fullstacktraining.com/adapter-pattern-in-typescript/">adapter pattern</a> can return data to React modules. The benefits are two fold:</p><ol><li>Your API handler, and test files won't need to import React, or <a href="https://testing-library.com/docs/react-testing-library/intro">React Testing Library</a>.</li><li>If you pivot away from React you can write a new adapter to communicate with the new view layer.</li></ol><!--kg-card-begin: markdown--><p><img src="https://s3.amazonaws.com/theodin.co.uk/posts/general/coding.svg" alt="mono-repos-architectures"></p>
<!--kg-card-end: markdown--><h2 id="monorepos">Monorepos</h2><p>Despite numerous <a href="https://blog.nrwl.io/misconceptions-about-monorepos-monorepo-monolith-df1250d4b03c">misconceptions about Monorepos</a>, fundamentally they represent a means to co-locate logical packages inside the same repo, they allow teams to independently build constituent parts of a project without blocking colleagues. Stability challenges often occur in distributed teams where there is no robust process to ensure dependency management is understood by producers and consumers of those packages.</p><p>If a Monorepo is right for your problem space, identify the areas of concern up-front, use the <a href="https://sunscrapers.com/blog/single-responsibility-principle-in-react-applications-part-1/">single responsibility principle</a> to help define what these are:</p><!--kg-card-begin: markdown--><pre><code>- package.json
- ...
|
---- /packages
    |
-------- /components
        |- package.json
        |- ...
-------- /routes
        |- package.json
        |- ...
-------- /api-handler
        |- package.json
        |- ...
-------- /api-react-adapter
        |- package.json
        |- ...
</code></pre>
<!--kg-card-end: markdown--><p>each package can run unit tests, perform linting, and create build artefacts etc, in isolation, which will speed up build times, and streamline developer workflows, this will also aid the first point ☝️ that your api-handler should not need to import React, and so your <code>package.json</code> file can omit this.</p><h2 id="technical-scorecard">Technical scorecard</h2><p>As a codebase grows and evolves, it will inevitably accrue technical debt, this can manifest for a range of reasons, some being:</p><ul><li>Applying <a href="https://thevaluable.dev/dry-principle-cost-benefit-example/">DRY principles</a>, that introduce abstractions, without being able to refactor all previous implementations.</li><li>Discovering a preferred approach, such as using functional components over classes.</li><li>Identifying new methods of testing, for example using <a href="https://kentcdodds.com/blog/stop-mocking-fetch">MSW instead of mocking fetch</a>.</li></ul><p>Technical debt presents several challenges including:</p><ul><li>Onboarding new starters - where it requires context from mentors who must point to the preferred approach.</li><li>Changing business logic, where it requires touching and refactoring 'outdated' patterns.</li></ul><p>A technical scorecard can help to track this, and be a useful input when understanding pain points. In the right hands it can highlight priority. A good technical scorecard can measure other dimensions too, such as developer satisfaction, time spent fixing vs building, as well as general codebase health. This is a worthwhile endeavour if your codebase is sufficiently growing and you are ramping up development resource.</p><h2 id="further-reading">Further reading</h2><ul><li>VIPER <a href="https://medium.com/@smalam119/viper-design-pattern-for-ios-application-development-7a9703902af6">design patterns for IOS</a></li><li>Presentation Model - <a href="https://martinfowler.com/eaaDev/PresentationModel.html">Martin Fowler</a></li><li>Adapter Pattern<a href="https://blog.fullstacktraining.com/adapter-pattern-in-typescript/"> for Javascript</a></li><li>Misconceptions <a href="https://blog.nrwl.io/misconceptions-about-monorepos-monorepo-monolith-df1250d4b03c">about Monorepos</a></li><li>Special thanks to <a href="https://www.manypixels.co/">ManyPixels</a> for imagery</li></ul>]]></content:encoded></item><item><title><![CDATA[Remote working: Creating conditions for success]]></title><description><![CDATA[Learnings from working remotely for a year in as a software engineer. Create a work environment where you will thrive]]></description><link>https://theodin.co.uk/a-year-remote-working/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f27</guid><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Fri, 03 Apr 2020 10:53:12 GMT</pubDate><content:encoded><![CDATA[<p>In 2019 I took a remote engineering role, motivated by a young family and a long commute.</p><p>Stepping away from a Software Management role, where I'd divided my time between technical leadership and people management, to a fully remote engineering role, was always going to require a change in mindset. Through this journey I've learned a few strategies which may be useful for others on the same path.</p><h3 id="separate-your-work-space">Separate your work space</h3><p>I took a month off between jobs to build a home shed-office (pronounced 'shoffice'). This was the single best investment I made in the transition, it won't be feasible for everyone, but whatever your environment, consider this a sacred space that needs to be treated with respect: </p><ul><li>Keeping the space tidy, and clutter free.</li><li>Educate others in the household to respect this space, this is where you will conduct yourself in a professional manner.</li><li>Have an 'off switch', it can be closing a door, or packing away of equipment, but make sure you know what that ritual is, and repeat it.</li></ul><!--kg-card-begin: markdown--><p><img src="https://s3.amazonaws.com/theodin.co.uk/posts/remote-working/sacred-office-space-at-home.jpg" alt="sacred office space"></p>
<!--kg-card-end: markdown--><h3 id="invest-in-audio-visual">Invest in audio visual</h3><p>Regardless of how your company is distributed, stand-ups, company all hands, and 1-2-1's will likely feature the medium of video calls. How you appear and sound becomes an extension of your professional demeanour: </p><ul><li>Consider face on cameras, with support for HD.</li><li>Simple lighting rigs will brighten dim spaces and improve streamed picture quality.</li><li>Headphones with built in microphones will offer superior audio fidelity. </li></ul><!--kg-card-begin: markdown--><p><img src="https://s3.amazonaws.com/theodin.co.uk/posts/remote-working/office-lighting-rig.jpg" alt="lighting rig"></p>
<!--kg-card-end: markdown--><h3 id="balance-over-burnout">Balance over burnout</h3><p> If you are fortunate enough to find a pursuit in life that you are passionate about, and create a set of favourable conditions to work in, it's very easy to get the balance wrong. I've spent most of my professional career fighting to get a balance that was right for me and those I love.  </p><ul><li>The brain processes information sequentially, which is why context switching is so expensive. Plan in half day increments. </li><li>The context switch must factor in breaks.</li><li>Exercise is paramount to a healthy physical and mental relationship with work. Set yourself up for success, prepare your workout/gear in advance, then you only need execute on it, a context change lends itself to this.</li></ul><h3 id="micro-interactions">Micro-interactions</h3><p>Continuing the topic of mental health, even the most introvert among us need to socialise. The opportunities for this are reduced when we are not co-located, so seeking and creating these opportunities is important.</p><ul><li>Asking for help is one of the easiest ways to do this. Pair programming using collaboration tools bridges the gap.</li><li>Daily standup in a remote environment will take longer, as it's not just about impediments and work in flight, it's an opportunity for people to share and connect.</li><li>Creating features of your work week, such as workshops and lightening talks will also create conditions for people to share and discuss areas of expertise.   </li></ul><h3 id="further-reading">Further reading</h3><ul><li>Lighting: <a href="https://www.amazon.co.uk/gp/product/B07YZ8PQW6/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&amp;psc=1">Lighting ring</a>, <a href="https://www.amazon.co.uk/gp/product/B079FQBFJD/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&amp;psc=1">Light bar</a></li><li>Video: <a href="https://www.amazon.co.uk/gp/product/B07MM4V7NR/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&amp;psc=1">Front-facing HD camera</a></li><li>Headphones: <a href="https://www.theverge.com/2017/12/8/16709882/best-wireless-over-ear-headphones-to-buy">best wireless headphones</a></li><li>Pair programming: <a href="https://visualstudio.microsoft.com/services/live-share/">Liveshare for VSCode</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Upgrade Ghost using Blue-Green deployments & Amazon Lightsail]]></title><description><![CDATA[Ghost is a powerful blogging platform with a promising roadmap of features, however updating to major releases can be problematic. An alternative approach to updating Ghost would be to use 'Blue-Green' deployments]]></description><link>https://theodin.co.uk/upgrading-ghost-blue-green-deployments-aws-lightsail/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f26</guid><category><![CDATA[AWS]]></category><category><![CDATA[AmazonLightsail]]></category><category><![CDATA[Ghost]]></category><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Sun, 25 Nov 2018 12:53:47 GMT</pubDate><content:encoded><![CDATA[<p>Ghost is a <a href="https://ghost.org/">powerful blogging platform</a> with a promising roadmap of features, however updating to major releases can be <a href="https://forum.ghost.org/t/ghost-cli-update-issue/1418">problematic</a>. The <a href="https://github.com/TryGhost/Ghost-CLI">Ghost CLI </a>sets out to solve this problem, but is not yet mature enough to trust updating releases on production servers.</p><blockquote>The objective of the Ghost CLI project is to make setting up and maintaining a Ghost site as straight forward as possible</blockquote><h3 id="blue-green-deployments">Blue-Green Deployments</h3><p>An alternative approach to updating Ghost would be to use 'Blue-Green' deployments, for a more in-depth description check out <a href="https://martinfowler.com/bliki/BlueGreenDeployment.html">Martin fowler's article on the subject</a>. In essence, you have a duplicate setup, Blue(e.g. Live) and Green(New Ghost version). Once updated Green is ready to deploy, you cut-over all traffic from Blue to Green. This has a number of advantages, most notably: </p><ul><li>Reduced/No downtime</li><li>Increased confidence and testing in production like environment</li><li>Ability to rollback easily </li></ul><h3 id="performing-blue-green-with-amazon-lightsail">Performing Blue-Green with Amazon Lightsail</h3><p><a href="https://www.techradar.com/uk/reviews/amazon-lightsail">Amazon Lightsail</a> offers a cheap and easy means to standup virtual servers with a simplified management interface. Although this article focuses on AWS, you could apply the same practice to <a href="https://www.digitalocean.com/">Digital Ocean</a> or other providers.  </p><p>The prerequisites for setup are: AWS account, AWS static IP, and DNS configured (Cloudflare). all of which will be covered. </p><p>A core tenant of Dev-Ops is to treat servers as '<a href="https://medium.com/@Joachim8675309/devops-concepts-pets-vs-cattle-2380b5aab313">Cattle, not Cats</a>', which is to say, it should be simple to standup and terminate servers with minimal system administration. In the case of Ghost you may want to speed up Green environment configuration by putting the setup into source control, but that will create it's own overhead as major releases will likely change this process.   </p><h3 id="creating-your-green-instance">Creating your Green instance </h3><p>Let's imagine you have a live v1 ghost blog served from AWS. You now want to upgrade to v2. From the AWS management console select <strong><em>Instances &gt; Create instance </em></strong>and select the ubuntu configuration as defined by the <a href="https://docs.ghost.org/install/ubuntu/">Ghost stack guide</a>. This will take a few moments to startup. You should have instances as follows where blue is live and green is your new candidate:</p><!--kg-card-begin: markdown--><p><img src="https://s3.amazonaws.com/theodin.co.uk/posts/Blue-Green/blue-green-instances.png" alt="blue-green-instances"></p>
<!--kg-card-end: markdown--><p>You can now setup your new instance following the <a href="https://docs.ghost.org/install/ubuntu/#create-a-new-user-">Ghost how to guide</a>. This should mean you are running the latest version of Ghost. Once done, you will want to use the <strong><em>Ghost admin console &gt; Labs </em></strong>export/import feature to move across your old posts and metadata to the new Green instance. Finally you may want to upload your new vX compliant theme into the Green Ghost instance. You can check that your theme meets the version requirements using the <a href="https://gscan.ghost.org/">gscan tool</a>. <strong>Please note:</strong> Once setup is complete, to have a true production environment you may need to re-run the <em>ghost-setup</em> command with your live blog domain name to ensure NGINX correctly maps HTTP requests on startup. </p><h3 id="setup-a-static-ip-address-with-lightsail">Setup a Static IP Address with Lightsail</h3><p>In the <a href="https://lightsail.aws.amazon.com">Lightsail console</a> navigate to <strong><em>Networking &gt; Create Static IP</em></strong> here we you will be asked to specify your availability region and an identifiable name for the IP address. Please note static IP addresses are only retained as long as they are attached to a specific instance, essentially a 'use it or loose it' policy. So be sure to attach to your Blue instance at this point. The IP address console should now display like so:</p><!--kg-card-begin: markdown--><p><img src="https://s3.amazonaws.com/theodin.co.uk/posts/Blue-Green/blue-green-static-ip.png" alt="blue-static-ip"></p>
<!--kg-card-end: markdown--><h3 id="routing-traffic-to-between-blue-green">Routing Traffic to between Blue-Green</h3><p>The domain name for your Ghost blog will point to your Blue(live) setup. <a href="https://www.cloudflare.com/ssl/">Cloudflare offer free SSL</a> that allows you to specify the static IP address to route all traffic to, meaning you can attach the static IP you created to either instance. If things go wrong and you need to rollback a straightforward re-attachment of the static IP to your Blue instance will reset you to your previous version. The console will show which instance has the static IP, in this example Green is now live:</p><figure class="kg-card kg-image-card"><img src="https://s3.amazonaws.com/theodin.co.uk/posts/Blue-Green/green-live-deployed.png" class="kg-image" alt="green deployed live"></figure><p></p><h3 id="blue-green-considerations">Blue Green Considerations</h3><p>Blue Green deployments are not a silver bullet, they come with their own tradeoffs, depending on the size and complexity of a service the cost overheads may be harder to justify. In the case of this example you could think of this as a transient event, where ghost-v1-blue is decommissioned, or you could use more general naming and keep both running so you can quickly and confidently keep pace with new updates without risking any production downtime. </p><h3 id="further-reading-">Further reading:</h3><p>If you are interesting in learning more about Blue-Green deployments and Dev-Ops best practices here is some recommended reading:</p><ul><li><a href="https://www.amazon.co.uk/dp/B07B9F83WM/ref=dp-kindle-redirect?_encoding=UTF8&amp;btkr=1">Accelerate: The Science of Lean Software and DevOps</a></li><li><a href="https://www.oreilly.com/library/view/the-devops-handbook/9781457191381/">The DevOps Handbook</a></li><li><a href="https://martinfowler.com/bliki/BlueGreenDeployment.html">BlueGreenDeployment - Martin Fowler</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Setup a Clojure Webserver with Jetty, Compojure, & Hiccup]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://clojure.org/">Clojure</a> is a versatile programming language founded on dynamic principles. Its speed and coherence have made it a desireable candidate for microservice achitectures, however the learning curve is steep.</p>
<h3 id="settingupaclojureproject">Setting up a Clojure project</h3>
<p>Clojures power also brings complexity. There are a number of ways to configure Clojure projects, but</p>]]></description><link>https://theodin.co.uk/setup-a-clojure-webserver-with-jetty-compojure/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f25</guid><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Wed, 09 May 2018 15:59:51 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://clojure.org/">Clojure</a> is a versatile programming language founded on dynamic principles. Its speed and coherence have made it a desireable candidate for microservice achitectures, however the learning curve is steep.</p>
<h3 id="settingupaclojureproject">Setting up a Clojure project</h3>
<p>Clojures power also brings complexity. There are a number of ways to configure Clojure projects, but one of the most popular is <a href="https://leiningen.org/">leiningen</a>. This simple configuration tool enables fast project setup, so you can focus on building.</p>
<h3 id="exampleclojurewebserver">Example Clojure webserver</h3>
<p>Clojure is an ideal language for web projects, suitable for API and application development. This <a href="https://github.com/philipbeel/example-clojure-webserver-jetty-compojure-hiccup">example project</a> provides a webserver boilerplate with support for app routing and HTML templating.</p>
<p>Once Leiningen is installed follow these steps to setup a webserver at <a href="http://localhost:3000">http://localhost:3000</a></p>
<pre><code>git clone git@github.com:philipbeel/example-clojure-webserver-jetty-compojure-hiccup.git

cd example-clojure-webserver-jetty-compojure-hiccup

lein run
</code></pre>
<h4 id="webserversetupusingringjettyadapter">Webserver setup using Ring Jetty adapter</h4>
<p><a href="https://github.com/ring-clojure/ring/wiki/Getting-Started">Ring Jetty adapter</a> allows integration of a configurable webserver into any Clojure project, it provides options for threading, port configuration, and basic <a href="https://practicalli.github.io/clojure-webapps/create-a-webserver-with-ring/add-a-jetty-webserver.html">req/response structures</a>. It can be used as the basis for web based projects.</p>
<h4 id="routingrequestswithcompojure">Routing requests with Compojure</h4>
<p><a href="https://github.com/weavejester/compojure/wiki/Routes-In-Detail">Compojure</a> provides a comprehensive routing library. The example project implements a two routes, for an index page and a 404 page, demonstrating how these can be abstracted into a <code>/routing</code> directory.</p>
<h4 id="expressivehtmltemplatingviahiccup">Expressive HTML templating via Hiccup</h4>
<p><a href="https://github.com/weavejester/hiccup">Hiccup</a> offers an expressive way to write HTML markup. The API reference documents how the structure can be extended to create dynamic markup. The <a href="https://github.com/philipbeel/example-clojure-webserver-jetty-compojure-hiccup/blob/master/src/server_example/routing/index.clj">example project</a> demonstrates how this can be used in conjunction with script and stylesheets to render comprehensive HTML documents.</p>
<h3 id="furtherreading">Further reading</h3>
<p>Clojure is an extremly robust language, whilst setup can be challenging there are a great number of libraries that make it extremely enjoyable to work with. If you are interested in finding out more about Clojure, here are some recommended links:</p>
<ul>
<li><a href="https://github.com/functional-koans/clojure-koans">A set of exercises for learning Clojure</a></li>
<li><a href="https://www.braveclojure.com/">Brave Clojure</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Typescript coverage with Mocha & NYC]]></title><description><![CDATA[How implement code coverage in Typescript projects using Mocha, and Istanbul NYC. ]]></description><link>https://theodin.co.uk/typescript-coverage-mocha-nyc/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f24</guid><category><![CDATA[typescript]]></category><category><![CDATA[Istanbul NYC]]></category><category><![CDATA[Mocha]]></category><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Fri, 09 Mar 2018 22:46:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><a href="https://www.typescriptlang.org/index.html">Typescript</a> provides strict typing, empowering teams to build enterprise applications that scale. Whilst precompilers offer benefits to Javascript, they present interoperability challenges when performing coverage checks on precompiled code.</p>
<h4 id="typescriptcoveragereports">Typescript coverage reports</h4>
<p>Coverage reports give insight into statements, functions, branches, and lines, but not necessarily <a href="https://theodin.co.uk/2015/12/30/javascript-coverage-with-gulp-karma-istanbul/">quality</a>. It stands to reason that if your application code is written in Typescript, then your tests should be too. Further to this, having coverage represented in Typescript as opposed to compiled Javascript is invaluable in the development workflow.</p>
<h4 id="typescriptcoverageexample">Typescript coverage example</h4>
<p>This <a href="https://github.com/philipbeel/example-typescript-nyc-mocha-coverage">example project</a> demonstrates how to generate a Typescript coverage report for unit tests written in  <a href="https://mochajs.org/">Mocha</a> and executed with <a href="https://github.com/istanbuljs/nyc">NYC</a>.</p>
<pre><code>git clone git@github.com:philipbeel/example-typescript-nyc-mocha-coverage.git
</code></pre>
<p>The example project implements a boilerplate Typescript app for a crude calculator, with addition and subtraction files located in <code>calculator/ts/src</code>. The coverage report is executed from <code>package.json</code>:</p>
<pre><code>cd example-typescript-nyc-mocha-coverage
npm install
npm run coverage
</code></pre>
<h4 id="coverageinteroperabilityexplained">Coverage interoperability explained:</h4>
<p>The command executes the following behaviour in order to generate the report:</p>
<ol>
<li>The <code>package.json</code> specifies <a href="https://github.com/istanbuljs/nyc#configuring-nyc">configuration</a> options for NYC, the app <code>.ts</code> files are included and all test files, denoted by <code>*.test.ts</code> are excluded from the coverage report</li>
<li>The <code>/test</code> directory includes a <code>mocha.opts</code> file, this tell Mocha where to find the tests that need executing.</li>
<li>The unit tests are run, then the results are collected by NYC, which produces a coverage summary and a generated <code>/coverage</code> directory outlining the full detailed report.</li>
</ol>
<pre><code>==== Coverage summary =======
Statements   : 100% ( 10/10 )
Branches     : 100% ( 0/0 )
Functions    : 100% ( 6/6 )
Lines        : 100% ( 10/10 )
==============================
</code></pre>
<h4 id="furtherreading">Further reading:</h4>
<p>Typescript solves a very specific problem, however, it may not be right for every situation. If you are interested in learning more here are some resources:</p>
<ul>
<li><a href="https://kamranicus.com/presentations/demystifying-typescript/#/">Demystifying Typescript</a></li>
<li><a href="https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html">Typescript by example</a></li>
<li><a href="https://hackernoon.com/typescript-vs-javascript-b568bc4a4e58">Typescript Vs Javascript</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Securing Ghost with SSL and Amazon Lightsail Bitnami Apps]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The advent of <a href="https://amazonlightsail.com/">Amazon Lightsail</a> makes it even easier to spin up low cost EC2 instances, these can be pre-configured with a range of images such as NodeJS. <a href="http://codingagaintomorrow.com/creating-a-blog-site-in-aws/">CodeAgainTomorrow</a> provides a tutorial to get setup with <a href="https://ghost.org/">Ghost</a>, ideal for a blog. Securing your instance with SSL is essential for <a href="https://moz.com/blog/seo-tips-https-ssl">a</a></p>]]></description><link>https://theodin.co.uk/securing-ghost-with-ssl-on-amazon-lightsail-bitnami-apps/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f23</guid><category><![CDATA[SSL]]></category><category><![CDATA[AmazonLightsail]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Ghost]]></category><category><![CDATA[Bitnami]]></category><category><![CDATA[Apache2]]></category><category><![CDATA[CSR]]></category><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Wed, 28 Jun 2017 22:36:45 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>The advent of <a href="https://amazonlightsail.com/">Amazon Lightsail</a> makes it even easier to spin up low cost EC2 instances, these can be pre-configured with a range of images such as NodeJS. <a href="http://codingagaintomorrow.com/creating-a-blog-site-in-aws/">CodeAgainTomorrow</a> provides a tutorial to get setup with <a href="https://ghost.org/">Ghost</a>, ideal for a blog. Securing your instance with SSL is essential for <a href="https://moz.com/blog/seo-tips-https-ssl">a number of security and SEO reasons</a>, configuring <a href="https://blog.yell.com/2016/03/https-is-hard/">SSL can be hard</a>, but it doesn't have to be.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>The following assumptions will be made:</p>
<ul>
<li>You have acquired an <a href="https://www.namecheap.com/security/ssl-certificates.aspx">SSL certificate</a> from a vendor</li>
<li>You selected the Bitnami NodeJS image for your Lightsail instance</li>
<li>You own a domain name and you have setup DNS to <a href="http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-ec2-instance.html">point to your instance</a></li>
<li>You have <a href="http://codingagaintomorrow.com/creating-a-blog-site-in-aws/">setup your ghost blog</a></li>
</ul>
<h2 id="generatingacsr">Generating a CSR</h2>
<p>Bitnami's Apache2 configuration comes with a self signed certificate pre-installed, which means the <code>bitnami.conf</code> only requires light modification. In order to swap the self signed cert for a trusted one, first you will need to generate a Certificate Signing Request (CSR)</p>
<h6 id="1navigatetotheapache2configuration">1. Navigate to the apache2 configuration</h6>
<p>SSH into your Lightsail instance and navigate to the conf directory:</p>
<pre><code>cd /opt/bitnami/apache2/conf
</code></pre>
<p>This directory will already be populated with the self signed <code>server.key</code>, <code>sever.crt</code>.</p>
<h6 id="2createrequest">2. Create request</h6>
<p>Next a CSR and key must be generated. To avoid confusion it's recommended to use the domain name for csr/key. Modify and run the following command:</p>
<pre><code>openssl req -new -newkey rsa:2048 -nodes -keyout domain-name.key -out domain-name.csr
</code></pre>
<p>When prompted enter information about the company and domain. <strong>Please note: United Kingdom region must use the 'GB' country code.</strong></p>
<h6 id="3copythecsr">3. Copy the CSR</h6>
<p>A new CSR and key will be generated, open the CSR and copy the entire contents:</p>
<pre><code>cat domain-name.csr
</code></pre>
<h2 id="verification">Verification</h2>
<p>Paste the CSR into the SSL vendors control panel. The certificate issuer will need to verify the owner of the domain, there are generally 3 ways to do this:</p>
<ul>
<li>Provide an accessible domain email address.</li>
<li>Create a unique DNS CNAME.</li>
<li>Upload a unique public facing asset to the server.</li>
</ul>
<p>Choose the appropriate method and follow the vendors instructions, it can take up to one hour to be verified.</p>
<h2 id="uploadsigningmaterials">Upload signing materials</h2>
<p>Once the SSL vendor has verified that you own the domain a set of signing materials will be available to download. Depending on the vendor the format can vary:</p>
<ul>
<li><code>domain.crt</code></li>
<li><code>domain.ca-bundle</code> (dependent on vendor)</li>
</ul>
<p>Either SCP these files into <strong>/opt/bitnami/apache2/conf</strong> or touch the files and copy paste the contents of the signing materials, for consistency it's recommended to use the domain when naming these files.</p>
<pre><code>cd /opt/bitnami/apache2/conf
touch domain.crt
vim domain.crt
</code></pre>
<h2 id="makecertsavailable">Make certs available</h2>
<p>To start using the new signing materials the <code>bitnami.conf</code> needs updating, open the configuration for editing:</p>
<pre><code>vim /opt/bitnami/apache2/conf/bitnami/bitnami.conf
</code></pre>
<p>Search for the following lines:</p>
<pre><code>&lt;VirtualHost _default_:443&gt;
  DocumentRoot &quot;/opt/bitnami/apache2/htdocs&quot;
  SSLEngine on
  SSLCertificateFile &quot;/opt/bitnami/apache2/conf/domain.crt&quot;
  SSLCertificateKeyFile &quot;/opt/bitnami/apache2/conf/domain.key&quot;
</code></pre>
<ul>
<li><strong>SSLCertificateFile:</strong> replace with the newly added <code>domain.crt</code></li>
<li><strong>SSLCertificateKeyFile:</strong> replace with the <code>domain.key</code> that you generated in the initial CSR request</li>
</ul>
<p>Additionally if a <code>domain.ca-bundle</code> was provided in the signing materials include this line for Apache2:</p>
<pre><code>SSLCertificateChainFile &quot;/opt/bitnami/apache2/conf/domain.ca-bundle&quot;
</code></pre>
<h2 id="exclusiveuseofhttps">Exclusive use of https</h2>
<p>In order to make exclusive use of https:// on all incoming requests, include the <strong>RequestHeader</strong> directive into the above block:</p>
<pre><code>RequestHeader set X-Forwarded-Proto &quot;https&quot;
</code></pre>
<h2 id="restartapache">Restart Apache</h2>
<p>For the changes to take effect, Apache must be restarted:</p>
<pre><code>sudo /opt/bitnami/ctlscript.sh restart apache
</code></pre>
<p>The CLI will notify you if there were any issues restarting Apache2, assuming everything is successful, test out the domain name on <strong>https://</strong> and you should get the padlock confirming you are now serving your ghost blog over SSL.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Programming reactive interfaces with RxJS]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Building enterprise level web UI's is challenging. Functional Reactive Programming (FRP) may hold the solution with the advent of 'Reactive Extensions for JavaScript' also known as <a href="https://github.com/Reactive-Extensions/RxJS">RxJS</a>.</p>
<h4 id="whatisreactiveprogramming">What is reactive programming!?</h4>
<p><a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754">André Staltz introduction</a> to 'reactive programming' gives a great overview to the subject, I strongly recommend you read this</p>]]></description><link>https://theodin.co.uk/programming-reactive-interfaces-with-rxjs/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f22</guid><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Sat, 08 Oct 2016 18:42:54 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Building enterprise level web UI's is challenging. Functional Reactive Programming (FRP) may hold the solution with the advent of 'Reactive Extensions for JavaScript' also known as <a href="https://github.com/Reactive-Extensions/RxJS">RxJS</a>.</p>
<h4 id="whatisreactiveprogramming">What is reactive programming!?</h4>
<p><a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754">André Staltz introduction</a> to 'reactive programming' gives a great overview to the subject, I strongly recommend you read this first.</p>
<p>Functional Reactive programming is a paradigm that combines event driven programming with the benefits of functional programming. UI development is a perfect use case, as the majority of engagement comes from user interaction.</p>
<h4 id="streamsandmonads">Streams and monads</h4>
<p>Event streams are the cornerstone of RxJS, however in order to explain this we must first understand monads, which is <a href="http://stackoverflow.com/questions/2704652/monad-in-plain-english-for-the-oop-programmer-with-no-fp-background">no easy task</a>. If you've ever used libraries like jQuery, the syntax may feel familiar:</p>
<pre><code>$('#id').fadeOut('slow').fadeIn('fast')
</code></pre>
<p>The conceptual idea of chaining functions onto monads means you can write succinct, readable code. RxJS builds on this theme by broadcasting and subscribing to event streams, functions can be chained to these event streams to perform a range of actions.</p>
<h4 id="rxjsinpractice">RxJS in practice</h4>
<p>Let's put these concepts into practice. Imagine you are given a requirement to build a PIN entry feature, that must apply the following business rules:</p>
<ul>
<li>Accept only numeric values from the keyboard.</li>
<li>Take a maximum of 4 numeric values.</li>
<li>Update the UI to display the user input values in order.</li>
<li>Display a notification when all criteria has been met.</li>
</ul>
<p>Lets look at how we might implement this in RxJS:</p>
<pre><code>    Rx.Observable.fromEvent(document, 'keyup')
        .debounce(100)
        .map((data) =&gt; data.key)
        .filter((key) =&gt; !isNaN(Number(key)))
        .take(4)
        .do(input =&gt; document.getElementsByTagName('input')[this.inputCount++].value = input)
        .count()
        .last(x =&gt; document.getElementById('notification').style.display='block')
        .subscribe(this.inputCount = 0);
</code></pre>
<p><a href="https://github.com/philipbeel/example-rxjs">Checkout the full example on Github</a></p>
<p><em>Please note this requires an ES6 compatible browser</em></p>
<p>In just 9 lines a stream has been created, which fulfils all these requirements. Lets step through the code to take a closer look at what's happening:</p>
<pre><code>    // Create observer on the keyup event
    Rx.Observable.fromEvent(document, 'keyup')
        // Wait 100ms between user keyup events 
        .debounce(100)
        // Strip the keyboard keys value from the data object
        .map((data) =&gt; data.key)
        // Filter out everything but number keys
        .filter((key) =&gt; !isNaN(Number(key)))
        // Only accept 4 numerical key values
        .take(4)
        // Push this value into the N input field on the DOM
        .do(input =&gt; document.getElementsByTagName('input')[this.inputCount++].value = input)
        // Count the number of numerical keypresses
        .count()
        // On the last numerical keypress display a notification to the user
        .last(x =&gt; document.getElementById('notification').style.display='block')
        // Finally subscribe to the key up event and start the input count at 0
        .subscribe(this.inputCount = 0);
</code></pre>
<h4 id="considerationsandimprovements">Considerations and improvements</h4>
<p>This example implementation is not perfect. The view interaction is tightly coupled, ideally this would be handled by a mediator or other actor. Taking this idea further we could include:</p>
<ul>
<li>An external API to validate the PIN value is correct</li>
<li>Error handling if the PIN does not match the expected value</li>
<li>Handling mouse and manual focus events.</li>
</ul>
<h4 id="summary">Summary</h4>
<p>RxJS has a steep learning curve, but With <a href="http://techblog.netflix.com/search/label/Rx">Netflix</a> driving the profile of this emerging set of libraries I expect resources and documentation to improve.</p>
<p>Having used RxJS in conjunction with Typescript and ES6 I have been really impressed by it's versatility, that said it may not suit every use case. If you are working on enterprise level applications with larger teams 20+ RxJS is worth some investigation.</p>
<h5 id="furtherreading">Further reading:</h5>
<ul>
<li><a href="http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html">RxJS documentation</a></li>
<li><a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754">The introduction to Reactive Programming you've been missing</a></li>
<li><a href="https://www.youtube.com/watch?v=AslncyG8whg">Netflix JavaScript Talks - RxJS + Redux + React = Amazing</a></li>
</ul>
<p>The full exampe RxJS code can be found on Github:<br>
<a href="https://github.com/philipbeel/example-rxjs">https://github.com/philipbeel/example-rxjs</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Javascript coverage with Gulp, Karma & Istanbul]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Creating modular, testable code in your Javascript projects is imperative. Coverage enables developers to measure their unit tests. <a href="https://gotwarlost.github.io/istanbul/">Istanbul</a> is one such tool and plays nicely with <a href="http://gulpjs.com/">gulp</a>. It can be used to cover statements, branches and functions.</p>
<h6 id="whatcoveragetoolsare">What coverage tools are:</h6>
<p>Useful indicators for project health, when combined with</p>]]></description><link>https://theodin.co.uk/javascript-coverage-with-gulp-karma-istanbul/</link><guid isPermaLink="false">5f29bfe7d199e5142dbf0f21</guid><category><![CDATA[javascript]]></category><category><![CDATA[karma]]></category><category><![CDATA[istanbul]]></category><category><![CDATA[gulp]]></category><dc:creator><![CDATA[Philip Beel]]></dc:creator><pubDate>Wed, 30 Dec 2015 01:56:58 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Creating modular, testable code in your Javascript projects is imperative. Coverage enables developers to measure their unit tests. <a href="https://gotwarlost.github.io/istanbul/">Istanbul</a> is one such tool and plays nicely with <a href="http://gulpjs.com/">gulp</a>. It can be used to cover statements, branches and functions.</p>
<h6 id="whatcoveragetoolsare">What coverage tools are:</h6>
<p>Useful indicators for project health, when combined with CI pipelines they ensure new and modified code is suitably covered and less likely to introduce bugs.</p>
<h6 id="whatcoveragetoolsarenot">What coverage tools are not:</h6>
<p>A guarantee that your tests are well written. You can have 100% code coverage, but if the tests are brittle, then it's for nothing.</p>
<hr>
<h5 id="istanbulcoverageexample">Istanbul Coverage example</h5>
<p>I've put together an <a href="https://github.com/philipbeel/example-istanbul-gulp-coverage">example project</a> to demonstrate how to integrate coverage into a project.</p>
<pre><code>git clone https://github.com/philipbeel/example-istanbul-gulp-coverage
</code></pre>
<p>You'll need to globally install gulp on your machine in order to run <code>gulp</code> on the CLI:</p>
<pre><code>cd example-istanbul-gulp-coverage
npm install 
npm install gulp -g
</code></pre>
<p>The example project implements YACA (Yet Another Calculator App) a crude calculator, with addition and subtraction files located in <code>calculator/js</code>. The project also contains a <code>gulpfile.js</code> and <code>karma.conf.js</code>, we'll walk through this later. For now we just want to run the default gulp task:</p>
<pre><code>gulp
</code></pre>
<p>You should see <code>coverage/js/index.html</code> open in your browser with the score of both files, <code>add.js</code> at 100% and <code>subtract.js</code> at 71%.</p>
<p><img src="https://s3.amazonaws.com/theodin.co.uk/posts/istanbul-example/istanbul-output.png" alt="istanbul coverage"></p>
<p>Clicking into a filename shows line by line details about what code is being covered. I've deliberately left off some tests on <code>subtract.test.js</code> so you can compare the results.</p>
<h6 id="coveragecommandexplained">Coverage command explained:</h6>
<p>When we executed the gulp command the following events sequence is triggered:</p>
<ol>
<li>The <code>unit:coverage</code> gulp task is executed, which starts a karma test runner and sets up the <a href="https://github.com/karma-runner/gulp-karma">configuration options</a></li>
<li>The phantom browser runs and the tests are executed inside of it.</li>
<li>The output is reported back to the gulpfile, Istanbul then creates a new <code>/coverage</code> directory to store the results.</li>
<li>A new browser tab is automatically opened displaying the Istanbul report.</li>
</ol>
<p>You can extend this example project to implement AMD, or switch mocha for jasmine, as per your requirements.</p>
<h6 id="furtherreading">Further reading</h6>
<p>Coverage testing can be valuable component of a wider CI toolchain. If your interested check out some of these valuable resources.</p>
<ul>
<li><a href="http://jenkins-ci.org/content/official-jenkins-lts-docker-image">Jenkins Docker Image</a></li>
<li><a href="http://elijahmanor.com/unit-test-like-a-secret-agent-with-sinon-js/">Sinnon JS unit testing</a></li>
<li><a href="https://www.atlassian.com/git/tutorials/git-hooks/">Git hooks</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>