<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Gopal Sharma&#39;s Blog</title>
    <description>Rants and raves of another programmer
</description>
    <link>http://gopalkri.com/</link>
    <atom:link href="http://gopalkri.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Fri, 18 Aug 2017 15:47:51 +0530</pubDate>
    <lastBuildDate>Fri, 18 Aug 2017 15:47:51 +0530</lastBuildDate>
    <generator>Jekyll v3.1.2</generator>
    
      <item>
        <title>Kotlin Data Class Constructor Problem Follow Up</title>
        <description>&lt;p&gt;I wrote about a &lt;a href=&quot;http://gopalkri.com/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;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;data class User private constructor (
    val userId: UUID,
    val name: String,
    val emailId: String
) {
    companion object {
        fun create(
            userId: UUID,
            name: String,
            emailId: String
        ) {
            return User(
                userId = userId,
                name = name.trim(),
                emailId = emailId.toLowerCase()
            )
        }
    }
}
&lt;/code&gt;&lt;/pre&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;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;val user = User.create(UUID.randomUUID(), &quot;Foo&quot;, &quot;foo@bar.com&quot;)
user.copy(emailId = &quot;FOO@bar.com&quot;)
&lt;/code&gt;&lt;/pre&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;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;data class User(
    val userId: UUID,
    private var _name: String,
    private val _emailId: String
) {
    val name: String
        get() = _name.trim()

    val emailId: String
        get() = _emailId.toLowerCase()
}
&lt;/code&gt;&lt;/pre&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;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;val user = User(
    userId = UUID.randomUUID(),
    _name = &quot;Foo&quot;,
    _emailId = &quot;foo@bar.com&quot;
)
&lt;/code&gt;&lt;/pre&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;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;class User private constructor(
    val userId: UUID,
    val name: String,
    val emailId: String
) {

    companion object {
        fun create(
            userId: UUID,
            name: String,
            emailId: String,
        ): User {
            return User(
                userId = userId,
                name = name.trim(),
                emailId = emailId.toLowerCase().trim()
            )
        }
    }

    override fun equals(other: Any?): Boolean {
        // Have IDEA generate this for me
        // Remember to re-generate it everytime I add a property to this class
    }

    override fun hashCode(): Int {
        // Have IDEA generate this for me
        // Remember to re-generate it everytime I add a property to this class
    }

    // Unfortunately IDEA cannot generate this for me, so type it out
    // I might eventually create a live template for this
    fun copy(
        userId: UUID = this.userId,
        name: String = this.name,
        emailId: String = this.emailId
    ): User {
        return create(
            userId,
            name.trim(),
            emailId.toLowerCase().trim()
        )
    }
}
&lt;/code&gt;&lt;/pre&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 15:23:00 +0530</pubDate>
        <link>http://gopalkri.com/2017/08/18/Kotlin-Data-Class-Constructor-Problem-Followup/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/08/18/Kotlin-Data-Class-Constructor-Problem-Followup/</guid>
        
        
      </item>
    
      <item>
        <title>Subscriptions</title>
        <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 10:21:03 +0530</pubDate>
        <link>http://gopalkri.com/2017/08/17/Subscriptions/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/08/17/Subscriptions/</guid>
        
        
      </item>
    
      <item>
        <title>Kotlin Data Class Constructor Problem</title>
        <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;highlighter-rouge&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;n&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;n&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;n&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;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;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;data class User(
    val userId: UUID,
    val name: String,
    val emailId: String
)
&lt;/code&gt;&lt;/pre&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 10:25:22 +0530</pubDate>
        <link>http://gopalkri.com/2017/08/15/Kotlin-Data-Class-Constructor-Problem/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/08/15/Kotlin-Data-Class-Constructor-Problem/</guid>
        
        
      </item>
    
      <item>
        <title>An Interesting Swift Benchmark</title>
        <description>&lt;h3 id=&quot;problem&quot;&gt;Problem&lt;/h3&gt;

