<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Bohr In</title>
    <atom:link href="/feed.xml" rel="self" type="application/rss+xml"/>
    <link>https://bohr.in//</link>
    <description>Words and photos from another internet nerd</description>
    <pubDate>Sun, 14 Mar 2021 06:49:15 +0000</pubDate>
    
      <item>
        <title>Check Out GitHub PRs Locally</title>
        <link>/2020/03/05/Check-Out-Github-PRs-Locally/</link>
        <guid isPermaLink="true">/2020/03/05/Check-Out-Github-PRs-Locally/</guid>
        <description>&lt;p&gt;I‘m a big believer in code reviews. When I’m trying to review a PR on GitHub, I almost always want to check out the code locally on my computer, so I can open it up in an IDE. This is easy to do, but unfortunately, it’s not commonly documented. You can always check the branch behind the PR out by name, but I find it easier to use the PR number. It’s also easier to do this as part of a larger script. Instructions to set this up are below.&lt;/p&gt;

&lt;p&gt;Open the &lt;code class=&quot;highlighter-rouge&quot;&gt;.git/config&lt;/code&gt; file from the root of the repo in a text editor. Find the section that looks like this (note that the value of &lt;code class=&quot;highlighter-rouge&quot;&gt;url&lt;/code&gt; will be different for you):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[remote &quot;origin&quot;]
	url = git@github.com:surya-soft/Kedwig.git
	fetch = +refs/heads/*:refs/remotes/origin/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add this line (this will not change, regardless of what your &lt;code class=&quot;highlighter-rouge&quot;&gt;url&lt;/code&gt; is):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to the end of it, to make it look like so:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[remote &quot;origin&quot;]
	url = git@github.com:surya-soft/Kedwig.git
	fetch = +refs/heads/*:refs/remotes/origin/*
	fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save the file.&lt;/p&gt;

&lt;p&gt;Run &lt;code class=&quot;highlighter-rouge&quot;&gt;git fetch&lt;/code&gt;. You will now have refs to each PR by number. To check out PR 1, you can run &lt;code class=&quot;highlighter-rouge&quot;&gt;git checkout origin/pr/1&lt;/code&gt;. This will check out the PR in a detached head state. Replace &lt;code class=&quot;highlighter-rouge&quot;&gt;1&lt;/code&gt; with the number of the PR you want to reivew, and you’re all set!&lt;/p&gt;
</description>
        <pubDate>Thu, 05 Mar 2020 14:16:26 +0000</pubDate>
      </item>
    
      <item>
        <title>Swift On Server 2019 Edition</title>
        <link>/2019/12/31/Swift-On-Server-2019-Edition/</link>
        <guid isPermaLink="true">/2019/12/31/Swift-On-Server-2019-Edition/</guid>
        <description>&lt;p&gt;Last year, I did a &lt;a href=&quot;https://www.youtube.com/watch?v=qpDiXZRADfE&quot;&gt;talk&lt;/a&gt; at try! Swift NYC on the state of Swift on Server in 2018. Since then, Swift on Server has evolved quite a bit. This blog post is my opinion on where Swift on Server stands at the end of 2019.&lt;/p&gt;

&lt;h2 id=&quot;progress&quot;&gt;Progress&lt;/h2&gt;

&lt;p&gt;In my talk last year, I pointed out several building blocks that were missing in the Swift on Server ecosystem. Of these, several have already been addressed. We now have &lt;a href=&quot;https://github.com/apple/swift-log&quot;&gt;Swift Log&lt;/a&gt;, &lt;a href=&quot;https://github.com/apple/swift-metrics&quot;&gt;Swift Metrics&lt;/a&gt;, &lt;a href=&quot;https://github.com/MrLotU/SwiftPrometheus/&quot;&gt;Swift Prometheus&lt;/a&gt;, and several other &lt;a href=&quot;https://swift.org/blog/sswg-update/&quot;&gt;building blocks&lt;/a&gt; in place.&lt;/p&gt;

&lt;h2 id=&quot;ibm&quot;&gt;IBM&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://swift.org/server/&quot;&gt;Swift Server Working Group&lt;/a&gt; recently &lt;a href=&quot;https://forums.swift.org/t/december-12th-2019/31735&quot;&gt;announced&lt;/a&gt; that IBM will no longer be working on Swift on Server. It isn’t yet clear what will happen to Kitura, but I think it’s safe to assume Kitura’s days are numbered.&lt;/p&gt;

&lt;p&gt;I believe this will be a substantial blow to the Swift on Server community. I had the good fortune to meet Chris and Ian at try! Swift. I’ve also had the privilege to get to know a few people who work on Swift on Linux right here in Bangalore. It’s unclear whether they will also be pulling back from the Swift community. These are great folks, and it’s rather unfortunate to hear that they will no longer be participating in the community.&lt;/p&gt;

&lt;p&gt;However, I must admit, this isn’t entirely surprising. Kitura’s approach to Swift on Server appeared for the most part to be to go head to head with Java, NodeJS, etc. This always felt like a mistake to me. Given the limited resources behind Swift on Server, it was always going to be incredibly unlikely that Swift would ever catch up to the long standing &amp;amp; thriving ecosystems that surround other server side languages, like Java, Ruby, Python, JavaScript, etc.&lt;/p&gt;

&lt;p&gt;So if Swift can’t really catch up to other ecosystems, why even bother trying?&lt;/p&gt;

&lt;h2 id=&quot;why-swift-on-server&quot;&gt;Why Swift on Server?&lt;/h2&gt;

&lt;p&gt;The most common argument I’ve heard that is that iOS developers already know Swift, and it would be easy for them  to transition to server programming. The second most common argument I’ve heard is that Swift on Server enables code sharing with iOS apps. In my opinion, these are both flawed arguments.&lt;/p&gt;

&lt;p&gt;While the programming language being used to write server code is definitely a factor, it is a relatively insignificant factor. The problems &amp;amp; frameworks being used to solve those problems, ultimately are a lot more important. iOS developers aren’t not working on server code because they have to use Ruby, or Python. They’re not writing server code because most of the knowledge &amp;amp; experience they’ve gained is useless. All that UIKit knowledge you gained the hard way - totally useless. On top of this, you need to learn a ton about the server side ecosystem. How do you do deployments? How do you monitor in production? How do you deal with concurrency? How do you debug performance issues? Gaining this knowledge &amp;amp; experience is a lot harder than learning a new programming language. Therefore, my belief is that this reason was never going to drive Swift on Server adoption.&lt;/p&gt;

&lt;p&gt;There are also multiple problems with the code sharing argument. First off, Swift still doesn’t officially run on Android, nor does it officially run on Windows, and as far as I’m aware, Swift’s WASM story still isn’t quite there. How many companies and teams do you know of that have only an iOS/macOS app, and a server, but no Android app, and no web app? It’s incredibly uncommon. Even if you’re on such a team that has only Apple front-ends, and a server component, what code would you realistically share? A few model objects? You could likely re-write those in a few hours or days. There’s not a lot of value in sharing this code. Besides, there’re better approaches to this sort of code sharing anyway: Protocol Buffers, gRPC, etc.&lt;/p&gt;

&lt;p&gt;Having said all that though, I am still bullish on Swift on Server. However, for Swift on Server to gain adoption, I think it’s going to have to bring something to the table for folks who’re already server side developers today. I think Swift has a few things going for it that few other languages do when it comes to server side development.&lt;/p&gt;

&lt;h3 id=&quot;memory-safety-without-garbage-collection&quot;&gt;Memory Safety Without Garbage Collection&lt;/h3&gt;

&lt;p&gt;Almost every popular server side language has both a VM/interpreter &amp;amp; garbage collection. While there are definitely advantages to both, they do have problems.&lt;/p&gt;

&lt;p&gt;Garbage collected environments are unpredictable. It is quite common to end up with GC problems that are incredibly hard to reproduce. It’s also often hard to figure out whether you have a garbage problem, or a garbage collection problem. Using languages like C/C++ which do not have garbage collection comes with a major downside: lack of memory safety. Swift (due to its use of ARC), provides a fantastic middle ground - memory safe, and predictable.&lt;/p&gt;

&lt;h3 id=&quot;fast-startup-time&quot;&gt;Fast Startup Time&lt;/h3&gt;

&lt;p&gt;VMs are also quite slow to start. For example, it is not uncommon for a typical Java application to take several seconds (sometimes even minutes) to start up. This was a non-issue in the past, when you expected to have huge machines that ran processes which ran for days (even months), but in a cloud native world, this is a real problem. For example, in server less functions, a VM is a deathblow.&lt;/p&gt;

&lt;h3 id=&quot;performance&quot;&gt;Performance&lt;/h3&gt;

&lt;p&gt;Swift is already quite fast &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, compared to languages like Ruby &amp;amp; Python for most use cases. It is also faster than Java in some cases. However, what excites me about Swift is that it can become an order of magnitude faster than most other languages. Swift’s type system, value types (with copy on write), static dispatch, the String APIs in the standard library, etc. have the potential to make Swift compete with a well tuned C program on performance. Unfortunately, that potential is not yet realized. Swift 5 &amp;amp; 5.1 bring brought some huge improvements though, and I’m optimistic about Swift competing on performance with systems programming languages in the near future.&lt;/p&gt;

&lt;h3 id=&quot;swift-nio&quot;&gt;Swift NIO&lt;/h3&gt;

&lt;p&gt;In a year, &lt;a href=&quot;https://github.com/apple/swift-nio&quot;&gt;Swift NIO&lt;/a&gt; has also moved forward quite a bit. I believe NIO is Swift on Server’s biggest asset. &lt;a href=&quot;https://vapor.codes&quot;&gt;Vapor&lt;/a&gt; has already adopted it in a big way. &lt;a href=&quot;https://github.com/vapor/postgres-nio&quot;&gt;Postgres-NIO&lt;/a&gt; has been accepted by the SSWG. There aren’t many (any?) robust non-blocking database drivers that are easy to use in other languages yet. NIO provides a base to build on - if the Swift on Server community can leverage it successfully to build high performance web frameworks, with non-blocking database drivers, I believe it will be an incredibly compelling reason for server side developers to start using Swift.&lt;/p&gt;

&lt;h2 id=&quot;competition&quot;&gt;Competition&lt;/h2&gt;

&lt;h3 id=&quot;rust&quot;&gt;Rust&lt;/h3&gt;

&lt;p&gt;In my opinion, Rust is the biggest competitor to the Swift on Server ecosystem. Rust is incredibly fast, memory safe, and is not garbage collected. It makes very similar tradeoffs on many fronts. The tooling ecosystem around it is quite mature as well. &lt;a href=&quot;https://tokio.rs&quot;&gt;Tokio&lt;/a&gt; is very similar to NIO, and has recently announced &lt;a href=&quot;https://tokio.rs/blog/2019-08-alphas/&quot;&gt;support&lt;/a&gt; for &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;await&lt;/code&gt;, which will be fantastic for developer ergonomics when higher level frameworks support it. Existing Rust frameworks are already much faster than Swift. While the war isn’t over yet, Rust has won several battles.&lt;/p&gt;

&lt;h3 id=&quot;kotlin&quot;&gt;Kotlin&lt;/h3&gt;

&lt;p&gt;The biggest hurdle with Swift &amp;amp; Rust, is that they are relatively recent, and the ecosystems around them are still quite immature. For example, if you want to write a Microsoft Excel file using Swift/Rust, there really isn’t a great library for that yet. If you need to connect to an Oracle or MS SQL database, there isn’t a good way to do that in Swift/Rust yet. Where Kotlin shines, is with its interop with Java. Being able to seamlessly integrate with Java (and the vast ecosystem around it) is incredibly powerful. This makes Kotlin fully viable as a server side language today for almost everyone. However, in the long run, unless Kotlin Native (and the ecosystem around it) emerges strongly, I believe Swift &amp;amp; Rust will bring substantial improvements to server side development to convince a lot of people to use them over Kotlin.&lt;/p&gt;

&lt;h2 id=&quot;wishlist&quot;&gt;Wishlist&lt;/h2&gt;

&lt;p&gt;Below are a few things I would like to see make Swift on Server viable:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Performance on par with (or better than) Rust.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;await&lt;/code&gt;. This is a huge boost to developer ergonomics when dealing with non-blocking code. A framework like Vapor would be so much nicer to use with &lt;code class=&quot;highlighter-rouge&quot;&gt;async&lt;/code&gt;/&lt;code class=&quot;highlighter-rouge&quot;&gt;await&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A solution/mitigation to &lt;code class=&quot;highlighter-rouge&quot;&gt;fatalError&lt;/code&gt; bringing down the entire process, instead of just killing a single request. For example, accessing an element in array that is out of bounds will result in the entire process dying, which could result in thousands of requests being dropped.&lt;/li&gt;
  &lt;li&gt;Robust non-blocking database drivers for popular relational databases (including databases like Microsoft SQL Server and Oracle, which are not open source).&lt;/li&gt;
  &lt;li&gt;Equivalent of &lt;a href=&quot;https://github.com/diesel-rs/diesel&quot;&gt;Diesel&lt;/a&gt; that supports all the above databases.&lt;/li&gt;
  &lt;li&gt;Robust connection pooling library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Update on 2020-01-04&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The folks at Vapor announced that Vapor Cloud is &lt;a href=&quot;https://docs.vapor.cloud/shutdown/&quot;&gt;shutting down&lt;/a&gt;. I don’t know what implication this has on the Vapor project (if any).&lt;/p&gt;

&lt;p&gt;If you have any thoughts, comments or concerns, please let me know! I’m &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt; on Twitter.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;https://github.com/TechEmpower/FrameworkBenchmarks &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 31 Dec 2019 08:30:00 +0000</pubDate>
      </item>
    
      <item>
        <title>A Codable Tale of Woe</title>
        <link>/2018/09/26/A-Codable-Tale-of-Woe/</link>
        <guid isPermaLink="true">/2018/09/26/A-Codable-Tale-of-Woe/</guid>
        <description>&lt;p&gt;I recently encountered a somewhat unusual Swift problem. I had a &lt;code class=&quot;highlighter-rouge&quot;&gt;struct&lt;/code&gt; that looked something like this:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Something&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I wanted to be able to construct one of these from a JSON response coming from a server. Obviously, I figured the easiest way to do this was to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Codable&lt;/code&gt;. So I did:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Something&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Codable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JSONDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decodedSomething&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Something&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jsonResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, I then realized that this server was using different keys, and as a result the call to &lt;code class=&quot;highlighter-rouge&quot;&gt;decode&lt;/code&gt; would fail. Here’s an example server response:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sV&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, to deal with that, I did this:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Something&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Codable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingKeys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingKey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sV&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JSONDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decodedSomething&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Something&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jsonResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And… everything was hunky dory.&lt;/p&gt;

&lt;p&gt;Except… it wasn’t. I had to also store a JSON representation of these &lt;code class=&quot;highlighter-rouge&quot;&gt;struct&lt;/code&gt;s on disk, and retrieve them later. I really did not want to use the same JSON representation as the server, because it looks ugly, and makes debugging annoying. I wanted to have the on-disk representation be:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;someValue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At first, I wasn’t really able to find a way to do this. It then occurred to me that I’d likely have to implement &lt;code class=&quot;highlighter-rouge&quot;&gt;encode(to encoder: Encoder)&lt;/code&gt; and it’s counterpart &lt;code class=&quot;highlighter-rouge&quot;&gt;init(from decoder: Decoder)&lt;/code&gt; to do this, so I attempted to. Unfortunately, that led me to another problem. I’d need to have different &lt;code class=&quot;highlighter-rouge&quot;&gt;CodingKeys&lt;/code&gt; enums for the server representation, and for my on-disk representation. But, even if I did have different &lt;code class=&quot;highlighter-rouge&quot;&gt;CodingKeys&lt;/code&gt;, how would I know which one to use with which &lt;code class=&quot;highlighter-rouge&quot;&gt;Encoder&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;Decoder&lt;/code&gt;? This also led me to a broader realization. Even if I tried to make my on-disk representation a Plist, instead of JSON, I’d still have to use the same &lt;code class=&quot;highlighter-rouge&quot;&gt;CodingKeys&lt;/code&gt;, which was suboptimal.&lt;/p&gt;

&lt;p&gt;So, I did what every good developer does, and googled for possible solutions to this problem, but did not find any. Then, I started reading the documentation hoping I’d find a way to solve this problem, and eventually came up with this solution:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decoderTypeKey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingUserInfoKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rawValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;decoderType&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoderTypeKey&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingUserInfoKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rawValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;encoderType&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONDecoder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JSONDecoder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decoderType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ServerDecoder&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;userInfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;decoderTypeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONDecoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoderType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONEncoder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JSONEncoder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoderType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ServerEncoder&quot;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;userInfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;encoderTypeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoderType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Something&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Codable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingKeys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingKey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerCodingKeys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingKey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sV&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Decoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;decoderType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoderTypeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoderType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONDecoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decoderType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;container&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;keyedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerCodingKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;container&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;keyedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Encoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoderType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoderTypeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoderType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encoderType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;container&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;keyedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerCodingKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;container&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;keyedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CodingKeys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;forKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;someValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;serverDecoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONDecoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;something&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serverDecoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Something&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jsonResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Output: Something(id: 1, someValue: &quot;foo&quot;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;serverEncoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ServerJSONEncoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serverEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Output: {&quot;id&quot;:1,&quot;sV&quot;:&quot;foo&quot;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;JSONEncoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Output: {&quot;id&quot;:1,&quot;someValue&quot;:&quot;foo&quot;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The basic idea here is that every &lt;code class=&quot;highlighter-rouge&quot;&gt;Encoder&lt;/code&gt; has a &lt;code class=&quot;highlighter-rouge&quot;&gt;userInfo&lt;/code&gt; dictionary, that you can put anything into. That same &lt;code class=&quot;highlighter-rouge&quot;&gt;userInfo&lt;/code&gt; dictionary is made available at the time of encoding or decoding. I choose to put in the “type” of encoder in there, and use that as a mechanism to determine the type of &lt;code class=&quot;highlighter-rouge&quot;&gt;Encoder&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;Decoder&lt;/code&gt;. This is what the &lt;code class=&quot;highlighter-rouge&quot;&gt;ServerJSONEncoder&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;ServerJSONDecoder&lt;/code&gt; subclasses do.&lt;/p&gt;

&lt;p&gt;Then, in the &lt;code class=&quot;highlighter-rouge&quot;&gt;init(from decoder: Decoder)&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;encode(to encoder: Encoder)&lt;/code&gt; methods I look for the existence of that key in the &lt;code class=&quot;highlighter-rouge&quot;&gt;userInfo&lt;/code&gt; dictionary. If it exists, and has a value I’m looking for, I use the appropriate &lt;code class=&quot;highlighter-rouge&quot;&gt;CodingKeys&lt;/code&gt; to encode or decode.&lt;/p&gt;

&lt;p&gt;And… everything is hunky dory again.&lt;/p&gt;

&lt;p&gt;Except… it isn’t.&lt;/p&gt;

&lt;p&gt;One problem with this solution is that it if I add another type of encoder/decoder, I now also have to update the &lt;code class=&quot;highlighter-rouge&quot;&gt;struct&lt;/code&gt; itself, which is not good.&lt;/p&gt;

&lt;p&gt;Second, there’s a whole bunch of repetition in the implementations of &lt;code class=&quot;highlighter-rouge&quot;&gt;init(from decoder: Decoder)&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;encode(to encoder: Encoder)&lt;/code&gt;. I haven’t yet found a way to avoid this duplication. The reason is because the type of &lt;code class=&quot;highlighter-rouge&quot;&gt;container&lt;/code&gt; changes based on which &lt;code class=&quot;highlighter-rouge&quot;&gt;CodingKey&lt;/code&gt; is used. So, I can’t pull &lt;code class=&quot;highlighter-rouge&quot;&gt;container&lt;/code&gt; out of the if. If you have any ideas on how to avoid this duplication, or another way to solve this problem, please let me know! I’m &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt; on Twitter.&lt;/p&gt;
</description>
        <pubDate>Wed, 26 Sep 2018 15:51:22 +0000</pubDate>
      </item>
    
      <item>
        <title>Testing Paper</title>
        <link>/2018/05/01/Testing-Paper/</link>
        <guid isPermaLink="true">/2018/05/01/Testing-Paper/</guid>
        <description>&lt;p&gt;I recently came across &lt;a href=&quot;https://inventitech.com/publications/2015_beller_gousios_panichella_zaidman_when_how_and_why_developers_do_not_test_in_their_ides.pdf&quot;&gt;this paper&lt;/a&gt;:   “When, How, and Why Developers (Do Not) Test in Their IDEs” written by Moritz Beller, Georgios Gousios, Annibale Panichella, and Andy Zaidman.&lt;/p&gt;

&lt;p&gt;Caveat: It doesn’t appear to be super recent &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, the sample size is not large (&amp;lt; 500 developers), and their data is gathered from Eclipse &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, so the conclusions drawn in the paper may need to be taken with a grain of salt. Having said that, I think the results are really interesting.&lt;/p&gt;

&lt;p&gt;I recommend reading the paper, but I’ve gathered some of the interesting parts below (with my commentary):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;developers rarely run their tests in the IDE&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Woah, no beating around the bush here.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TDD is not widely practiced. Programmers who claim to do it, neither follow it strictly nor for all their modifications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Seems obvious… TDD always seemed like a bit of a farce to me. There’s a good idea in there somewhere, but I think people take it way too far.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;software developers only spend a quarter of their work time engineering tests, whereas they think they test half of their time&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one’s interesting - I always thought it was a 1:1 ratio. That is, if I spend 4 hours writing production code, I spend 4 hours writing tests. I’ll have to find a way to get more stats on this for my team.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Observed behavior often contradicted survey answers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is not at all surprising - this is why I believe in &lt;a href=&quot;https://usetiming.com&quot;&gt;measuring real data&lt;/a&gt;, and not trusting that people can remember what they did.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The majority of projects and users do not practice testing actively.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not surprising, but damning.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Developers largely do not run tests in the IDE. However, when they do, they do it heftily.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This doesn’t seem to be a bad thing though:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;One reason why some developers do not execute tests in the IDE is that the tests would render their machine unusable, for example during the execution of UI tests in the Eclipse Platform UI project. The Eclipse developers push their untested changes to the Gerrit review tool and rely on it to trigger the execution of the tests on the continuous integration server. In such a scenario, the changes only become part of the “holy repository” if the tests execute successfully. Otherwise, the developer is notified via email. Despite the tool overhead and a possibly slower reaction time, our low results on test executions in the IDE suggest that developers increasingly prefer such more complex setups to manually executing their tests in the IDE. IDE creators could improve the continuous integration server support in future releases to facilitate this new workflow of developers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tests run in the IDE take a very short amount of time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;we found that testing in the IDE happens fast-paced. Most tests finish within five seconds, or less.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is definitely a problem I’ve faced before. Nobody likes &lt;a href=&quot;https://xkcd.com/303/&quot;&gt;waiting on a computer&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tests and production code do not co-evolve gracefully.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not surprising, but pretty damning.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Developers frequently select a specific set of tests to run in the IDE. In most cases, developers execute one test.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This resonates with me. We use gradle to build, and IntelliJ as our IDE. Unfortunately they don’t play very nice with each other and occasionally, I can’t run tests from IntelliJ. This usually means I don’t run tests at all, because running one test from gradle is a pain.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Bottom line, this paper paints a pretty horrifying picture of testing in software development. I can’t say I’m surprised by this. Most code I’ve encountered isn’t tested properly, and yet most of it seems to mostly work. This isn’t to say that I think testing isn’t a worthwhile activity. I still do believe it’s a valuable tool. However, it is perhaps also worthwhile to think about what degree of testing is actually required instead of being dogmatic about TDD, BDD, etc.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Looks like it was published in 2015? &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;Eclipse is a terrible IDE, so I wouldn’t expect it to make testing (or anything, really) easy. It’s also mostly only used for Java development. Perhaps other languages would have different results? &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 01 May 2018 16:02:26 +0000</pubDate>
      </item>
    
      <item>
        <title>Code Review On BitBucket</title>
        <link>/2018/04/23/Code-Review-On-Bitbucket/</link>
        <guid isPermaLink="true">/2018/04/23/Code-Review-On-Bitbucket/</guid>
        <description>&lt;p&gt;My team recently started using BitBucket to collaborate on a project. We didn’t make the choice - it was made for us. Historically, we’ve used GitHub. However, since we were going to be using it, I figured we might as well make the most of it. On the surface, BitBucket seems like a good deal. It’s got pipelines and deployments built in. Being made by Atlassian, you’d think that it integrates better with JIRA than any other source control system. It’s also significantly cheaper than GitHub. All of this sounded great, until… Code Review.&lt;/p&gt;

&lt;p&gt;But, before I start complaining, a bit of background about our workflow. We have an organization on BitBucket. That organization has a repository (let’s call it &lt;code class=&quot;highlighter-rouge&quot;&gt;Repo&lt;/code&gt;). Each person on the team, forks &lt;code class=&quot;highlighter-rouge&quot;&gt;Repo&lt;/code&gt;, creates a branch on their fork, does some work, and files a PR. After this, at least one other member of the team has to review the PR, and provide constructive feedback. The reviewer(s) and author may go back and forth a few times until they both agree the PR is good to go. When things are good to go, we merge the PR, and we’re done.&lt;/p&gt;

&lt;p&gt;This workflow worked great for us when we were on GitHub. There’s one huge problem with BitBucket though - you can’t seem to be able to check out a PR locally! BitBucket’s UI for review is fine, but it is no substitute for being able to look at the code in your IDE, with a debugger on standby. On GitHub checking out a PR locally was &lt;a href=&quot;https://help.github.com/articles/checking-out-pull-requests-locally/&quot;&gt;trivial&lt;/a&gt;. I was really quite baffled when the same process didn’t work on BitBucket.&lt;/p&gt;

&lt;p&gt;So I went looking to Google, looking for help. I came across &lt;a href=&quot;https://www.atlassian.com/git/articles/pull-request-proficiency-fetching-abilities-unlocked&quot;&gt;this post&lt;/a&gt; that suggested that I had to make a minor change to the GitHub way, and things would work. Cool! Except… Nope. Didn’t work. &lt;a href=&quot;https://twitter.com/AskAtlassian/status/987424765714432000&quot;&gt;Turns out&lt;/a&gt;, that only works on an older version of BitBucket Server (previously called Stash). Ugh.&lt;/p&gt;

&lt;p&gt;So not knowing what to do, I filed a support ticket to Atlassian asking them if they had a solution to this problem. The support person responded (very politely) with a link to this &lt;a href=&quot;https://confluence.atlassian.com/bbkb/how-to-locally-fetch-and-checkout-a-pull-request-724402529.html&quot;&gt;page&lt;/a&gt;. Unfortunately… that doesn’t work either, for several reasons.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;They ask you to hover over a DOM element, wait for the browser to show the URL it points to, and use that for the next step. Wait what!? That sounds ridiculous!&lt;/li&gt;
  &lt;li&gt;Turns out, the DOM element that article refers to doesn’t even point to a link anymore.&lt;/li&gt;
  &lt;li&gt;Even if I could manage to predict the URL, the URL will be an https url, and we don’t use https to work with git, we prefer ssh.&lt;/li&gt;
  &lt;li&gt;Even if you’re willing to use https, you’d still need to have read access to the forked repo (which unlike GitHub, BitBucket does not set up by default when someone forks your repo).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Wow. Just… Wow.&lt;/p&gt;

&lt;p&gt;Then I figured, there must definitely be some way of downloading a patch file of the PR? GitHub has a &lt;a href=&quot;https://coderwall.com/p/6aw72a/creating-patch-from-github-pull-request&quot;&gt;way&lt;/a&gt; to do this. Turns out, nope.&lt;/p&gt;

&lt;p&gt;The Atlassian support person later pointed me to this &lt;a href=&quot;https://bitbucket.org/site/master/issues/5814/reify-pull-requests-by-making-them-a-ref&quot;&gt;issue&lt;/a&gt; and said they’d be fixing this issue soon. But, I looked a little closer at the issue, and it’s been open since, wait for it… &lt;strong&gt;2012&lt;/strong&gt;. &lt;em&gt;6 years!&lt;/em&gt; Good lord!&lt;/p&gt;

&lt;p&gt;This is when I started seriously considering wasting the absurd amount of time it’d take to get us off BitBucket, and back on to GitHub. Before I gave up hope though, I figured it was worth looking into the BitBucket API to see if there was some way to get this to work. Fortunately, that did not let me down. There’s an &lt;a href=&quot;https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Busername%7D/%7Brepo_slug%7D/pullrequests/%7Bpull_request_id%7D/patch&quot;&gt;endpoint&lt;/a&gt; that allows you to get a PR as a patch.&lt;/p&gt;

&lt;p&gt;I set about trying to get this to work, and quickly ran across the &lt;a href=&quot;https://developer.atlassian.com/bitbucket/api/2/reference/meta/authentication&quot;&gt;hell hole&lt;/a&gt; that is OAuth2. I was about to give up again, when I noticed this section way at the bottom of the page:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Basic auth
Basic HTTP Authentication as per RFC-2617 (Digest not supported). Note that Basic Auth with username and password as credentials is only available on accounts that have 2-factor-auth / 2-step-verification disabled. If you use 2fa, you should authenticate using OAuth2 instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cool! I wasn’t using 2fa anyway, so time to get this working. After a bit of finagling, I came up with this snippet which I stuck into my &lt;code class=&quot;highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;co_bb_pr&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    curl &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;USERNAME&amp;gt;:&amp;lt;PASSWORD&amp;gt;&quot;&lt;/span&gt; https://bitbucket.org/api/2.0/repositories/&amp;lt;ORG&amp;gt;/&amp;lt;REPO&amp;gt;/pullrequests/&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;/patch &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;.patch &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; git apply &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;.patch
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I can now run:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;co_bb_pr 27
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And have a PR 27 checked out locally.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Finally&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you have a better way of doing this, please let me know! I’m &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Mon, 23 Apr 2018 15:42:58 +0000</pubDate>
      </item>
    
      <item>
        <title>Rosco</title>
        <link>/2018/01/19/Rosco/</link>
        <guid isPermaLink="true">/2018/01/19/Rosco/</guid>
        <description>
</description>
        <pubDate>Fri, 19 Jan 2018 08:10:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Kotlin Data Class Constructor Problem Follow Up</title>
        <link>/2017/08/18/Kotlin-Data-Class-Constructor-Problem-Followup/</link>
        <guid isPermaLink="true">/2017/08/18/Kotlin-Data-Class-Constructor-Problem-Followup/</guid>
        <description>&lt;p&gt;I wrote about a &lt;a href=&quot;/2017/08/15/Kotlin-Data-Class-Constructor-Problem/&quot;&gt;problem I was having with Kotlin data class constructors&lt;/a&gt; a few days ago. I sent it to a few people and asked for thoughts on how they might address the issue.&lt;/p&gt;

&lt;p&gt;A few people proposed a few different possible solutions to the problem. I thought I’d write them down here, as well as what I ended up doing.&lt;/p&gt;

&lt;h1 id=&quot;make-constructor-private&quot;&gt;Make constructor private&lt;/h1&gt;

&lt;p&gt;One proposed solution was to make the constructor private and instead have a factory method:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;data class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constructor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the face of it, this looks like a good solution. However, there is a problem with it that IDEA very nicely warns you about: the &lt;code class=&quot;highlighter-rouge&quot;&gt;copy&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Even if you make the constructor private, it is still exposed by the &lt;code class=&quot;highlighter-rouge&quot;&gt;copy&lt;/code&gt; method that is generated by the compiler.&lt;/p&gt;

&lt;p&gt;You could still write something like this:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randomUUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo@bar.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FOO@bar.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which is problematic.&lt;/p&gt;

&lt;h1 id=&quot;make-fields-private&quot;&gt;Make fields private&lt;/h1&gt;

&lt;p&gt;Another proposed solution looks like this:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;data class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;_emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’re unfortunately a couple of problems with this as well. First, every time you read &lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;emailId&lt;/code&gt; you end up creating a whole new object, which means more garbage. This seems unnecessarily wasteful.&lt;/p&gt;

&lt;p&gt;Second, the call site becomes ugly:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randomUUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Foo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_emailId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo@bar.com&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Admittedly, this is not a problem if you don’t use named parameters. However, named parameters are super useful, especially when you have model objects (the obvious use case for data classes) with &amp;gt; 5 parameters. It significantly reduces the likelihood of making a mistake.&lt;/p&gt;

&lt;h1 id=&quot;eventual-non-solution&quot;&gt;Eventual non solution&lt;/h1&gt;

&lt;p&gt;Eventually, I wasn’t able to find any solutions to this problem that still allowed me to use data classes. So I ended up not using a data class, and instead writing out all the boilerplate necessary:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;companion&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Have IDEA generate this for me&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Remember to re-generate it everytime I add a property to this class&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hashCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Have IDEA generate this for me&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Remember to re-generate it everytime I add a property to this class&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Unfortunately IDEA cannot generate this for me, so type it out&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// I might eventually create a live template for this&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not ideal, but it works…&lt;/p&gt;

&lt;p&gt;If you have a better solution in mind, please do let me know: &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt;!&lt;/p&gt;
</description>
        <pubDate>Fri, 18 Aug 2017 09:53:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Subscriptions</title>
        <link>/2017/08/17/Subscriptions/</link>
        <guid isPermaLink="true">/2017/08/17/Subscriptions/</guid>
        <description>&lt;p&gt;Recently, a lot of iOS and macOS apps have switched from a pay once and use until next major version pricing model to a subscription model. The latest example I’m aware of is &lt;a href=&quot;https://ulyssesapp.com/blog/2017/08/ulysses-switches-to-subscription/&quot;&gt;Ulysses&lt;/a&gt;. I don’t use Ulysses, but one of the apps I use that has also made the switch is &lt;a href=&quot;https://1password.com&quot;&gt;1Password&lt;/a&gt;. There’s been a lot of discussion about this all over the internet.&lt;/p&gt;

&lt;p&gt;Here’s a quick summary of both sides of the debate. Some people think subscriptions for iOS and macOS apps are good - they provide a way to increase revenue, and have it be more predictable. Other people are of the opinion that subscriptions do not make sense for “apps” - people are ok with paying a subscription fee for something like Dropbox, but not for an app like Ulysses. I thought that the discussion on &lt;a href=&quot;https://www.coreint.org/2017/08/episode-293-this-might-make-sense-to-you/&quot;&gt;the latest CoreInt episode&lt;/a&gt; put forth both sides of this debate much better than I can. I highly recommend giving it a listen.&lt;/p&gt;

&lt;p&gt;However, I feel like there are some factors I haven’t seen discussed yet (perhaps they have been, and I just haven’t seen it).&lt;/p&gt;

&lt;h1 id=&quot;total-cost-of-ownership&quot;&gt;Total cost of ownership&lt;/h1&gt;

&lt;p&gt;Most apps switching from a paid upgrades model to a recurring subscription model are also raising their total cost of ownership at the same time. Even if the amount of money you pay up front is lower, your total cost of ownership is way higher.&lt;/p&gt;

&lt;p&gt;I’ve been a 1Password user for over 5 years now. During that time, I’ve spent around $75 on 1Password for Mac, and iOS. I use Dropbox to sync my passwords, but I don’t pay for Dropbox specifically for 1Password.&lt;/p&gt;

&lt;p&gt;If you think about the total cost of ownership over 5 years, with 1Password’s subscription model, which is $2.99 per month (billed annually), that’s $180. That is more than 2 times my previous total cost of ownership!&lt;/p&gt;

&lt;p&gt;So far, I haven’t really seen anyone make the switch from paid upgrades to subscriptions without also dramatically increasing the total cost of ownership. I’d be very interested to see if the backlash against subscriptions is as high if the total cost is no different, or lower.&lt;/p&gt;

&lt;p&gt;The only things I can think of that reduce or maintain total cost of ownership are all content subscriptions. Things like Netflix, Apple Music, etc. If I watch 2 or 3 movies a month that are available on Netflix, I’ve reduced my price compared to renting them on iTunes (this is partly why I pay for Netflix). Having said that, content and software are really different beasts, so I’m not sure this really applies.&lt;/p&gt;

&lt;h1 id=&quot;subscriptions-are-good-because-developers-wont-hold-back-features&quot;&gt;Subscriptions are good because developers won’t hold back features&lt;/h1&gt;

&lt;p&gt;The argument here is that in the paid upgrades pricing model, developers have to hold back features that are ready for the next major release in order to make paying for an upgrade worth while.&lt;/p&gt;

&lt;p&gt;I think this has theory has already proven itself to be invalid. Great example: Adobe Lightroom. In the last 2 years, Lightroom has added virtually no meaningful new features. I’ve paid adobe $240 over that period for absolutely &lt;em&gt;nothing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This leads me to my next point…&lt;/p&gt;

&lt;h1 id=&quot;comparisons-to-adobe-office-365-etc&quot;&gt;Comparisons to Adobe, Office 365, etc.&lt;/h1&gt;

&lt;p&gt;A lot of people are pointing to subscriptions like Adobe’s Creative Cloud, and Microsoft’s Office 365 as successful switches to subscription based models. However, I believe this is a misleading comparison to make.&lt;/p&gt;

&lt;p&gt;There are no alternatives to Adobe Creative Cloud, and Microsoft Office for the vast majority of people using it. Think about it - what would a Lightroom user switch to? What would a Photoshop user switch to? What would a Microsoft Office user switch to? You could say Apple Photos, Pixelmator, Acorn, or iWork, but really, in a professional context, none of those are real options. Even if you’re willing to switch, the people you work with won’t.&lt;/p&gt;

&lt;p&gt;So even if Adobe and Microsoft do atrocious things like having a garbage installer, not allowing you to unsubscribe without making 12 phone calls, or charging you outrageous amounts of money for absolutely nothing in return, you’re still going to have to pay them - you simply have no choice.&lt;/p&gt;

&lt;p&gt;Ulysses, 1Password, etc. however, are not in that category. For most users, there are loads of alternatives.&lt;/p&gt;

&lt;h1 id=&quot;so-when-do-subscriptions-work&quot;&gt;So when do subscriptions work?&lt;/h1&gt;

&lt;p&gt;I think Manton was on to something on CoreInt when he said people are willing to pay for apps with a server component because there are real costs to running servers. However, I’m not convinced that most people really understand the details of how software is built, and that servers cost money, etc. I like to think of it more as a difference between products and services.&lt;/p&gt;

&lt;p&gt;Let’s take software out of the picture for a moment. Would you pay once a week to have someone clean your house? You would. Would you pay once a week to have a vacuum cleaner in your house? Highly unlikely!&lt;/p&gt;

&lt;p&gt;In summary, I believe that subscriptions are great for services. They are a much harder sell for products.&lt;/p&gt;
</description>
        <pubDate>Thu, 17 Aug 2017 04:51:03 +0000</pubDate>
      </item>
    
      <item>
        <title>Kotlin Data Class Constructor Problem</title>
        <link>/2017/08/15/Kotlin-Data-Class-Constructor-Problem/</link>
        <guid isPermaLink="true">/2017/08/15/Kotlin-Data-Class-Constructor-Problem/</guid>
        <description>&lt;p&gt;I’ve been trying to do something with a model class in Kotlin that I’ve done many times before in Java, and I’ve been left without a clean way to do what I need.&lt;/p&gt;

&lt;p&gt;Here’s what I’m trying to do in java:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.jetbrains.annotations.NotNull&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.UUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;userId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;emailId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getUserId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@NotNull&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getEmailId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The key things to note are the calls to &lt;code class=&quot;highlighter-rouge&quot;&gt;name.trim()&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;emailId.toLowerCase()&lt;/code&gt; in the constructor. These calls ensure that every &lt;code class=&quot;highlighter-rouge&quot;&gt;User&lt;/code&gt; object created has a “valid” value for &lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;emailId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Initially, in kotlin, this is what I had:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;data class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;emailId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem here is that I don’t see any way of putting in the calls to &lt;code class=&quot;highlighter-rouge&quot;&gt;trim()&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;toLowerCase()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Do you know of any ways to solve this problem? Please let me know: &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt;!&lt;/p&gt;
</description>
        <pubDate>Tue, 15 Aug 2017 04:55:22 +0000</pubDate>
      </item>
    
      <item>
        <title>An Interesting Swift Benchmark</title>
        <link>/2017/07/27/An-Interesting-Swift-Benchmark/</link>
        <guid isPermaLink="true">/2017/07/27/An-Interesting-Swift-Benchmark/</guid>
        <description>&lt;h3 id=&quot;problem&quot;&gt;Problem&lt;/h3&gt;

&lt;p&gt;I recently &lt;a href=&quot;/2017/07/21/Extensions-On-Optional-String-In-Swift/&quot;&gt;wrote about&lt;/a&gt; creating extensions on &lt;code class=&quot;highlighter-rouge&quot;&gt;Optional&amp;lt;String&amp;gt;&lt;/code&gt;. When I shared this post in the Swift India slack group, one of the people there pointed out to me that I could just use the &lt;a href=&quot;https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html&quot;&gt;nil coalescing operator&lt;/a&gt; instead of the extension methods I’d created.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fooLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;instead of:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fooLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;orEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I had a real doh! moment for not thinking of this myself. I was going to update my original post to say “well actually, nevermind - just use the nil coalescing operator”. Then however, I got some more feedback, which is why I let the post remain.&lt;/p&gt;

&lt;p&gt;One person told me that they didn’t even know Swift had a nil coalescing operator, and that &lt;code class=&quot;highlighter-rouge&quot;&gt;orEmpty&lt;/code&gt; was obvious to them where &lt;code class=&quot;highlighter-rouge&quot;&gt;??&lt;/code&gt; was not. Hmm, interesting. The fact that I knew the nil coalescing operator existed, but didn’t think to use it made me think that perhaps &lt;code class=&quot;highlighter-rouge&quot;&gt;orEmpty&lt;/code&gt; was cleaner. FWIW, I’m still not sure what the right tradeoff to make is in this regard - use a language feature that may not be super obvious, or use something custom that probably won’t exist in other projects?&lt;/p&gt;

&lt;p&gt;The more interesting piece of feedback I got though, was that the nil coalescing operator was &lt;em&gt;slow&lt;/em&gt; in terms of build time. I believe it was based off of &lt;a href=&quot;https://medium.com/@RobertGummesson/regarding-swift-build-time-optimizations-fc92cdd91e31&quot;&gt;this post&lt;/a&gt;. While that sort of made some sense intuitively, I figured I’d write a quick benchmark to see if I could prove/disprove that theory.&lt;/p&gt;

&lt;p&gt;The general strategy was to generate Swift source files that used each of these ways of doing the same thing and measure how long it took to compile.&lt;/p&gt;

&lt;h3 id=&quot;experiment&quot;&gt;Experiment&lt;/h3&gt;

&lt;p&gt;Here’s the quick and dirty python script I wrote to do this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/python&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;common&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'''
extension Optional {
    public func or(other: Wrapped) -&amp;gt; Wrapped {
        if let ret = self {
            return ret
        } else {
            return other
        }
    }
}
extension Optional where Wrapped == String {
    public func orEmpty() -&amp;gt; String {
        return self.or(other: &quot;&quot;)
    }
}

struct Foo {
    let foo: String?
}
let foo = Foo.init(foo: &quot;foo&quot;)
'''&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;common&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expanduser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'~/Desktop/foo.swift'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;fout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;system&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'swiftc -o '&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expanduser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'~/Desktop/foo'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;' '&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;et&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;et&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;write_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expanduser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'~/Desktop/results.csv'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;', '&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expanduser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'~/Desktop/results.csv'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FileNotFoundError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'nil'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'''
let a{} = foo.foo ?? &quot;&quot;
'''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'nil with type specified'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'''
let a{}: String = foo.foo ?? &quot;&quot;
'''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'empty'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'''
let a{} = foo.foo.orEmpty()
'''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'empty with type specified'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'''
let a{}: String = foo.foo.orEmpty()
'''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'other'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'''
let a{} = foo.foo.or(other: &quot;&quot;)
'''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;benchmark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'other with type specified'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'''
let a{}: String = foo.foo.or(other: &quot;&quot;)
'''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;

&lt;p&gt;I ran it on my 15 inch 2017 Macbook Pro with a 2.8 GHz Intel Core i7 processor plugged into power, and fully charged (be warned: this takes a few hours to run - I let it run overnight). I used the swift compiler that ships with Xcode 8.3.3. I took the median of the 10 samples, and graphed them:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/post-images/2017-07-27-An-Interesting-Swift-Benchmark/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, it turns out I was totally wrong - the nil coalescing operator is way faster than my ways.&lt;/p&gt;

&lt;p&gt;However, I noticed something weird that the graph above hides:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/post-images/2017-07-27-An-Interesting-Swift-Benchmark/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You may want to open those images up in a new tab - they’re much higher res than is visible, but I was too lazy to change the markup of my page to actually use the resolution.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you remove the 2500 and 5000 values, you’ll notice that &lt;code class=&quot;highlighter-rouge&quot;&gt;orEmpty&lt;/code&gt; is faster than nil-coalescing.&lt;/p&gt;

&lt;p&gt;Weird!&lt;/p&gt;

&lt;p&gt;Nil coalescing is faster, but only if the number of times the compiler has to do it is larger.&lt;/p&gt;

&lt;p&gt;I haven’t been able to figure out why this is so far, but I’ll keep digging. If you know why, or have any theories, please let me know: &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt;!&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This benchmark is highly synthetic. First, it only uses one source file (hopefully your apps are not all in one source file). Second, I highly doubt that most code bases are going to have more than a few hundred of these occurrences. At that volume, and at these absolute times (0.6 - 1 second) per 1,000 occurrences, I don’t think performance is a reason to use one or the other. The question goes back to one of style, and I’m not really sure which way to go. At this moment in time, I’d probably go with the nil coalescing operator.&lt;/p&gt;
</description>
        <pubDate>Thu, 27 Jul 2017 06:45:56 +0000</pubDate>
      </item>
    
      <item>
        <title>Extensions On Optional String In Swift</title>
        <link>/2017/07/21/Extensions-On-Optional-String-In-Swift/</link>
        <guid isPermaLink="true">/2017/07/21/Extensions-On-Optional-String-In-Swift/</guid>
        <description>&lt;p&gt;Earlier today I was writing some code that looked like this:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fooLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fooLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;baz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;baz&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bazLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baz&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bazLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I figured there had to be a cleaner way to express this. My initial thought process was to write an extension to &lt;code class=&quot;highlighter-rouge&quot;&gt;String&lt;/code&gt; that does this. Very quickly though, I realized I need to extend &lt;code class=&quot;highlighter-rouge&quot;&gt;Optional&lt;/code&gt;, not &lt;code class=&quot;highlighter-rouge&quot;&gt;String&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I came up with this:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Optional&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Wrapped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Wrapped&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This allows me to now write:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fooLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much better!&lt;/p&gt;

&lt;p&gt;Then I thought, there’s a way to make this even better for &lt;code class=&quot;highlighter-rouge&quot;&gt;Optional&amp;lt;String&amp;gt;&lt;/code&gt; specifically. So I came up with this:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Optional&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Wrapped&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;orEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And voila! I can now write:&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;fooLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;orEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Way better!&lt;/p&gt;
</description>
        <pubDate>Fri, 21 Jul 2017 16:47:11 +0000</pubDate>
      </item>
    
      <item>
        <title>Removing Passwords From PDFs</title>
        <link>/2017/07/13/Removing-Passwords-From-Pdfs/</link>
        <guid isPermaLink="true">/2017/07/13/Removing-Passwords-From-Pdfs/</guid>
        <description>&lt;p&gt;I recently came across a pdf file that required a password to open. This isn’t a super uncommon thing, particularly when sensitive files are being sent over email. The problem with this though is if I want to save the file (to say iCloud Drive), and open it later, I’m never going to remember the password when I need to open the file.&lt;/p&gt;

&lt;p&gt;There’s usually a &lt;a href=&quot;http://osxdaily.com/2015/02/17/how-to-remove-a-password-from-a-pdf-file-in-os-x/&quot;&gt;pretty simple way&lt;/a&gt; to “remove“ the password from pdf files. Unfortunately, for some reason that way did not work on this file.&lt;/p&gt;

&lt;p&gt;I went looking around for another way to do this, and came across &lt;a href=&quot;https://github.com/qpdf/qpdf&quot;&gt;qpdf&lt;/a&gt;. And… it worked!&lt;/p&gt;

&lt;p&gt;I figured I’d share this in case it’s useful to anyone else, and so I can find it easily when I need it the next time.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/qpdf/qpdf&quot;&gt;qpdf&lt;/a&gt; can be installed with &lt;a href=&quot;https://brew.sh&quot;&gt;homebrew&lt;/a&gt;: &lt;code class=&quot;highlighter-rouge&quot;&gt;brew install qpdf&lt;/code&gt;. Once it’s installed, here’s how you use it to remove the password from a pdf file (in this example, a.pdf):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;qpdf &lt;span class=&quot;nt&quot;&gt;--decrypt&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;password&amp;gt; a.pdf a-nopasswd.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Thu, 13 Jul 2017 12:59:46 +0000</pubDate>
      </item>
    
      <item>
        <title>Why I Dislike CoreData</title>
        <link>/2017/04/26/Why-I-Dislike-Coredata/</link>
        <guid isPermaLink="true">/2017/04/26/Why-I-Dislike-Coredata/</guid>
        <description>&lt;p&gt;On a recent &lt;a href=&quot;https://fatalerror.fm/episodes/2017/4/24/27-core-data&quot;&gt;episode&lt;/a&gt; of &lt;a href=&quot;https://fatalerror.fm&quot;&gt;Fatal Error&lt;/a&gt;, the hosts talked about why they’d never use Core Data in a new project. I’m one of those people as well. I’d definitely recommend listening to the episode, but I also thought I’d jot down my reasons for never using Core Data if I have a choice in the matter.&lt;/p&gt;

&lt;h2 id=&quot;magic&quot;&gt;Magic&lt;/h2&gt;

&lt;p&gt;If I had to summarize my problems with Core Data in one word, it’d be this: magic. Core Data does a whole bunch of stuff that for all intents and purposes is black magic. Most of the time you have no idea how anything works. For instance, if you read a property on a model object, you don’t actually know whether it’s in memory, or is being faulted in from disk. Figuring it out is an extremely daunting task (often impossible, since Core Data is not open source), and I don’t know too many people who can actually use Core Data well.&lt;/p&gt;

&lt;h2 id=&quot;garbage-api&quot;&gt;Garbage API&lt;/h2&gt;

&lt;p&gt;IMO, CoreData’s API is garbage. Here’re the top reasons why.&lt;/p&gt;

&lt;h3 id=&quot;model-objects-need-to-subclass-nsmanagedobject&quot;&gt;Model objects need to subclass NSManagedObject&lt;/h3&gt;

&lt;p&gt;Your model objects need to subclass &lt;code class=&quot;highlighter-rouge&quot;&gt;NSManagedObject&lt;/code&gt;. This means no more value types for model objects. It also means your code is forever tied to Core Data (see point below about isolation).&lt;/p&gt;

&lt;h3 id=&quot;everything-is-mutable&quot;&gt;Everything is mutable&lt;/h3&gt;

&lt;p&gt;All your model objects are mutable, and can change underneath you in several circumstances. This means you have to reason about concurrency every time you do something as silly as a property read.&lt;/p&gt;

&lt;h3 id=&quot;need-to-pass-contexts-around-everywhere&quot;&gt;Need to pass contexts around everywhere&lt;/h3&gt;

&lt;p&gt;You basically cannot do anything without a context, so you have to pass contexts around everywhere, effectively making them global. In fact, I recently saw an app which sticks a global context in &lt;code class=&quot;highlighter-rouge&quot;&gt;AppDelegate&lt;/code&gt;, and references it from a whole bunch of places in the app. This effectively makes the app untestable.&lt;/p&gt;

&lt;h3 id=&quot;hard-to-isolate&quot;&gt;Hard to isolate&lt;/h3&gt;

&lt;p&gt;Good design encourages separation of concerns. Your data layer should not be intricately tied into your presentation layer. Ideally, your data layer should be defined by a protocol, and your presentation layer should simply treat that protocol as a dependency. If implemented this way, I could swap out my data layer from one implementation (say JSON files written to disk), to another (say SQLite), and have no impact on my presentation layer.&lt;/p&gt;

&lt;p&gt;With CoreData however, this is virtually impossible, without also losing all the benefits of using CoreData. Swapping CoreData out for another persistence mechanism would require you to effectively re-write most of your app from scratch.&lt;/p&gt;

&lt;p&gt;Okay, but I don’t ever want to swap out CoreData for something else. Why should I care? Because separation of concerns is a good idea anyway. It makes testing your app a heck of a lot easier, for one.&lt;/p&gt;

&lt;h3 id=&quot;massive-learning-curve&quot;&gt;Massive learning curve&lt;/h3&gt;

&lt;p&gt;One of the things I like about Swift, is the idea of progressive disclosure. The idea is that there is a small learning curve to do simple things. As you go along your journey, you will learn more, as you need to. You shouldn’t have to climb a mountain just to get started.&lt;/p&gt;

&lt;p&gt;The problem with CoreData, is that you need to learn a &lt;em&gt;ton&lt;/em&gt; of stuff to just get started with it. Sure, there are a lot of well written tutorials about it, but the fact is, you shouldn’t need them.&lt;/p&gt;

&lt;h2 id=&quot;not-portable&quot;&gt;Not portable&lt;/h2&gt;

&lt;p&gt;This one is not relevant if you’re only on Apple platforms. However, if you are also on Android, using SQLite on both iOS and Android allows you to not have to re-think a whole bunch of stuff again.&lt;/p&gt;

&lt;h2 id=&quot;what-about-realm&quot;&gt;What about Realm?&lt;/h2&gt;

&lt;p&gt;I haven’t used &lt;a href=&quot;https://realm.io&quot;&gt;Realm&lt;/a&gt; for anything significant yet. Realm fixes two major problems with CoreData: it is open source &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, and portable.&lt;/p&gt;

&lt;p&gt;However, the reason I chose not to delve into Realm too deeply, is that it has several of the problems above as well. Magic, mutability, passing around contexts, etc. I’m also not sure how solid their business model is, so there’s also a risk of the project being abandoned if their company shuts down.&lt;/p&gt;

&lt;h2 id=&quot;so-what-do-i-actually-use&quot;&gt;So what do I actually use?&lt;/h2&gt;

&lt;p&gt;Currently, &lt;a href=&quot;https://github.com/groue/GRDB.swift&quot;&gt;GRDB&lt;/a&gt;. It is a fantastically designed &lt;em&gt;thin&lt;/em&gt;, &lt;em&gt;Swifty&lt;/em&gt; API around SQLite. It doesn’t try to do too much. It allows you to define model objects the way you want, have them be value types, and have them be immutable. It supports writing SQL just as well as it supports its own SQL generation wrappers.&lt;/p&gt;

&lt;p&gt;It does progressive disclosure quite well, IMO. To start with, write your model objects as you usually would, conform to the requisite GRDB protocols, and you’re good to go. If you need to do more, start writing SQL. But, if you don’t understand what WAL is, that’s totally fine - you probably don’t need it. If you do though, it’s right there for you to use.&lt;/p&gt;

&lt;p&gt;If you’re writing in Objective-C, &lt;a href=&quot;https://github.com/ccgus/fmdb&quot;&gt;FMDB&lt;/a&gt; is pretty great.&lt;/p&gt;

&lt;p&gt;I’ve also heard good things about &lt;a href=&quot;https://github.com/yapstudios/YapDatabase&quot;&gt;YapDatabase&lt;/a&gt;, but I haven’t used it myself. Their API seems to be pretty nice, though.&lt;/p&gt;

&lt;p&gt;Further reading: a &lt;a href=&quot;https://news.ycombinator.com/item?id=6553584&quot;&gt;Hacker News comment&lt;/a&gt; from &lt;a href=&quot;https://twitter.com/mikeash&quot;&gt;Mike Ash&lt;/a&gt; on the topic.&lt;/p&gt;

&lt;p&gt;Get in touch on twitter &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt; if you have any thoughts, comments, feedback, or questions!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Which means that at least in theory, you can go figure out  what it’s doing. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 26 Apr 2017 03:07:01 +0000</pubDate>
      </item>
    
      <item>
        <title>Multi Line Strings In Kotlin</title>
        <link>/2017/04/20/Multi-Line-Strings-In-Kotlin/</link>
        <guid isPermaLink="true">/2017/04/20/Multi-Line-Strings-In-Kotlin/</guid>
        <description>&lt;p&gt;I’ve recently been writing a fair amount of Kotlin for one of our &lt;a href=&quot;http://www.usetiming.com&quot;&gt;products&lt;/a&gt;. We’re using it both in the Android app, as well as in the backend server. Since both of these use cases involve writing SQL, I looked around to see if Kotlin supports multi line strings, so I could write my SQL inline, but also not have it be littered with &lt;code class=&quot;highlighter-rouge&quot;&gt;+&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;\n&lt;/code&gt; everywhere. Turns out, Kotlin is pretty great for this use case!&lt;/p&gt;

&lt;p&gt;Consider this example from our Android code base:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        SELECT
            ${TN.PROJECTS}.${CN.PROJECT_ID},
            ${TN.PROJECTS}.${CN.NAME},
            ${TN.PROJECTS}.${CN.COLOR_CODE},
            ${TN.PROJECTS}.${CN.CHANGE_TOKEN},
            ${TN.PROJECTS}.${CN.DELETED}
        FROM ${TN.PROJECTS}, ${TN.TIMERS}
        WHERE
            ${TN.PROJECTS}.${CN.DELETED} = '0' AND
            ${TN.TIMERS}.${CN.DELETED} = '0' AND
            ${TN.PROJECTS}.${CN.PROJECT_ID} = ${TN.TIMERS}.${CN.PROJECT_ID} AND
            ${TN.TIMERS}.${CN.START_TIME} BETWEEN datetime('now', '-14 days') AND datetime('now', '1 second')
        GROUP BY ${TN.PROJECTS}.${CN.PROJECT_ID}
        ORDER BY ${TN.PROJECTS}.${CN.NAME}
        &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;TN&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;CN&lt;/code&gt; are enums which represent table and column names.&lt;/p&gt;

&lt;p&gt;Ideally, I’d like to avoid all the &lt;code class=&quot;highlighter-rouge&quot;&gt;${}&lt;/code&gt; crap, but using those ensures I don’t make a typo and have my query fail. Aside from that caveat, this SQL is pretty readable, as it is appropriately indented, and logically broken up into multiple lines.&lt;/p&gt;

&lt;p&gt;Best of both worlds, really!&lt;/p&gt;

&lt;p&gt;Unfortunately, there is one problem with this code. You’re likely writing something like this in a situation where the statement is already indented 2-3 levels. If that’s the case, the resulting string is going to be littered with unnecessary indents because the lines after the first one do not begin on the first character of the line. So if you’re debugging this code, and you want to log the exact query string, or copy paste it into an sqlite3 (or your SQL client of choice) to play around with it, it’s going to be ugly.&lt;/p&gt;

&lt;p&gt;Fortunately, Kotlin has this handled as well. Enter &lt;a href=&quot;https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-indent.html&quot;&gt;trimIndent&lt;/a&gt;! Stick a call to this handy little standard library function at the end of your multi line literal, and it will handle the rest.&lt;/p&gt;

&lt;p&gt;For example, without &lt;code class=&quot;highlighter-rouge&quot;&gt;trimIndent&lt;/code&gt;, the above query would look like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                    SELECT
                        PROJECTS.PROJECT_ID,
                        PROJECTS.NAME,
                        PROJECTS.COLOR_CODE,
                        PROJECTS.CHANGE_TOKEN,
                        PROJECTS.DELETED
                    FROM PROJECTS, TIMERS
                    WHERE
                        PROJECTS.DELETED = '0' AND
                        TIMERS.DELETED = '0' AND
                        PROJECTS.PROJECT_ID = TIMERS.PROJECT_ID AND
                        TIMERS.START_TIME BETWEEN datetime('now', '-14 days') AND datetime('now', '1 second')
                    GROUP BY PROJECTS.PROJECT_ID
                    ORDER BY PROJECTS.NAME
                                   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With &lt;code class=&quot;highlighter-rouge&quot;&gt;trimIndent&lt;/code&gt;, it looks like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SELECT
    PROJECTS.PROJECT_ID,
    PROJECTS.NAME,
    PROJECTS.COLOR_CODE,
    PROJECTS.CHANGE_TOKEN,
    PROJECTS.DELETED
FROM PROJECTS, TIMERS
WHERE
    PROJECTS.DELETED = '0' AND
    TIMERS.DELETED = '0' AND
    PROJECTS.PROJECT_ID = TIMERS.PROJECT_ID AND
    TIMERS.START_TIME BETWEEN datetime('now', '-14 days') AND datetime('now', '1 second')
GROUP BY PROJECTS.PROJECT_ID
ORDER BY PROJECTS.NAME                   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much better! 👍&lt;/p&gt;

&lt;p&gt;There’s also a slightly different variant of this function called &lt;a href=&quot;https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-margin.html&quot;&gt;trimMargin&lt;/a&gt; which may suit your needs better.&lt;/p&gt;

&lt;p&gt;Get in touch on twitter &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt; if you have any thoughts, comments, feedback, or questions!&lt;/p&gt;
</description>
        <pubDate>Thu, 20 Apr 2017 05:13:16 +0000</pubDate>
      </item>
    
      <item>
        <title>Apple Accelerator</title>
        <link>/2017/04/06/Apple-Accelerator/</link>
        <guid isPermaLink="true">/2017/04/06/Apple-Accelerator/</guid>
        <description>&lt;p&gt;Recently, Apple launched a App Accelerator in Bangalore. Phil Schiller &lt;a href=&quot;https://twitter.com/pschiller/status/847719929373577217&quot;&gt;tweeted&lt;/a&gt; about it:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;App Accelerator Bengaluru - now open for iOS developers &lt;a href=&quot;https://developer.apple.com/accelerator/&quot;&gt;https://developer.apple.com/accelerator/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I signed up for a couple of sessions on the first day of sessions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Designing Great Apps&lt;/li&gt;
  &lt;li&gt;Advanced Swift&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The sessions were held at Apple’s offices in RMZ Galleria.&lt;/p&gt;

&lt;p&gt;A couple of people on the &lt;a href=&quot;https://swiftindia.herokuapp.com&quot;&gt;Swift India Slack&lt;/a&gt; asked me to take notes during the sessions and share them since not everyone who wanted to attend could attend. I figured I’d start with the first session in this post: Designing Great Apps.&lt;/p&gt;

&lt;h2 id=&quot;designing-great-apps&quot;&gt;Designing Great Apps&lt;/h2&gt;

&lt;p&gt;This talk was given by the resident “design guy”, Karthick Gopal. The goal of this talk was to highlight what makes great apps (was also referred to as “next generation” apps).&lt;/p&gt;

&lt;p&gt;To start off with, ask yourself this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What does your app make your users feel?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s not just about what features it has, what it looks like etc. It’s about what it makes users feel.&lt;/p&gt;

&lt;p&gt;Great apps are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Inviting&lt;/em&gt;. This is done with judicious use of colors, contrast, etc.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Accessible&lt;/em&gt;. 1 in 7 Indians has a disability. We should cater for them in our design. Use technologies like Dynamic Type to do this.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Engaging&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Intuitive&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Specialized&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Personal&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;State of the art&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They also &lt;em&gt;stand out&lt;/em&gt;, and &lt;em&gt;provide clear value&lt;/em&gt; to their users.&lt;/p&gt;

&lt;h2 id=&quot;3-steps-to-make-great-apps&quot;&gt;3 Steps To Make Great Apps&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Use state of the art technologies
    &lt;ul&gt;
      &lt;li&gt;Use the latest and greatest frameworks and extension points provided by Apple. However, do not blindly just integrate everything - think about what makes sense for your apps.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Optimize your apps
    &lt;ul&gt;
      &lt;li&gt;Think about which devices in the Apple ecosystem your app makes (iPhones, iPads,  watch, Macs) sense to be on.&lt;/li&gt;
      &lt;li&gt;Think about how your apps will work on the specific devices your apps will be on.&lt;/li&gt;
      &lt;li&gt;As you design your app for a device, also think about whether your app could work on other devices in the future, even if that is not your current focus.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Specialize your apps
    &lt;ul&gt;
      &lt;li&gt;Use  frameworks.&lt;/li&gt;
      &lt;li&gt;Particularly extension points.&lt;/li&gt;
      &lt;li&gt;However, do so judiciously.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;

&lt;p&gt;Karthick highlighted a few apps in his presentation for having great design.&lt;/p&gt;

&lt;h4 id=&quot;ixigo&quot;&gt;Ixigo&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://itunes.apple.com/in/app/ixigo-flight-hotel-booking/id418128294?mt=8&quot;&gt;Ixigo&lt;/a&gt; has a fantastic on boarding experience, making it inviting for new users. It uses delightful animations to draw you in.&lt;/p&gt;

&lt;h4 id=&quot;bear&quot;&gt;Bear&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;http://www.bear-writer.com&quot;&gt;Bear&lt;/a&gt; focuses on the task at hand: taking notes. Icons and actions are very subtle. They use colors really well. It’s also fun, and engaging. There first note you see when you open the app has a cute bear in it. It also looks similar on iPhone, iPad, and Mac, while still staying true to each platform.&lt;/p&gt;

&lt;h4 id=&quot;mr-crab-2&quot;&gt;Mr. Crab 2&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://itunes.apple.com/us/app/mr-crab-2/id1075872386?mt=8&quot;&gt;Mr. Crab 2&lt;/a&gt; is a fun game. Not crammed with all kinds of buttons and features. Optimized for each platform it is on.&lt;/p&gt;

&lt;h4 id=&quot;not-on-the-high-street&quot;&gt;Not On The High Street&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://itunes.apple.com/gb/app/gift-finder-by-notonthehighstreet-com/id571641021?mt=8&quot;&gt;This&lt;/a&gt; is a premium shopping app in the UK. It is highly visual. Focus is on the item, and it’s photos. They have high fidelity photos everywhere. Very little text.  TV app is video intensive, since video is most used on  TV. However, since people are not used to buying stuff on their TV, it uses handoff to allow the user to purchase an item being viewed on the  TV on their iPhone.&lt;/p&gt;

&lt;h4 id=&quot;night-sky-4&quot;&gt;Night Sky 4&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://itunes.apple.com/in/app/night-sky-4/id475772902?mt=8&quot;&gt;Night Sky 4&lt;/a&gt; has fantastic user interaction. Super smooth, and performant. Does not distract you with information you don’t need until you ask for it.&lt;/p&gt;

&lt;h4 id=&quot;field-day&quot;&gt;Field Day&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://itunes.apple.com/us/app/field-day/id1120218161?mt=8&quot;&gt;Field Day&lt;/a&gt; is a game designed specifically for  Watch. Designed for kids, so has a lot of cute animations, transitions, and graphics.&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;Karthick summarized with these points:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Have a great on boarding experience&lt;/li&gt;
  &lt;li&gt;Exhibit a clear and precise design language&lt;/li&gt;
  &lt;li&gt;Leverage key iOS technologies&lt;/li&gt;
  &lt;li&gt;Exist on the platforms where your users do&lt;/li&gt;
  &lt;li&gt;Surprise and delight users over time&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Deliver clear value&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, I quite enjoyed the session, and learned a few things from it. Hopefully this is useful to the people who weren’t able to attend this time around. Feel free to hit me up on twitter &lt;a href=&quot;https://twitter.com/gopalkri&quot;&gt;@gopalkri&lt;/a&gt; if you have any thoughts, comments, feedback, or questions!&lt;/p&gt;
</description>
        <pubDate>Thu, 06 Apr 2017 07:00:02 +0000</pubDate>
      </item>
    
  </channel>
</rss>
