AJ Kovalainenajk.fihttp://ajk.fi/2016-11-10T00:00:00+02:00AJ KovalainenDeveloper/Designer Rolehttp://ajk.fi/2016/developer-designer-role/2016-11-10T00:00:00+02:002025-05-19T17:12:01+00:00AJ Kovalainen<p><a href="https://twitter.com/timolaak/status/794467259951484928">A friend wanted to know</a> how a developer/designer hybrid role works in real life. Especially when it comes to working in a software consultancy. So here are my thoughts.</p>
<p><a href="http://www.solita.fi/">Solita</a> is a software consultancy, and I think being a developer & designer hybrid...</p><p><a href="https://twitter.com/timolaak/status/794467259951484928">A friend wanted to know</a> how a developer/designer hybrid role works in real life. Especially when it comes to working in a software consultancy. So here are my thoughts.</p>
<p><a href="http://www.solita.fi/">Solita</a> is a software consultancy, and I think being a developer & designer hybrid at Solita worked very well. I designed & developed HTML/JS prototypes for various projects. The team then “copy-pasted” it into the code. A few times, when I was on a project as a designer, I created style guides with some of the UI interactions implemented in JS. I also did small one-man projects where I designed e.g. a campaign website with the client and then implemented it e.g into an existing website monolith in ASP.NET. I guess that’s better for the company as you don’t have to put two resources on it, and have them spend budget communicating. Tho' a lot of the time talking with someone opens up new possibilities so ¯\_(ツ)_/¯</p>
<p>At <a href="https://flockler.com/">Flockler</a> being a developer/designer works great. I can create brandline adhering fully functional features on my own. Of course, I don’t just build it & ship it like that, but seek feedback continuously. And we’re actually lucky to have two developer/designer hybrids on our team, and we give feedback on both the design & the code to each other :) And it works great because in a fun way we complement each other. I’d say I’m more of a developer, with a ratio of 60% developer 40% designer while <a href="https://twitter.com/peritpatrio">Petri</a> is more of a designer with the same ratio in reverse.</p>
<p>The trickiest thing for me at least is that sometimes you’re in dev mode and can’t get into the artistic/creative mode, and sometimes you’re in design mode and just can’t think in code. But if you e.g. draw in Sketch first, then have a long pause (reset the brain with exercise or sleep) and write the code e.g. next day, it works better. Can be done in reverse as well (code first, design later).</p>
<p>Are you a fellow developer/designer hybrid? Or have you wondered what it’s like? Let me know your thoughts!</p>
Soundboard with Ember.jshttp://ajk.fi/2016/soundboard-with-ember-js/2016-05-02T00:00:00+03:002025-05-19T17:12:01+00:00AJ Kovalainen<p>I have a friend who’s a pretty fun guy. He’s been sending these bigger-than-life one-liners, small songs and what-not to our gang’s WhatsApp group and we’ve been having a laugh at them over a period of time. They’re mostly alcohol related and heavily...</p><p>I have a friend who’s a pretty fun guy. He’s been sending these bigger-than-life one-liners, small songs and what-not to our gang’s WhatsApp group and we’ve been having a laugh at them over a period of time. They’re mostly alcohol related and heavily tied to the Finnish culture. But I digress.</p>
<p>Looking for these sound clips in our WhatsApp group is tedious. It’s also impossible to anyone except our group. I wanted to make these clips easily available to everyone so I built a quick Ember app called <a href="http://ajk.fi/simo-soundboard/">Simo Soundboard</a> just for that, and here’s how I did it.</p>
<p><strong>TL;DR: Quick soundboard</strong><br>
If you just want to build a similar soundboard quickly—and don’t care about my story—you can clone my <a href="https://github.com/Darep/simo-soundboard">simo-soundboard</a> GitHub repo, replace <a href="https://github.com/Darep/simo-soundboard/tree/master/vendor/audio">the audio files</a>, <a href="https://github.com/Darep/simo-soundboard/blob/master/app/routes/application.js">give each file a nice name</a>, <a href="https://github.com/Darep/simo-soundboard/blob/master/config/secrets.ejson">change the secrets</a>, <a href="https://github.com/Darep/simo-soundboard/blob/master/README.md#building">compile the code</a> and deploy it somewhere. And there you go.</p>
<h3>Getting started</h3>
<p>I picked Ember because I’ve been working with Ember for 3 years and I’m very comfortable working with it. I simply love the workflow you get with <a href="http://ember-cli.com/">ember-cli</a> – even if an app doesn’t need Ember all that much, just like this soundboard didn’t! I used only Ember as there wasn’t any backend stuff required. Just static resources and some client-side logic.</p>
<p>Next, I started creating a mockup of the app in HTML & CSS. Soundboards are usually very simple and I wanted to follow that convention. I also wanted it to work well on mobiles so I started the design with the small screen sizes in mind. I made it responsive so it didn’t look like a stretched up mobile UI on desktop.</p>
<figure class="center"><a href="/uploads/2016/05/soundboard-ui-9592e2ae.png" class="img-wrap"><img src="/uploads/2016/05/soundboard-ui-9592e2ae.png" alt="Screenshot of the soundboard" onload="this.parentNode.parentNode.className += ' show';" width="423" height="450" /></a></figure>
<p>The actual Ember part of the app was very simple: just one ApplicationRoute as the root object, a template, and one play-button component that would wrap each sound clip and its logic.</p>
<h3>Playing sound</h3>
<p>After getting the initial design and the basic Ember app structure done, the next hurdle was to get the browser to play the sound clip. Having worked on <a href="http://www.beatstream.fi">Beatstream</a>, I know from experience how tricky playing sound in a wide range of browsers and devices can be. I’ve tested a bunch of different audio playing libraries and my experience is that <a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager2</a> does it best. So I pulled that into the app with <code>bower install --save ember-cli-soundmanager-shim</code>, updated the ember-cli-build.js to include SoundManager2’s files in the build, and made the <code>play-button</code> component use SM2 to play the audio file it was given. You can see the code in <a href="https://github.com/Darep/simo-soundboard/blob/master/app/components/play-button.js">https://github.com/Darep/simo-soundboard/blob/master/app/components/play-button.js</a>.</p>
<h3>Deployment with secrets</h3>
<p><a href="https://github.com/ember-cli-deploy/ember-cli-deploy">ember-cli-deploy</a> is another tool that I really like. It’s a “root” addon for creating a deployment pipeline. Basically, you stack a bunch of addons on top of it and they are run on deploy. I wanted to deploy the soundboard onto my cheap RamNode server so I went with rsync and ember-cli-rsync.</p>
<p>Secrets such as passwords, encryption keys and access keys should not be checked into the source code repository. At least not in plain text. I still like to have the secrets in the repo so I encrypt them with <a href="https://github.com/Shopify/ejson">EJSON</a>. It’s a Go app/Ruby gem by Shopify and I’ve been using it for a while. I would love to have a JS version of the gem for these JS based apps but none exist so far.</p>
<p>EJSON works simply by encrypting a given JSON file into “encrypted JSON” using a certain private key. Later you can use the same private key to decrypt the EJSON back to regular JSON. I wrote a <a href="https://github.com/Darep/simo-soundboard/blob/master/config/secrets.js">simple Node.js script to decrypt EJSON</a> which I use in this project as well. It requires the Ruby ejson gem, sadly.</p>
<p>After you have the secrets you can actually deploy. Running <code>ember deploy production</code> will walk through the ember-cli-deploy chain: build according to <a href="https://github.com/Darep/simo-soundboard/blob/master/ember-cli-build.js">build config</a>, create some manifest & revision data, and finally transfer the files to the destination host & directory specified in my secrets.ejson.</p>
<h3>Testing in production</h3>
<p>After I deployed the app to my server I noticed a usability problem related to bandwidth: there was no indication in the UI (like a loading gif) when a sound clip was being downloaded in the background. The user was just left there hanging wondering if something was going to happen soon. I know Chrome has a network throttling feature and I do use it, but I rarely remember to use it while developing unless I know I’m e.g. fixing a network latency related problem. So deploying and testing in the real production environment revealed a bug I hadn’t thought of. It’s good to deploy early and often to catch stuff like this.</p>
<figure class="center"><a href="/uploads/2016/05/soundboard-clip-loading-c0752b51.gif" class="img-wrap"><img src="/uploads/2016/05/soundboard-clip-loading-c0752b51.gif" alt="Animation of a clip playing" onload="this.parentNode.parentNode.className += ' show';" width="320" height="207" /></a></figure>
<p>And there you have it. Finished soundboard. “Vois hakkee Vammalasta Kossun” as our friend Simo once said.</p>
I'm a digital nomadhttp://ajk.fi/2016/im-a-digital-nomad/2016-04-02T00:00:00+03:002025-05-19T17:12:01+00:00AJ Kovalainen<p>In September 2015, my wife and I hopped onto Finnair’s wings. The plane would take us from the autumn-stricken Helsinki to Singapore. A week long holiday in tropic after no summer holidays sounded good to me. Seven days of sweating and air-conditioned...</p><p>In September 2015, my wife and I hopped onto Finnair’s wings. The plane would take us from the autumn-stricken Helsinki to Singapore. A week long holiday in tropic after no summer holidays sounded good to me. Seven days of sweating and air-conditioned shopping malls later, we hopped over to Australia. There we would spend the next 6 months or so working as a ‘<a href="https://en.wikipedia.org/wiki/Digital_nomad">digital nomad</a>.’ We are already 6 months in and it’s been great!</p>
<figure class="center"><a href="/uploads/2016/04/working-remotely-f3e4e4c3.jpg" class="img-wrap"><img src="/uploads/2016/04/working-remotely-f3e4e4c3.jpg" alt="Me working from home" onload="this.parentNode.parentNode.className += ' show';" width="1800" height="1283" /></a></figure>
<p>The idea for this trip came to me in 2009. At the time I was working as an IT Trainee at UPM, a global forest industry company. I enjoyed working with this Australian bloke and somehow we all started joking around about me moving to Australia to work on UPM’s IT. The “joke” stuck with me and I started saving money for the trip. Saving is easy, but saving to stay in Australia for several months is not easy. I left UPM in 2010 and didn’t feel like going back to work there. So my plan was to find a job at an Australian company, but in the end I happened to find something different: in 2013 I got a remote-friendly position at Flockler and could live anywhere with Internet.</p>
<p>We bought plane tickets for all the major flights at the start of May 2015, 4 months before leaving for the trip. HEL→SIN, SIN→DRW, BNE→NRT, and NRT→HEL<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. The next day we started selling our stuff and gave notice on our lease. Getting rid of all that stuff felt so good! Right now my belongings consist of my Macbook, a camera, miscellaneous computer stuff (like cables, a mouse & keyboard), and a suitcase full of clothes. And I feel good about owning so little even though I could do with less clothes, hehe.</p>
<p>So we flew to Singapore. Then we hopped to Darwin, the north-most big city of Australia and spent another week on holiday there. After Darwin we flew straight down the middle of Australia to Adelaide. Adelaide was a lovely place, we were there for 12 days and I worked at Cocolat café through most of that. From Adelaide it was a 1 hour flight to Melbourne where we spent 3 months. Melbourne is amazing, probably my favorite city in the world! Then I took another week of holidays to travel via Wagga Wagga & Canberra to Sydney where we stayed for 1 month. I met with an old university friend and worked from their office for a few days. We took an extended weekend trip to get to Brisbane through Byron Bay, and now we are in Brisbane. We will be here for 3 months.</p>
<figure class="center"><a href="/uploads/2016/04/us-8e6ffe9a.jpg" class="img-wrap"><img src="/uploads/2016/04/us-8e6ffe9a.jpg" alt="Noora and me in Gold Coast" caption="Noora and me in Gold Coast. Photo by <a href="http://www.heijastuspinta.fi/" target="_blank">Maria Morri</a>" onload="this.parentNode.parentNode.className += ' show';" width="960" height="724" /></a><figcaption>Noora and me in Gold Coast. Photo by <a href="http://www.heijastuspinta.fi/" target="_blank">Maria Morri</a></figcaption></figure>
<p>I’m not sure how to put the experience in words, but I’ll say this: trying to work while moving from city to city every week or few days is not easy. I full-heartedly recommend staying in one place for at least a month, preferably several. Slow travel. Suits me perfectly.</p>
<p>Anyways. I just wanted to drop a quick memo/update on what’s been going on. Let me know if you’d like to know details about stuff, like living arrangements, expenses and so on!</p>
<p>P.S. If you’re fluent with Finnish, check out our <a href="http://sites.flockler.com/suuri-seikkailu">travel blog</a>.</p>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>We’re gonna make a one month stopover in Japan before flying back to Finland <a href="#fnref1" rev="footnote">↩</a></p>
</li>
</ol>
</div>
The Recipe for the Worlds Largest Rails Monolith by Akira Matsudahttp://ajk.fi/2015/summary-on-amatsudas-rails-monolith-talk/2015-06-01T00:00:00+03:002025-05-19T17:12:01+00:00AJ Kovalainen<p>Akira Matsuda gave <a href="https://www.youtube.com/watch?v=naTRzjHaIhE">a really good talk</a> on some of the problems that CookPad has run into with their quite sizable Rails app:</p>
<ul>
<li><p>300 app servers, deploys are slow (~20min) => replaced capistrano with a handmade deploy program (<a href="https://github.com/sorah/mamiya">mamiya</a>) which deploys in...</p></li>
</ul><p>Akira Matsuda gave <a href="https://www.youtube.com/watch?v=naTRzjHaIhE">a really good talk</a> on some of the problems that CookPad has run into with their quite sizable Rails app:</p>
<ul>
<li><p>300 app servers, deploys are slow (~20min) => replaced capistrano with a handmade deploy program (<a href="https://github.com/sorah/mamiya">mamiya</a>) which deploys in 1 min</p></li>
<li><p>1000+ models, 30 databases, ActiveRecord is choking => read / write splitting, handmade ActiveRecord adapter for this (<a href="https://github.com/eagletmt/switch_point">switch_point</a>)</p></li>
<li><p>Tests take 5 hours<br/>
=> execute rspecs distributedly (<a href="https://github.com/cookpad/rrrspec">rrrspec</a>)<br/>
=> use a beefy, spot instance server to run tests. Cheap.<br/>
=> database_cleaner is slow with 1000+ tables => <a href="https://github.com/amatsuda/database_rewinder">database_rewinder</a></p></li>
<li><p>ActiveRecord migrations take forever to execute => <a href="https://github.com/winebarrel/ridgepole">ridgepole</a></p></li>
<li><p>Big rails app with big team results in code conflicts => created a rapid prototyping framework for rails (<a href="https://github.com/cookpad/chanko">chanko</a>)</p></li>
<li><p>Upgrading rails: created a response verification tool (<a href="https://github.com/cookpad/kage">kage</a>)</p></li>
</ul>
<p>Conclusion: Monolithic apps can scale, you don’t have to split it into many apps, eventho' microservices are really hot these days. Microservices bring their own problems and are not a silver bullet.</p>
Writing Fast Ruby by Erik Michaels-Oberhttp://ajk.fi/2014/writing-fast-ruby/2014-11-24T00:00:00+02:002025-05-19T17:12:01+00:00AJ Kovalainen<p>Good tips for optimizing your Ruby code. Remember though, premature optimization is the root of all evil!</p>
<p>Good tips for optimizing your Ruby code. Remember though, premature optimization is the root of all evil!</p>
Cache bustinghttp://ajk.fi/2014/cache-busting/2014-08-30T00:00:00+03:002025-05-19T17:12:01+00:00AJ Kovalainen<p>Caching CSS, JS, images and other website resources on the client is a standard for quality websites. If you want your site to be fast, you should be doing browser caching using <code>ETag</code> and <code>Cache-control</code> or <code>Expires</code> headers. If you are not yet caching...</p><p>Caching CSS, JS, images and other website resources on the client is a standard for quality websites. If you want your site to be fast, you should be doing browser caching using <code>ETag</code> and <code>Cache-control</code> or <code>Expires</code> headers. If you are not yet caching your website’s assets client-side, hit the <a href="https://developers.google.com/speed/docs/best-practices/caching">Google’s performance guide</a> for in-depth info.</p>
<p>Unfortunately, caching creates a problem. When you update the CSS, JS, or other resources, the user’s <strong>browser won’t download the updated files until the specified caching period is over</strong>. For CSS and JS, I usually set the caching period to be 1 year. Without cache busting, the user would have to wait 1 year or push refresh (aka. F5) to see the changes. And users won’t go around pushing F5 on any website they visit. That’s just silly :)</p>
<p>Luckily invalidating (or busting) cached website resources, such as CSS & JS, is not hard: <strong>serve the asset under a new, unique name.</strong></p>
<p>For example, if your CSS file was previously called <code>style.css</code>, you can rename the new version to <code>style-v2.css</code> and change the <code>href</code> of <code><link></code> to <code>style-v2.css</code> in your HTML manually.</p>
<h3>Automatic cache busting</h3>
<p>Renaming the assets everytime manually (as mentioned above) is doable if the project is small and you have the nerves. But it’s actually simple to automate.</p>
<p>Many Web frameworks – such as <a href="http://rubyonrails.org/">Ruby on Rails</a> – actually already provide automatic cache busting. If you’re using such a framework, you only have to configure it. There are also libraries and tools made for busting the cache. <a href="https://developers.google.com/speed/pagespeed/mod">mod_pagespeed</a> is one. I’ve used it successfully in the past for specifically this.</p>
<p>If you want to create your own automatic simple cache busting, I’ll explain my technique for automatic cache busting with WordPress and PHP.</p>
<h3>How to: Automatic cache busting in WordPress</h3>
<p>First of all, I have my asset (a CSS file) located at <code>/wp-content/themes/ajk/css/main.css</code>.</p>
<p>Add this <code>auto_version()</code> function into <code>functions.php</code> of your theme:</p>
<script src="https://gist.github.com/Darep/4627661.js"></script>
<p>Add a <code><link></code> to the CSS file into the WordPress theme’s <code>header.php</code> with <code>auto_version()</code> like this:</p>
<div class="highlight"><pre class="highlight php"><code><span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"</span><span class="cp"><?php</span> <span class="k">echo</span> <span class="nf">auto_version</span><span class="p">(</span><span class="nf">get_template_directory_uri</span><span class="p">()</span> <span class="mf">.</span> <span class="s1">'/css/main.css'</span><span class="p">);</span> <span class="cp">?></span><span class="s">"</span><span class="nt">></span>
</code></pre></div>
<p>And you should see this in your HTML source:</p>
<div class="highlight"><pre class="highlight html"><code><span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"/wp-content/themes/ajk/css/main.1361054840.css"</span><span class="nt">></span>
</code></pre></div>
<p>See that <code>1361054840</code>? That’s a unique identifier. It will change everytime the file changes.</p>
<p>But this isn’t enough, this alone won’t work. This won’t load our CSS at all, because a CSS file with numbers like that doesn’t exist.</p>
<p>Add a rewrite rule to a <code>.htaccess</code> file (Apache only):</p>
<div class="highlight"><pre class="highlight conf"><code><span class="c"># CSS/JS auto-versioning
</span><span class="n">RewriteEngine</span> <span class="n">On</span>
<span class="n">RewriteRule</span> ^(.*)\.[\<span class="n">d</span>]{<span class="m">10</span>}\.(<span class="n">css</span>|<span class="n">js</span>)$ $<span class="m">1</span>.$<span class="m">2</span> [<span class="n">L</span>]
</code></pre></div>
<p><em>(Note: I only have <code>(css|js)</code> written on the <code>RewriteRule</code> line there, but you should also cache and cache bust images, webfonts and so forth)</em></p>
<p>Now when the browser asks for <code>main.1361054840.css</code> Apache will serve the <code>main.css</code> file!</p>
<h3>How to: Automatic cache busting in other environments</h3>
<p>If you understand PHP and Apache rewrite rule syntax, you can easily port this technique to other platforms. A co-worker recently did this for a .NET project based on the description above:</p>
<ol>
<li>He created a C# version of the <code>auto_version()</code> shown above</li>
<li>He then created a <code>HttpHandler</code> in C#/.NET for recognizing the unique identifier and serving the actual resource file</li>
</ol>
<h2>Some notes</h2>
<h3>Build process busting</h3>
<p>If you happen to have a build process for your project, changing the asset’s name and updating the URLs could be done in the build phase. No need to waste CPU cycles on-demand, like with the <code>.htaccess</code> method or a <code>HttpHandler</code>. For example, <a href="http://rubyonrails.org/">Ruby on Rails</a> has a task for precompiling the assets, which will create “copies” of the asset under a new, unique name.</p>
<h3>Hash instead of timestamp</h3>
<p><a href="https://developers.google.com/speed/docs/best-practices/caching">Google’s guide for optimizing the cache</a> tells you that a hash is more reliable than a last modified timestamp. The timestamp method is easier to implement, but timestamps can be wrong on different systems, or may not even get updated when you deploy, or update, or whatever… So if you want to go pro, you should definitely use a hash instead of the last modified timestamp. My auto_version() is just a simple example and it gets the job done for me.</p>
<h3>Query strings</h3>
<p>Some people suggest adding a query string to the resource URL. Like here:</p>
<div class="highlight"><pre class="highlight html"><code><span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"/css/styles.css?v2"</span><span class="nt">></span>
</code></pre></div>
<p>Or:</p>
<div class="highlight"><pre class="highlight html"><code><span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"/css/styles.css?1234567890"</span><span class="nt">></span>
</code></pre></div>
<p>This will definitely bust the cache, but it might have some unwanted consequences: atleast some proxies will not cache URLs that have query strings in them.</p>
<h2>Summary</h2>
<p>Pretty much every website should be optimized for speed. Especially considering the rising mobile devices usage these days. Browser caching is one of the ingredients for speed, but it creates the problem of “how-to invalidate the cache”. And this is easy: rename the cached resources & optionally automate this renaming.</p>
<p>I’m happy to take on any critique, comments, suggestions and the sort! <a href="https://twitter.com/Darep">Send me a tweet</a> or comment below.</p>