&lt;p&gt;I recently &lt;a href=&quot;http://gopalkri.com/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;highlighter-rouge&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;p&gt;instead of:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&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;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;highlighter-rouge&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;&#39;&#39;&#39;
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;)
&#39;&#39;&#39;&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;&#39;&#39;&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;&#39;~/Desktop/foo.swift&#39;&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;&#39;w&#39;&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;&#39;swiftc -o &#39;&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;&#39;~/Desktop/foo&#39;&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;&#39; &#39;&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;&#39;~/Desktop/results.csv&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;a&#39;&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;&#39;, &#39;&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;&#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;&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;&#39;~/Desktop/results.csv&#39;&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;&#39;nil&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;&#39;&#39;
let a{} = foo.foo ?? &quot;&quot;
&#39;&#39;&#39;&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;&#39;nil with type specified&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;&#39;&#39;
let a{}: String = foo.foo ?? &quot;&quot;
&#39;&#39;&#39;&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;&#39;empty&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;&#39;&#39;
let a{} = foo.foo.orEmpty()
&#39;&#39;&#39;&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;&#39;empty with type specified&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;&#39;&#39;
let a{}: String = foo.foo.orEmpty()
&#39;&#39;&#39;&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;&#39;other&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;&#39;&#39;
let a{} = foo.foo.or(other: &quot;&quot;)
&#39;&#39;&#39;&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;&#39;other with type specified&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&#39;&#39;&#39;
let a{}: String = foo.foo.or(other: &quot;&quot;)
&#39;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&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;amp-img width=&quot;1954&quot; height=&quot;1095&quot; layout=&quot;responsive&quot; src=&quot;/assets/images/2017-07-27-An-Interesting-Swift-Benchmark/1.png&quot;&gt;&lt;/amp-img&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;amp-img width=&quot;2339&quot; height=&quot;1287&quot; layout=&quot;responsive&quot; src=&quot;/assets/images/2017-07-27-An-Interesting-Swift-Benchmark/2.png&quot;&gt;&lt;/amp-img&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 12:15:56 +0530</pubDate>
        <link>http://gopalkri.com/2017/07/27/An-Interesting-Swift-Benchmark/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/07/27/An-Interesting-Swift-Benchmark/</guid>
        
        
        <category>swift</category>
        
      </item>
    
      <item>
        <title>Extensions On Optional String In Swift</title>
        <description>&lt;p&gt;Earlier today I was writing some code that looked like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&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;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;highlighter-rouge&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;p&gt;This allows me to now write:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&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;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;highlighter-rouge&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;p&gt;And voila! I can now write:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&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;p&gt;Way better!&lt;/p&gt;
</description>
        <pubDate>Fri, 21 Jul 2017 22:17:11 +0530</pubDate>
        <link>http://gopalkri.com/2017/07/21/Extensions-On-Optional-String-In-Swift/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/07/21/Extensions-On-Optional-String-In-Swift/</guid>
        
        
      </item>
    
      <item>
        <title>Removing Passwords From PDFs</title>
        <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;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;qpdf --decrypt --password&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;
</description>
        <pubDate>Thu, 13 Jul 2017 18:29:46 +0530</pubDate>
        <link>http://gopalkri.com/2017/07/13/Removing-Passwords-From-Pdfs/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/07/13/Removing-Passwords-From-Pdfs/</guid>
        
        
      </item>
    
      <item>
        <title>Why I Dislike CoreData</title>
        <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 08:37:01 +0530</pubDate>
        <link>http://gopalkri.com/2017/04/26/Why-I-Dislike-Coredata/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/04/26/Why-I-Dislike-Coredata/</guid>
        
        
      </item>
    
      <item>
        <title>Multi Line Strings In Kotlin</title>
        <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;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;val cursor = db.rawQuery(
        &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} = &#39;0&#39; AND
            ${TN.TIMERS}.${CN.DELETED} = &#39;0&#39; AND
            ${TN.PROJECTS}.${CN.PROJECT_ID} = ${TN.TIMERS}.${CN.PROJECT_ID} AND
            ${TN.TIMERS}.${CN.START_TIME} BETWEEN datetime(&#39;now&#39;, &#39;-14 days&#39;) AND datetime(&#39;now&#39;, &#39;1 second&#39;)
        GROUP BY ${TN.PROJECTS}.${CN.PROJECT_ID}
        ORDER BY ${TN.PROJECTS}.${CN.NAME}
        &quot;&quot;&quot;,
        null
)
&lt;/code&gt;&lt;/pre&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;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 = &#39;0&#39; AND
                        TIMERS.DELETED = &#39;0&#39; AND
                        PROJECTS.PROJECT_ID = TIMERS.PROJECT_ID AND
                        TIMERS.START_TIME BETWEEN datetime(&#39;now&#39;, &#39;-14 days&#39;) AND datetime(&#39;now&#39;, &#39;1 second&#39;)
                    GROUP BY PROJECTS.PROJECT_ID
                    ORDER BY PROJECTS.NAME
                                   
&lt;/code&gt;&lt;/pre&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;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 = &#39;0&#39; AND
    TIMERS.DELETED = &#39;0&#39; AND
    PROJECTS.PROJECT_ID = TIMERS.PROJECT_ID AND
    TIMERS.START_TIME BETWEEN datetime(&#39;now&#39;, &#39;-14 days&#39;) AND datetime(&#39;now&#39;, &#39;1 second&#39;)
GROUP BY PROJECTS.PROJECT_ID
ORDER BY PROJECTS.NAME                   
&lt;/code&gt;&lt;/pre&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 10:43:16 +0530</pubDate>
        <link>http://gopalkri.com/2017/04/20/Multi-Line-Strings-In-Kotlin/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/04/20/Multi-Line-Strings-In-Kotlin/</guid>
        
        
        <category>kotlin</category>
        
      </item>
    
      <item>
        <title>Apple Accelerator</title>
        <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;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 12:30:02 +0530</pubDate>
        <link>http://gopalkri.com/2017/04/06/Apple-Accelerator/</link>
        <guid isPermaLink="true">http://gopalkri.com/2017/04/06/Apple-Accelerator/</guid>
        
        
      </item>
    
      <item>
        <title>Migrating Repositories with Git LFS</title>
        <description>&lt;p&gt;I recently decided to try migrating a private repository from &lt;a href=&quot;github.com&quot;&gt;github.com&lt;/a&gt; to &lt;a href=&quot;gitlab.com&quot;&gt;gitlab.com&lt;/a&gt; since GitLab seems to have shipped a lot of great features recently. GitLab has a feature that allows you to import repositories, including Issues from Github, so I decided to give it a try.&lt;/p&gt;

&lt;p&gt;After GitLab was done importing, however, I was disappointed to find that it had not actually copied over several assets I had checked in with LFS. All the references to those assets were still pointing to Github.&lt;/p&gt;

&lt;p&gt;After getting over my initial disappointment, and filing an &lt;a href=&quot;https://gitlab.com/gitlab-com/support-forum/issues/1033&quot;&gt;issue&lt;/a&gt;, I figured hey, this is still git. I can do the LFS migration myself.&lt;/p&gt;

&lt;p&gt;I set about googling for answers on how to migrate git repositories with LFS, but to my dismay, I did not find any information about this. There are loads of blog posts that refer to migrating assets from a vanilla git repository to LFS, but nothing about what I was trying to do.&lt;/p&gt;

&lt;p&gt;So I started digging around in man pages, and eventually found &lt;a href=&quot;https://github.com/github/git-lfs/blob/master/docs/man/git-lfs-fetch.1.ronn&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;git lfs fetch&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/github/git-lfs/blob/master/docs/man/git-lfs-push.1.ronn&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;git lfs push&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Turns out, you can use these commands to migrate lfs assets as well.&lt;/p&gt;

&lt;p&gt;I’m assuming you have your original LFS enabled repository on github cloned (this remote is assumed to be &lt;code class=&quot;highlighter-rouge&quot;&gt;origin&lt;/code&gt;). You’ve also imported it into GitLab with their importer, and added it as a remote (called &lt;code class=&quot;highlighter-rouge&quot;&gt;gitlab&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Now, run:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git lfs fetch --all 
git lfs push gitlab --all 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This can take a while (it will show progress), but once it’s done, you’re good to go!&lt;/p&gt;

&lt;p&gt;Hopefully, if you use git LFS, this gives you some peace of mind that if the need arises, you will be able to migrate to another git host if you so choose without too much hassle 😀.&lt;/p&gt;
</description>
        <pubDate>Fri, 07 Oct 2016 14:54:52 +0530</pubDate>
        <link>http://gopalkri.com/2016/10/07/Migrating-Repositories-With-Git-Lfs/</link>
        <guid isPermaLink="true">http://gopalkri.com/2016/10/07/Migrating-Repositories-With-Git-Lfs/</guid>
        
        
      </item>
    
  </channel>
</rss>
