<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Göksel Köksal on Medium]]></title>
        <description><![CDATA[Stories by Göksel Köksal on Medium]]></description>
        <link>https://medium.com/@gokselkoksal?source=rss-5c2696f0be42------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*C5Wyx-auGwICkyoxBpPMYw.jpeg</url>
            <title>Stories by Göksel Köksal on Medium</title>
            <link>https://medium.com/@gokselkoksal?source=rss-5c2696f0be42------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 24 Apr 2026 05:38:08 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@gokselkoksal/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Improve your tests with this simple trick]]></title>
            <link>https://medium.com/@gokselkoksal/improve-your-tests-with-this-simple-trick-7782399b7f4a?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/7782399b7f4a</guid>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[software-testing]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Fri, 02 Apr 2021 00:00:11 GMT</pubDate>
            <atom:updated>2026-01-25T23:58:42.593Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*I3nakncVjSpANF6C" /><figcaption>Photo by <a href="https://unsplash.com/@rparmly?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Ross Parmly</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><p>Let’s say you joined a new team and you’re expected to make some changes to an existing feature. You rightfully think that the best way to understand a feature is to check the existing tests to get a feel of possible scenarios to consider.</p><p>You then dig into the codebase and find the following test case.</p><pre>let notificationScheduler = MockNotificationScheduler()<br>let locationProvider = MockLocationProvider()<br>let locationListener = LocationListener(<br>  locationProvider: locationProvider,<br>  notificationScheduler: notificationScheduler<br>)<br><br>locationProvider.currentLocation = .ireland<br>locationListener.start()<br><br>locationProvider.currentLocation = .turkey<br><br>XCTAssertEqual(<br>  notificationScheduler.scheduledNotification, <br>  InsuranceNotification(from: .ireland, to: .turkey)<br>)</pre><p>It’s a bit hard to see the wood for trees, isn’t it? You might have a wild guess about what’s going on here but the scenario itself isn’t obvious.</p><p>Let’s break it down.</p><p>On the first line, we have the MockNotificationScheduler.</p><pre>let notificationScheduler = MockNotificationScheduler()</pre><p>We go to the implementation to find out MockNotificationScheduler implements NotificationSchedulerProtocol, which looks like this:</p><pre>protocol NotificationSchedulerProtocol {<br>  func scheduleInsuranceNotification(from: Country, to: Country)<br>}</pre><p>It’s fair to assume that this one schedules a notification for the given from and to countries.</p><p>Moving onto the MockLocationProvider on the second line.</p><pre>let locationProvider = MockLocationProvider()</pre><p>We again go to the implementation and find out MockLocationProvider implements LocationProviderProtocol which looks like the following:</p><pre>protocol LocationProviderProtocol {<br>  var currentLocation: Country { get }<br>  var locationUpdateHandler: ((Country) -&gt; Void)? { get set }<br>}</pre><p>This one is obvious. It is used for determining the current location and detecting the location changes.</p><p>The last definition is the LocationListener. Looks like this one is not a mock object and it&#39;s most likely the <em>subject under test</em>.</p><pre>let locationListener = LocationListener(<br>  locationProvider: locationProvider,<br>  notificationScheduler: notificationScheduler<br>)</pre><p>We check the implementation for this one and see LocationListener is a service that listens for location updates and schedules notifications when the user travels from one country to another.</p><p>So… It looks like LocationListener is observing the changes in location using LocationProvider and schedule insurance notifications using NotificationScheduler when needed.</p><p>With all this information, we can go back to the test case itself and hopefully understand the scenario being tested.</p><pre>locationProvider.currentLocation = .ireland<br>locationListener.start()<br><br>locationProvider.currentLocation = .turkey<br><br>XCTAssertEqual(<br>  notificationScheduler.scheduledNotification, <br>  InsuranceNotification(from: .ireland, to: .turkey)<br>)</pre><p><strong>At this point, we can confidently tell that the test case above is testing if a notification is scheduled when the user travels from Ireland to Turkey.</strong></p><p>**However, would you consider this test <em>readable</em>?**</p><p>We had to check the internals of three components just to understand the scenario being tested. Tests in the codebase should also act as documentation so we can conclude that this is a poorly structured test.</p><p><strong>What would have been ideal here?</strong></p><p>Ideally, the test case itself should describe the scenario in a readable way so that…</p><p>I recently wrote a small helper to solve this problem. With <a href="https://gist.github.com/gokselkoksal/a384ffe46ccd656de95ee144f0bf7304?ref=goksel.codes">Scenario</a>, the test case above would turn into this:</p><pre>Scenario(&quot;User travels to a different country and receives an insurance offer&quot;)<br>  .given(&quot;user is currently in Ireland&quot;) {<br>    locationProvider.currentLocation = .ireland<br>    locationListener.start()<br>  }<br>  .when(&quot;user travels to Turkey&quot;) {<br>    locationProvider.currentLocation = .turkey<br>  }<br>  .then(&quot;a local notification should be scheduled to offer travel insurance&quot;) {<br>    XCTAssertEqual(<br>      notificationScheduler.scheduledNotification, <br>      InsuranceNotification(from: .ireland, to: .turkey)<br>    )<br>  }</pre><p>So what did we gain here?</p><ul><li>The test is more structured and readable. We don’t have to go into the implementation to understand the scenario being tested.</li><li>Scenario forces us to write in given/when/then format which helps the developer to better structure the test when writing it out.</li><li><strong>Bonus</strong>: Each block runs an XCTContext activity so we get beautiful test reports!</li></ul><p>The approach is nothing new! <a href="https://en.wikipedia.org/wiki/Behavior-driven_development?ref=goksel.codes">Behaviour-Driven Development</a> has been around for quite a while and some popular implementations are…</p><ul><li>🥒 <a href="https://cucumber.io/?ref=goksel.codes">Cucumber</a> is a wildly popular framework especially for cross-platform testing as it completely decouples code and scenario definition.</li><li>⚡️ <a href="https://github.com/Quick/Quick?ref=goksel.codes">Quick</a> is a widely used BDD framework for Swift and Objective-C which lets you create test cases similar to those above.</li></ul><p>(And I am sure there are others that I missed!)</p><p><strong>So why build another helper, you ask?</strong></p><p>Despite Cucumber and Quick being great and mature frameworks, they are big commitments. They change how you develop tests so much that it feels like you’re developing with a whole new language. <a href="https://gist.github.com/gokselkoksal/a384ffe46ccd656de95ee144f0bf7304?ref=goksel.codes">Scenario</a> on the other hand is a small helper that you can opt-in whenever you want without big commitments.</p><p>Hope you enjoyed the article! ❤️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7782399b7f4a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Performing optimistic updates]]></title>
            <link>https://medium.com/@gokselkoksal/performing-optimistic-updates-d0dea11e1d9d?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/d0dea11e1d9d</guid>
            <category><![CDATA[ios-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[software-testing]]></category>
            <category><![CDATA[software-architecture]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Sat, 20 Feb 2021 00:00:23 GMT</pubDate>
            <atom:updated>2026-01-25T23:59:48.570Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rNrWrrkUmbJtN4Bs" /><figcaption>Photo by <a href="https://unsplash.com/@swimstaralex?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Alexander Sinn</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><p>You might have noticed that “like” or “favorite” action in social media almost never makes you wait, although there is a network call in progress in the background. The users who “like” content are generally more likely to come back and engage with more content. This is because platforms choose to optimize flows that lead to user engagement and strive to make these flows as frictionless as possible.</p><p>Consider Twitter’s like button. The heart icon immediately goes red when we tap it. This is good because we can simply like something and move on when the real work still happens in the background.</p><p>So how can we implement this? Let’s first define what needs to happen from a user’s perspective.</p><ul><li>The UI immediately reacts <strong>as if the action was successful</strong>. (This is why we call it <strong>optimistic</strong>.)</li><li>We perform the network request in the background.</li><li>If it succeeds, happy days, we already performed the update.</li><li>If it fails, we need to revert the optimistic update.</li></ul><p>Now, to achieve this in code, we need to know…</p><ul><li>what is the <strong>actual task</strong> we want to perform and <strong>how we can perform</strong> this task</li><li>what is the <strong>optimistic update</strong> we want to perform while this task is in progress</li><li>and how we can <strong>revert the optimistic update</strong> if the task fails</li></ul><p>If we have all this, we can even design a generic API that aids us when implementing optimistic updates. Let’s see if we can do that.</p><p>Consider we have the following data model.</p><pre>struct Post { <br>  var id: UUID <br>  var message: String <br>  var isLiked: Bool <br>}</pre><p>Let’s define the task and the update we want to perform on this model.</p><pre>enum PostTask { <br>  case like(id: UUID) <br>} <br><br>enum PostUpdate { <br>  case isLiked(Bool) <br>}</pre><p>Now we need to define how we can perform this task and apply the model updates.</p><pre>class PostService {<br>  func perform(<br>    _ task: PostTask, <br>    completion: (Result&lt;Bool, Error&gt;) -&gt; Void<br>  ) {<br>    // perform the network call<br>    // report the result in the callback<br>  }<br>}</pre><p>This service will only perform the task and report the result. Useful but not quite there. What we need is more like a function that receives both the task and the optimistic update.</p><pre>let service = PostService()<br><br>func perform(<br>  _ task: PostTask, <br>  optimisticUpdate: PostUpdate<br>) {<br>  // perform the optimistic update here!<br>  service.perform(task) { result in<br>    switch result {<br>    case .success:<br>      // task is successful. happy days!<br>    case let .failure(error):<br>      // task has failed. revert the optimistic update!<br>  }<br>}</pre><p>OK, we got the shape but there are missing pieces.</p><ol><li><strong>Generic models</strong>. If we want a generic API, we should not rely on PostTask or PostUpdate.</li><li><strong>Generic service</strong>. We need a way to inject a service that can perform the given task.</li><li><strong>Generic events</strong>. We need a way to broadcast important events so the updates can be performed.</li></ol><p>This feels like we need a stateful object instead of just a function. So let’s start with a generic class.</p><pre>class OptimisticUpdater&lt;Task, Update, Error&gt; { ... }</pre><p>We tackled the first problem. Now we need a generic function that can perform the task and report the result.</p><pre>enum TaskResult&lt;Update, Error: Swift.Error&gt; {<br>  /// Task is successful. Optimistic update can be kept.<br>  case success<br> <br>  /// Task has failed. Optimistic update should be reverted.<br>  case failure(Error, rollbackUpdate: Update)<br>}<br><br>typealias PerformTaskFunction&lt;Task, Update, Error&gt; = (<br>  _ task: Task,<br>  _ update: Update,<br>  _ finish: @escaping (TaskResult&lt;Update, Error&gt;) -&gt; Void<br>) -&gt; Void</pre><p>Now that we have also defined a generic function signature for performing tasks, we can move on to the next problem. We need to publish optimistic update events so that the model can be updated and changes can be propagated to the UI.</p><p>We can start with a simple enum and deliver events using a block.</p><pre>class OptimisticUpdater&lt;Task, Update, Error&gt; {<br>  enum Event {<br>    /// Optimistic update should be applied. Task is about to start executing.<br>    case optimisticUpdateRequested(Update, task: Task)<br><br>    /// Task is successful. Optimistic update should be kept.<br>    case taskSucceeded(Task, update: Update)<br> <br>    /// Task has failed. Optimistic update should be reverted.<br>    case taskFailed(Task, error: Error, failedUpdate: Update, rollbackUpdate: Update)<br>  }<br> <br>  var eventHandler: ((Event) -&gt; Void)?<br>}</pre><p>As we also solved the last problem, if we glue everything together, we get an <a href="https://gist.github.com/gokselkoksal/ee9802e3a48ac2ee5a5f5576b5a4e150?ref=goksel.codes#file-optimisticupdater-swift">OptimisticUpdater implementation like this one</a>.</p><p>Let’s see how we can use it.</p><pre>let service = PostService()<br>var post = Post(id: UUID(), message: &quot;Test&quot;, isLiked: false)<br><br>// 1. Create an optimistic updater:<br>postUpdater = OptimisticUpdater&lt;PostTask, PostUpdate, PostTaskError&gt; { <br>  task, optimisticUpdate, finish in<br>                                                                       <br>  service.perform(task) { (result) in<br>    switch result {<br>    case .success:<br>      finish(.success)<br>    case let .failure(error):<br>      finish(.failure(error, rollbackUpdate: optimisticUpdate.revert()))<br>    }<br>  }<br>}<br> <br>// 2: Set a callback for updater events:<br>postUpdater.eventHandler = { event in<br>  switch event {<br>  case let .optimisticUpdateRequested(update, task: task):<br>    post.apply(update)<br>  case let .taskSucceeded(task, update: update):<br>    showConfirmation(task)<br>  case let .taskFailed(task, error: error, failedUpdate: failedUpdate, rollbackUpdate: rollbackUpdate):<br>    showError(error, for: task)<br>    post.apply(rollbackUpdate)<br>  }<br>}<br> <br>// 3. Use the updater to like a post:<br>postUpdater.perform(.like(id: post.id), optimisticUpdate: .isLiked(true))</pre><p>So what did we achieve here?</p><ul><li>We completely separated real work from the optimistic updates.</li><li>We isolated the logic required to perform an optimistic update in one component, which can be used to update any model.</li><li>We don’t have to think about when the update should happen and when it should be reverted every time we use it!</li><li>It is completely testable. See below:</li></ul><pre>var service = MockPostService()<br>var post = Post(id: UUID(), message: &quot;Test&quot;, isLiked: false)<br>var postUpdater = OptimisticUpdater { /* use mock service here */ }<br>var success: Bool?<br>postUpdater.eventHandler = { event in<br>  switch event {<br>  case let .optimisticUpdateRequested(update, task: task):<br>    post.apply(update)<br>  case let .taskSucceeded(task, update: update):<br>    success = true<br>  case let .taskFailed(task, error: error, failedUpdate: failedUpdate, rollbackUpdate: rollbackUpdate):<br>    post.apply(rollbackUpdate)<br>    success = false<br>  }<br>}<br><br>// When the task is performed and the call is in progress<br>postUpdater.perform(.like(id: post.id), optimisticUpdate: .isLiked(true))<br><br>// Then expect optimistic model update post.isLiked=true<br>XCTAssertEqual(success, nil)<br>XCTAssertEqual(post.isLiked, true)<br><br>// When the response is received<br>service.resume()<br><br>// Then expect post.isLiked=true and success=true<br>XCTAssertEqual(success, true)<br>XCTAssertEqual(post.isLiked, true)</pre><p>Thanks for reading! ❤️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0dea11e1d9d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Testing Analytics Events]]></title>
            <link>https://medium.com/@gokselkoksal/testing-analytics-events-655cb01bf7ed?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/655cb01bf7ed</guid>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Mon, 19 Oct 2020 10:48:33 GMT</pubDate>
            <atom:updated>2026-01-26T00:00:07.330Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9F7GuMeygip10ppssatrNQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@goumbik?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Lukas Blazek</a> on <a href="https://unsplash.com/@gokselkk/likes?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Since we make lots of important decisions by looking at the analytics data (if not, you should), I will not go into “why” having accurate analytics data is extremely important.</p><p>You probably also know that it is extremely painful to manually test if analytics events are being reported correctly. It’s very time consuming to perform some actions in the app, wait for the analytics tool to receive these events and verify each. Now, multiply this with number of releases you’ll have in the future… It’s a nightmare. 😩</p><p><strong>This time could be better spent elsewhere</strong>.</p><p>Any time you have this feeling, there’s a good chance that things can be automated. Can we automate analytics testing? Why not.</p><p><strong>Could we write black-box UI tests?</strong> With UI testing, we could actually record the UI actions leading to a specific analytics event. These UI actions can be repeated whenever we want to generate analytics events on the portal. But the verification part would still be manual on the analytics tool we’re using. <strong>This would still require manual verification so it is probably not what we want.</strong></p><p><strong>Could we write unit tests?</strong> Simulate UI actions that would lead to an analytics event, check if the mock analytics layer received the event and verify the details… <strong>This could work! Let’s try it out.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=655cb01bf7ed" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Reactive Code and Component Design]]></title>
            <link>https://medium.com/@gokselkoksal/reactive-code-and-component-design-c286e0ce780a?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/c286e0ce780a</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[functional-programming]]></category>
            <category><![CDATA[reactive-programming]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Thu, 18 Apr 2019 08:01:00 GMT</pubDate>
            <atom:updated>2024-01-10T22:12:29.476Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xnDjT_FF-5OBCrTgHBF6aA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/MYXf7tGEntk?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Mikael Kristenson</a> on <a href="https://unsplash.com/search/photos/light?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Functional Reactive Programming (FRP) is almost an industry standard on mobile today. If you’re not familiar with it, here’s a <a href="https://blog.danlew.net/2017/07/27/an-introduction-to-functional-reactive-programming/">great read</a> by Daniel Lew on fundamentals. In the first part, he explains the difference between <strong>passive</strong> and <strong>reactive</strong> components. I find this really interesting. I think we should talk more about <em>what it means to be reactive</em> before diving into any implementation. In this post, we will repeat his switch-lightbulb experiment, then try to reflect the learnings on component design.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*i9zzlGoqSmLvQmZJ1_wHSA.png" /><figcaption>Credit: <a href="https://blog.danlew.net/2017/07/27/an-introduction-to-functional-reactive-programming/">blog.danlew.net</a></figcaption></figure><p>Experiment is <em>very</em> simple. We have a switch that turns the light on or off. How would you build it?</p><p>If we design a <strong>passive</strong> lightbulb:</p><ul><li><strong>Switch</strong> turns the <strong>lightbulb</strong> on/off when it’s switched on/off.</li><li><strong>Switch</strong> knows about the <strong>lightbulb</strong>.</li></ul><pre>class Switch {<br>  var state: Bool {<br>    didSet {<br>      lightbulb.state = state<br>    }<br>  }<br>  <br>  let lightbulb: Lightbulb<br>  ...<br>}</pre><p>If we design a <strong>reactive</strong> lightbulb:</p><ul><li><strong>Lightbulb</strong> should be created with an object which reflects the state of the <strong>switch</strong> and observe it. (That object would be Observable&lt;Bool&gt;.)</li><li>Neither <strong>switch</strong> nor the <strong>lightbulb</strong> knows about each other. They are decoupled.</li></ul><pre>class Lightbulb {<br><br>  private(set) var state = false<br>  private let disposeBag = DisposeBag()<br>  <br>  init(observable: Observable&lt;Bool&gt;) {<br>    disposeBag += observable.subscribe { [weak self] value in<br>      self?.state = value<br>    }<br>  }<br><br>  init(_ switch: Switch) {<br>    self.init(observable: aSwitch.observable)<br>  }<br>}</pre><p>There’s no difference between output of these implementations from the user’s point of view. However, by using reactive approach, <strong>we decoupled the switch and the lightbulb</strong>. This is where observables come in handy. It’s easy to represent an object’s input or output as an observable so we can pass it around instead of the component itself.</p><h3>Designing Components</h3><p>Would we always use an observable to represent a component’s input or output? Let’s think about it.</p><p>In switch-lightbulb example, the switch produces an infinite number of on-off events and the lightbulb is expected to <em>react</em> to them accordingly. That’s why the following model make sense.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*17v608uaacvEeJIbJdgT2w.png" /></figure><p>In this case, Observable solves our problem because both switch’s output and lightbulb’s input are <em>event streams</em>.</p><p>What if it was not an event stream?</p><p>Let’s say we’re designing a recipe list component. We could expect a recipe-fetcher as input, so that we can fetch the recipes with it and display them. What would this fetcher return?</p><ul><li>If the recipes are fetched synchronously from a database, returning [Recipe] would make sense.</li><li>If the recipes are fetched asynchronously from a server, then we would need a type like Future&lt;[Recipe]&gt; to indicate that recipe list is coming from a remote source.</li></ul><p>Could we use Observable&lt;[Recipe]&gt; instead of Future&lt;[Recipe]&gt;?</p><p>Yes, <em>we could</em>. But should we? Remember, observables represent event streams. In this case, we’re talking about a network request so it’ll either return a value or an error. It’s definitely not an event stream but <em>can be</em> represented using an event stream that receives only one value. Since observables are more than likely to receive more than one value, using Observable&lt;[Recipe]&gt; as return type would set a wrong expectation on receiving end and therefore, is not a wise choice.</p><p>Using the correct abstractions is extremely important in programming because developers generate a mental model by looking at them. When we look at a block of code that we’re not familiar with, we start developing a mental model by looking at names, types and connections. If we have the right model, everything becomes 10 times easier. Therefore, it’s important that we thrive for better abstractions.</p><p>Looking at the examples above, we can generalize return types as below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WA-11zNdKdLo2Ux0dzPJrA.png" /></figure><p>Takeaway here is that:</p><blockquote><strong>Observable is not always the right abstraction.</strong></blockquote><p>One of the main goals of component design is to encapsulate certain functionality so that it can be reused across the codebase. It’s really hard to do so without <strong>clearly defined responsibility, inputs and outputs</strong>. The table above is the toolkit that should be used to achieve this.</p><h3>Bottom Line</h3><p>Reactivity is extremely useful when designing decoupled components with clear input and output, especially when it involves user input. But this is not as trivial as it sounds. We first should be able to <em>observe</em>, to be able to <em>react</em>. An abstraction like Observable is a great solution to this problem.</p><p>It’s also very important to know that we have other tools under our belt. Observable is a powerful abstraction but great power comes with great responsibility. We should use abstractions when they&#39;re needed, not when <em>we can</em>. This is very important to keep things simple and understandable. If you look at the return-type table above, you&#39;ll realize we actually <em>can</em> use an Observable in all those cases, but that wouldn&#39;t be very wise.</p><p>If you read between the lines, you’ll probably realize I’m not a huge fan of RxSwiftor ReactiveCocoa as it&#39;s very easy (or even advertised in some cases) to abuse their Observable / Signal implementation. I don&#39;t want to get into details now as it can be a blog post on its own. 😅</p><p>Hope this provides another perspective on FRP and popular frameworks around it.</p><p>Thanks for scrolling all the way! ❤️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c286e0ce780a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JSON Wars: Codable ⚔️ Unbox]]></title>
            <link>https://medium.com/@gokselkoksal/json-wars-codable-vs-unbox-9dfed523b0bf?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/9dfed523b0bf</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[json]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[object-oriented]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Mon, 28 May 2018 07:44:45 GMT</pubDate>
            <atom:updated>2024-01-14T14:23:03.870Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CJmqrjX43p_OAE6YP_V17Q.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/ZeKDTlXFWu8?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Julian Howard</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><a href="https://theswiftpost.co/swift-4s-codable/">Codable</a> got everyone excited because we all love parsing JSON and it’s nice to have this tool as a part of the standard library. Now it’s time to test if it’s worthy enough to be our favorite one.</p><p>Let’s see how Codable performs under rough conditions. We’re going to parse the following JSON using Codable and then compare it against the popular <a href="https://github.com/JohnSundell/Unbox">Unbox</a>/<a href="https://github.com/JohnSundell/Wrap">Wrap</a> implementation.</p><pre>{<br>  “placeName”: “İstanbul, Turkey”,<br>  “lat”: 41.0049823,<br>  “lon”: 28.7319958,<br>  “dateAdded”: “2018-05-25”,<br>  “info”: “İstanbul is a very historical city.”<br>}</pre><p>We want our data model to look like the following.</p><pre>struct Place: Codable {<br>  let name: String<br>  let coordinate: Coordinate<br>  let dateAdded: Date<br>  let info: String?<br>}</pre><pre>struct Coordinate {<br>  let latitude: Decimal<br>  let longitude: Decimal<br>}</pre><p><strong>Challenges</strong>:</p><ul><li>placeName and name doesn’t match. We need to tweak coding keys.</li><li>Two separate keys lat and lon become a Coordinate object. Custom decoding is needed.</li><li>We need to use YYYY-mm-dd date format for dateAdded field.</li><li>We need to throw an error if name, coordinate and dateAdded fields are missing but info field is optional.</li></ul><h3>Implementation Using Codable</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1b4ce2dedee74d62d57e7aaa92763abb/href">https://medium.com/media/1b4ce2dedee74d62d57e7aaa92763abb/href</a></iframe><h3>Implementation Using Unbox &amp; Wrap</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a84fe75f0cf65f69fb404500e242c1fa/href">https://medium.com/media/a84fe75f0cf65f69fb404500e242c1fa/href</a></iframe><h3>Usage</h3><p>Their usage is almost the same. That is, of course, if we define decoder and encoder as a class property.</p><p><strong>Codable</strong>:</p><pre>let place = try Place.decoder.decode(Place.self, from: jsonData)<br>let placeData = try Place.encoder.encode(place)</pre><p><strong>Unbox/Wrap</strong>:</p><pre>let place = try Place(unboxer: Unboxer(data: jsonData))<br>let placeData = try wrap(place) as Data</pre><h3>Comparison 🎯</h3><ul><li>Codable implementation is 47 lines, whereas Unbox implementation is 39 lines for this example.</li><li>Keys in Codable is always strongly typed (CodingKeys) while Unbox only accepts String keys.</li><li>While decoding properties, Unbox infers the type but Codable requires the type as a parameter. However, this can be enabled in Codable as well using a simple extension like <a href="https://gist.github.com/gokselkoksal/8bb3af6405e354a5958956d6bb78f2c5">KeyedDecodingContainer+TypeInference</a>.</li></ul><pre>// Codable:<br>try container.decode(String.self, forKey: .name)<br>// Unbox:<br>name = try unboxer.unbox(key: &quot;placeName&quot;)</pre><ul><li>Codable only supports one date encoding/decoding strategy. So if we had a UNIX timestamp property along with dateAdded, we would need to manually transform it into a Date object in init(from decoder:) method.</li><li>Codable has lots of advanced features around keys, which are not available in Unbox/Wrap. (See: <a href="https://developer.apple.com/documentation/foundation/archives_and_serialization/using_json_with_custom_types">Using JSON with Custom Types</a>)</li><li>Unbox/Wrap is a third-party dependency while Codable is a part of standard library.</li></ul><h3>Bottom Line 🎖</h3><p>While Codable requires some research and digestion before advanced usage, you can hit the ground running with Unbox in minutes. For serialization, Unbox only requires you to implement an init method which defines all the mappings.</p><p>On the other hand, Codable is black magic.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/442/1*qPlHpmS--TJx4-9xWAcdlw.gif" /></figure><p>Most of the cases, it just works without any customization. Although advanced usage can sometimes be complicated due to keys being strongly typed, it’s easy to learn. Codable is like a Swiss army knife so I can’t think of any case you can’t handle with it.</p><p>I started this post thinking that Unbox is much simpler and readable compared to Codable for advanced usage, but sample code indicates otherwise. It might be time to move away from all third-party JSON parsing frameworks and make peace with Codable.</p><p>Well played, Apple.</p><p><strong>Thanks for reading!</strong> Please let me know what you think and help spread the word. ❤️👏</p><p><strong><em>Further reading</em></strong><em>: </em><a href="https://theswiftpost.co/swift-4s-codable/"><em>Swift 4’s Codable</em></a><em> by </em><a href="https://medium.com/u/95da5651e56a"><em>Alp Avanoğlu</em></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9dfed523b0bf" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Blurring the Lines Between MVVM and VIPER]]></title>
            <link>https://medium.com/@gokselkoksal/blurring-the-lines-between-mvvm-and-viper-dcb3dc9815ac?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/dcb3dc9815ac</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Fri, 20 Apr 2018 07:31:01 GMT</pubDate>
            <atom:updated>2024-01-14T14:24:28.928Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*olJUeL2ziDvUPnXBBbPCYA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/Skf7HxARcoc?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Markus Spiske</a> on <a href="https://unsplash.com/search/photos/software-design?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>If you have been developing mobile apps for a while, you’ve probably heard of MVVM and VIPER. While some people say MVVM does not scale well, some others say VIPER is an overkill. I am here to explain why I think they are very similar and we don’t even need to separate the two.</p><p>Let’s first quickly go over MVVM and VIPER.</p><h3>What is MVVM?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/642/1*o_JyWEmSFcAnhMJaVakg8Q.png" /></figure><ul><li><strong>View</strong> delivers user actions to <strong>view model</strong>.</li><li><strong>View model</strong> handles these actions and updates its state.</li><li><strong>View model</strong> then notifies the <strong>view</strong>, either with data binding or manually using delegation or blocks.</li></ul><h3>What is VIPER?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/882/1*K0yDVAP5FHZoD1TreVoz2A.png" /></figure><ul><li><strong>View</strong> delivers user actions to <strong>presenter</strong>.</li><li><strong>Presenter</strong> then delivers these actions to either <strong>interactor</strong> or <strong>router</strong>.</li><li>If the action requires computation, <strong>interactor</strong> handles it and returns the state to the <strong>presenter</strong>.</li><li><strong>Presenter</strong> then transforms this state to presentation data and updates the <strong>view</strong>.</li><li>Navigation logic is encapsulated in <strong>router</strong> and <strong>presenter</strong> is responsible from triggering it.</li></ul><p><em>For more information on these architectures, reference this great post by </em><a href="https://medium.com/u/632fc0b37c99"><em>Bohdan Orlov</em></a><em>: </em><a href="https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52"><em>iOS Architecture Patterns</em></a></p><h3>What’s our main goal?</h3><p>Our first goal is to separate UI and business logic. Therefore, we can easily update UI without breaking any business rules and also test business logic in isolation. Both MVVM and VIPER assures this, but in different ways. If we look from this point of view, they are structured as follows.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YdU8NhD2nQqPl3pSS8e9sg.png" /></figure><p>While MVVM has only a view component in UI layer, VIPER separates UI responsibilities into 3 components, which are View, Presenter and Router. It’s also obvious that business layer looks pretty much the same.</p><p>Let’s see how they actually differ in UI layer in practise.</p><h3>An Imaginary App: Top Movies</h3><p>Imagine that we’re building a simple app using MVVM which fetches top 25 movies from IMDB and shows them on a list. The components would probably look like the following.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2abde8e38222a5f9f949af68fb87333b/href">https://medium.com/media/2abde8e38222a5f9f949af68fb87333b/href</a></iframe><p><strong>Information Flow:</strong></p><ul><li>(View sets itself as view model’s delegate.)</li><li>User taps on reload.</li><li>View calls fetchMovies on view model.</li><li>When the movies are fetched, view model notifies the delegate (view).</li><li>updateWithMovies method gets called internally and transforms movies into presentation data and shows them on the list.</li></ul><p>This is pretty straightforward. Let’s build the exact same app for macOS now and try to reuse code as much as possible.</p><h3>An Imaginary Case: Implementing macOS Version</h3><p>One thing is certain, view classes will be completely different. In that case, we can’t reuse the presentation logic that sits in our iOS app. iOS view currently transforms Movie objects into presentation data in updateMovies method. The only way to reuse that piece is to take it out. Let’s move presentation model generation to a mediator class between the view and the view model, so that we can reuse it in both iOS and macOS views.</p><p>I will call this mediator class Presenter, just by chance.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/374ee4e43d834ef8ba72319f6f316711/href">https://medium.com/media/374ee4e43d834ef8ba72319f6f316711/href</a></iframe><p><strong>Information Flow:</strong></p><ul><li>(View sets itself as presenter’s delegate.)</li><li>(Presenter sets itself as view model’s delegate)</li><li>User taps on reload.</li><li>View calls reload on presenter.</li><li>Presenter calls fetchMovies on view model.</li><li>When the movies are fetched, view model notifies the delegate (presenter).</li><li>Presenter transforms movies into presentation data and notifies the delegate (view).</li><li>View updates itself.</li></ul><p>This means that we can hook up any view that conforms to MovieListView protocol and expect it to work properly, platform independently.</p><p>We now delivered our brand-new macOS app by reusing most of the code we have for iOS.</p><p>But there’s an Apple Event coming up…</p><h3>An Imaginary Case: iOS Redesign</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wf990OsM2JbVyrkJ0I7w4A.png" /></figure><p>In a few weeks, Apple announces iOS 26 and Jony Ive pulls a new trick by introducing a completely new design system. Our designers get excited and quickly come up with a new UI for iOS. Now our job will be to implement this new design and prove its usability with A/B testing, which means we’ll only show the new UI to some percentage of our users.</p><p>We’re actually in very good standing! We only need to create a new view for iOS that conforms to MovieListView protocol and hook it up with the presenter. Easy peasy.</p><pre>protocol MovieListView: MovieListPresenterDelegate {<br>  ...<br>  func didTapOnMovie(at index: Int)<br>  func showDetailView(for movie: Movie)<br>}</pre><p>While implementing this new class, we’ll realize that showDetailView implementations should be the same in both old and the new view. We’ll maybe copy-paste this piece from the old class at first, but then it’ll probably kill us inside because we all know copy-paste is bad.</p><p>OK — let’s move it out too. We’ll call this component Router, again, just by chance.</p><pre>protocol MovieListRouter {<br>  func showDetailView(for movie: Movie)<br>}</pre><p>This router will reference the current view weakly, and be responsible from pushing the detail view whenever it’s needed. But where do we keep this component? Should we compose it in the both old and new view classes? We could… But, talking from experience, views better be very dumb since they tend to change a lot.</p><p>Let’s push this responsibility to the presenter as well and let it compose the router. This way view will only be responsible from delivering user actions to the presenter. Presenter will then decide when to call the view model for a computation or the router for navigation needs.</p><p>Now that we reused the navigation logic as well, we can release in peace.</p><p>Let’s look at the final structure.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44b43d2a84284a3d47441d3853dfa50e/href">https://medium.com/media/44b43d2a84284a3d47441d3853dfa50e/href</a></iframe><p>I think you got the point by now. If we rename MovieListViewModel to MovieListInteractor, we are 100% VIPER and we didn’t violate any rule that is enforced by MVVM.</p><h3>Moral of the Story</h3><p>Software architectures are just a set of rules. Some has less, some has more rules. Using one doesn’t necessarily mean abandoning the other one. This is true, especially when we are talking about MVC, MVVM and VIPER.</p><pre>MVC 📗 → MVVM 📘 → VIPER 📙</pre><p>Going from left to right, I only see an evolution process that enables scalability, not contradictions. VIPER is just the most detailed version of them all and that’s why some people consider it as an overkill. Listen to these people, they might be right!</p><p>VIPER in full has 5 components, and you might not need all of them in all cases. I think we should just use our best judgement while developing a feature instead of blindly accepting some made-up rules.</p><p>My current development recipe is as follows:</p><ul><li>Start with VIPER-lite, which is exactly the same as MVVM. Only use view, interactor and entities for starters.</li><li>If you expect UI changes soon, append a presenter to your implementation.</li><li>If you have complex/reusable routing logic, append a router.</li><li>For each feature, have a separate file to layout class interfaces and design the communication between them before the actual implementation. This is generally considered as an overhead but it definitely helps you design better interfaces which would eventually save time.</li></ul><p><strong>Notes</strong>:</p><ul><li>You cannot define private variables in a protocol, they are only used to give hints about the expected implementation.</li><li>Some methods like didTapOnMovie(at:) or presentation(from:) would also be private methods in the actual implementation. They are shown as a part of the protocol for demonstration purposes.</li></ul><p>What do you think? Please leave a comment below if you have any questions or feedback. 💬</p><p><strong>Thanks for reading!</strong></p><p>Help spread the word. ❤️👏</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dcb3dc9815ac" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Channels for Data Flow in Swift ]]></title>
            <link>https://medium.com/@gokselkoksal/using-channels-for-data-flow-in-swift-14bbdf27b471?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/14bbdf27b471</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Mon, 05 Mar 2018 08:31:01 GMT</pubDate>
            <atom:updated>2024-01-14T14:25:10.398Z</atom:updated>
            <content:encoded><![CDATA[<h4>An alternative to delegation and NotificationCenter</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cyQ4UHQdJDryah733k8c-g.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/7NJE_JbVReo?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Milivoj Kuhar</a> on <a href="https://unsplash.com/search/photos/radio?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Apple frameworks use delegation and observer pattern (NotificationCenter) heavily to pass information around. Although there is nothing wrong about these patterns, the actual implementation always looked a bit inconsistent to me.</p><p>Let’s look at the basic traits of these patterns first:</p><ul><li><strong>Delegation:</strong> Supports 1-to-1, two-way communication.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/482/1*0hVqPP9urBk189uprdpaLQ.png" /></figure><ul><li><strong>Observer</strong>: Supports 1-to-many, one-way communication.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/482/1*-8KMJZg3JON8S2Ppbe_HMg.png" /></figure><p>Let’s look at some UITableViewDelegate methods.</p><pre>optional func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -&gt; CGFloat</pre><ul><li><strong>UITableView</strong>: Sender</li><li><strong>UITableViewDelegate (Mostly </strong><strong>UIViewController)</strong>: Receiver</li></ul><p>This method is a good example of 1-to-1, two-way communication.</p><p>Since the table view requires height to be returned by the controller, communication is two-way and it can’t be 1-to-many. (Otherwise, we wouldn’t be able to decide which returned height value should be used.)</p><p>However, the following method does not return anything.</p><pre>optional func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)</pre><p>Here, sender only <strong>notifies</strong> the receiver. Therefore, the communication is one-way and can either be 1-to-1 or 1-to-many.</p><blockquote><strong>In this case, is delegation a good choice?<br>- </strong>Maybe…</blockquote><blockquote><strong>What happens if we need to notify more than one component?<br>- </strong>We can’t.</blockquote><blockquote><strong>What if we don’t care about row selection but want to provide row height ourselves? Do we still need to provide empty implementations?<br>- </strong>If this was a pure Swift protocol, <strong>yes</strong>, we would need empty implementations in place for each delegate method we don’t care about, which is pretty annoying. Since UITableViewDelegate is inherited from Objective-C, we can mark methods as optional for the sake of backwards compatibility. But Swift disables this “feature” for a reason. Having huge protocols violates <a href="https://en.wikipedia.org/wiki/Interface_segregation_principle">interface segregation principle</a> and makes them unreadable. Table views are a huge part of my life as a developer but I still can’t remember what’s defined in UITableViewDelegate and UITableViewDataSource protocols because the list is way too long.</blockquote><p>So… Why don’t we use observer pattern for every one-way action? We could provide the same functionality with more flexibility and it would also clear up most methods in huge delegate protocols.</p><h3>An Imaginary Problem</h3><p>We have a settings page which features theme selection. We want to update our home screen whenever the theme changes.</p><h4>Solution #1: Using Delegation</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ee95d9778f9c580692213fc37180cfd7/href">https://medium.com/media/ee95d9778f9c580692213fc37180cfd7/href</a></iframe><p>This solution works but is it flexible enough? What happens if we have 5 tabs to be updated with this theme change?</p><h4>Solution #2: Using NotificationCenter</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ed09717ef5d662efdd2316e07425aa58/href">https://medium.com/media/ed09717ef5d662efdd2316e07425aa58/href</a></iframe><p>Now we support 1-to-many communication, but we doubled the number of lines, right? This is the main problem with NotificationCenter. It is powerful but not very handy.</p><h4>Solution #3: Using Channels</h4><p>What is a channel?</p><p>It’s nothing new. Channel is an observer pattern implementation which provides a much better API than NotificationCenter.</p><ul><li>Create a channel:</li></ul><pre>enum Message {<br>  case themeDidChange(Theme)<br>}</pre><pre>let channel = Channel&lt;Message&gt;()</pre><ul><li>Subscribe to it:</li></ul><pre>channel.subscribe(self) { message in<br>  // Handle message here.<br>}</pre><ul><li>Broadcast a message:</li></ul><pre>channel.broadcast(.themeDidChange(.light))</pre><p>So using a channel, our solution would look like the following:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a658cd2cddafcc087364682f2f40d8b2/href">https://medium.com/media/a658cd2cddafcc087364682f2f40d8b2/href</a></iframe><h3>Final Words</h3><ul><li>We can standardize data flow in our code by adapting channels for one-way communication and delegation for two-way communication.</li><li>We can finally stop using NotificationCenter.</li><li><a href="https://github.com/gokselkoksal/Lightning/blob/master/Lightning/Sources/Components/Channel.swift">Channel implementation</a> is less than 100 lines of code and now is a part of <a href="https://github.com/gokselkoksal/Lightning/">Lightning framework</a>.</li></ul><p><strong>Thanks for scrolling all the way!</strong></p><p>Your opinion matters! Please let me know what you think and help spread the word. ❤️👏</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=14bbdf27b471" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Lightning Read #2: Optional String Pitfalls]]></title>
            <link>https://medium.com/@gokselkoksal/lightning-read-2-optional-string-pitfalls-1a24a65f5f00?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/1a24a65f5f00</guid>
            <category><![CDATA[string]]></category>
            <category><![CDATA[tips]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Wed, 06 Dec 2017 08:31:01 GMT</pubDate>
            <atom:updated>2018-04-22T19:17:57.003Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oQyvN9tTy5KX6XC-QyQH1w.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/iF5odYWB_nQ?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Max Bender</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>I was trying to build a URL the other day. Check the following code block:</p><pre>init?(userId: <strong>String?</strong>) {<br>  guard userId != nil else { return nil }<br>  <br>  <strong>self.path = &quot;/user/\(userId)&quot;</strong><br>  self.url.appendPathComponent(self.path)<br>}</pre><p>Seems legit, right?</p><p>Assume that we’re passing 23940 as userId to this initializer. Depending on the Swift version, path value would be:</p><pre><strong>Swift 2.x </strong>| path = &quot;/user/23940&quot;<br><strong>Swift 3.x </strong>| path = &quot;/user/Optional(&quot;23940&quot;)&quot;<br><strong>Swift 4.x </strong>| path = &quot;/user/Optional(&quot;23940&quot;)&quot;</pre><p>Subtle, but heart-breaking.</p><p>Firstly, beware of this issue if you’re working on a super-old project which still uses Swift 2.x for some reason, and planning to migrate.</p><p>Secondly, we could use a guard-let instead of a guard-check statement here to fix this issue. However, it’s not convenient to have guard statements everywhere, especially when you simply want to print stuff.</p><p>I created the following struct to overcome this problem:</p><pre>public struct Printable&lt;T&gt;: CustomStringConvertible {<br>    <br>    public let value: T?<br>    <br>    public init(_ value: T?) {<br>        self.value = value<br>    }<br>    <br>    public var description: String {<br>        if let value = value {<br>            return String(describing: value)<br>        } else {<br>            return &quot;(null)&quot;<br>        }<br>    }<br>}</pre><p><strong><em>Note</em></strong><em>: Yes, we could also print “nil” instead of “(null)” but I think the latter is more expressive. You can always choose this one or the other.</em></p><p>Whenever you have optionals, you simply wrap them in a Printable struct as below.</p><pre>self.path = &quot;/user/\(Printable(userId))&quot; // &quot;/user/23940&quot;<br>print(Printable(userId))                 // &quot;23940&quot;</pre><p>Or, in a more complex example:</p><pre>struct User: CustomStringConvertible {</pre><pre>  let id: String<br>  let firstName: String?<br>  let lastName: String?<br>  <br>  var description: String {<br>    var string = id<br>    string += &quot;, \(Printable(firstName))&quot;<br>    string += &quot;, \(Printable(lastName))&quot;<br>    return string<br>  }<br>}</pre><pre>let user1 = User(<br>  id: &quot;23940&quot;, <br>  firstName: &quot;Göksel&quot;, <br>  lastName: &quot;Köksal&quot;<br>)</pre><pre>let user2 = User(<br>  id: &quot;23941&quot;, <br>  firstName: &quot;Sıla&quot;, <br>  lastName: nil<br>)</pre><pre>print(user1)<br>print(user2)</pre><p>Without Printable struct, these objects would print below;</p><pre>&quot;23940, Optional(&quot;Göksel&quot;), Optional(&quot;Köksal&quot;)&quot;<br>&quot;23941, Optional(&quot;Sıla&quot;), nil&quot;</pre><p>With Printable, it prints;</p><pre>&quot;23940, Göksel, Köksal&quot;<br>&quot;23941, Sıla, (null)&quot;</pre><p>The latter seems much cleaner.</p><h3>Alternatives</h3><h4>Global “describe” Function</h4><pre><strong>func describe&lt;T&gt;(_ value: Optional&lt;T&gt;) -&gt; String</strong> {<br>  switch value {<br>    case .some(let wrapped):<br>      return String(describing: wrapped)<br>    case .none:<br>      return &quot;(null)&quot;<br>  }<br>}</pre><h4>Optional Extension</h4><pre>extension Optional {<br>  <br><strong>  var stringValue: String</strong> {<br>    switch self {<br>      case .some(let wrapped):<br>        return String(describing: wrapped)<br>      case .none:<br>        return &quot;(null)&quot;<br>    }<br>  }<br>}</pre><p>Credit: <a href="https://medium.com/u/95da5651e56a">Alp Avanoğlu</a></p><h4>Comparison</h4><pre>var url1: URL? = URL(string: &quot;www.google.com&quot;)<br>var url2: URL? = nil</pre><pre><strong>// `Printable` struct:</strong></pre><pre>print(Printable(url1))  // Prints &quot;www.google.com&quot;<br>print(Printable(url2))  // Prints &quot;(null)&quot;</pre><pre><strong>// `describe` global function:</strong></pre><pre>print(describe(url1))   // Prints &quot;www.google.com&quot;<br>print(describe(url2))   // Prints &quot;(null)&quot;</pre><pre><strong>// `stringValue` extension on `Optional`:</strong></pre><pre>print(url1.stringValue) // Prints &quot;www.google.com&quot;<br>print(url2.stringValue) // Prints &quot;(null)&quot;</pre><h3>Moral of the Story</h3><p>If you are annoyed by logs like Optional(www.google.com) on your console, you can start using one of the alternatives.</p><p><strong>Thanks for dropping by!</strong> And, as usual, help spread the word. ❤️👏</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1a24a65f5f00" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Lightning Read #1: Lazy Collections in Swift]]></title>
            <link>https://medium.com/@gokselkoksal/lightning-read-1-lazy-collections-in-swift-fa997564c1a3?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/fa997564c1a3</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[lazy-loading]]></category>
            <category><![CDATA[complexity]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Tue, 21 Nov 2017 08:01:01 GMT</pubDate>
            <atom:updated>2018-04-22T19:17:04.191Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oQyvN9tTy5KX6XC-QyQH1w.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/iF5odYWB_nQ?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Max Bender</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>I was planning to write “short” and simple articles about my findings from day-to-day Swift experiments for a while now… 🕵</p><p>Here goes the first lightning article! 🚀</p><h3>Problem: Intermediate clutter that comes with map, flatMap and filter functions</h3><p>Let’s say we have the following requirements in an imaginary project:</p><blockquote>There are 6 frames for an animation in format animation_&lt;index&gt;.jpeg available to download.</blockquote><blockquote>- Download animation frames using Request objects.</blockquote><blockquote>- Discard every second frame for better performance.</blockquote><p>In a real world, we would most probably have more frames but think of this as a simplified example.</p><p>Instead of using a for loop for these 6 frames, we will go functional and use map, flatMap and filter methods.</p><pre><strong>let frameIndexes: [Int] = Array(1...6)</strong></pre><pre><strong>let imageRequests: [Request] = frameIndexes</strong><br>  // Optimize by filtering every second frame:<br><strong>  .filter { $0 % 2 == 1 }</strong><br>  // Transform frame number to image name:<br><strong>  .map { &quot;animation_\($0).jpeg&quot; }</strong><br>  // Transform image names to URLs:<br><strong>  .flatMap { URL(string: &quot;https://www.somehost.com/\($0)&quot;) }</strong><br>  // Transform URLs to request objects:  <br><strong>  .map { Request(url: $0) }</strong></pre><p>This is much more readable than having a for-loop. But how about performance? Let’s dig into details by going over this code block line by line.</p><ul><li>filter block runs 6 times for each frame index in the array.</li><li><em>A new array gets created with 3 filtered frame indexes.</em></li><li>map block runs 3 times for each item.</li><li><em>A new array gets created with 3 image names.</em></li><li>flatMap block runs 3 times for each item.</li><li><em>A new array gets created with 3 URLs. (Assuming URL creation will be successful on each image name.)</em></li><li>map block runs 3 times on each URL.</li><li><em>A new array gets created with 3 request objects.</em></li></ul><p>Call order will look like this:</p><pre>filter<br>filter<br>filter<br>filter<br>filter<br>filter</pre><pre><strong>// A new array is created.</strong></pre><pre>mapToName<br>mapToName<br>mapToName</pre><pre><strong>// A new array is created.</strong></pre><pre>flatMapToURL<br>flatMapToURL<br>flatMapToURL</pre><pre><strong>// A new array is created.</strong></pre><pre>mapToRequest<br>mapToRequest<br>mapToRequest</pre><pre><strong>// A new array is created.</strong></pre><p>Although we only need the resulting array at the end, we created 3 more intermediate arrays, which has absolutely no use. This happened because filter, map and flatMap are eager functions that calculate immediately.</p><p>It’s not a problem for a small data set, but it can be problematic when dealing with a huge data set.</p><h3>Solution: Using LazyCollection</h3><p>Using a lazy collection, we can get rid of intermediate array creations in between. There is a lazy property defined on RandomAccessCollection which Array conforms to. lazy basically provides a lazy implementation of the same array, using LazyRandomAccessCollection&lt;T&gt; type, which only calculates values when in need.</p><p>Let’s implement the lazy approach now.</p><pre>let frameIndexes: [Int] = Array(1...6)</pre><pre>let lazyImageRequests = frameIndexes<br>  <strong>.lazy</strong><br>  .filter { $0 % 2 == 1 }<br>  .map { &quot;animation_\($0).jpeg&quot; }<br>  .flatMap { URL(string: &quot;https://www.somehost.com/\($0)&quot;) }<br>  .map { Request(url: $0) }</pre><p>Easy, right? We keep the same declarative way of transforming values from one to another, but achieved good performance just by adding .lazy after frameIndexes.</p><p>It will perform better because nothing will be executed unless we access an element. We have 2 options at this point:</p><ul><li>We can use the lazy collection just like normal array and calculate each value as we access them.</li><li>We can go over the elements of lazy collection one by one and store them in a normal array.</li></ul><p>We’ll go with the second option to inspect the call order.</p><pre>var imageRequests: [Request] = []</pre><pre><strong>for request in lazyImageRequests {<br>    imageRequests.append(request)<br>}</strong></pre><pre>// We could also use:<br>// lazyImageRequests.forEach { imageRequests.append($0) }</pre><p>After this for loop, call order would be:</p><pre><strong>// Item 0:</strong><br>filter</pre><pre><strong>// Item 1:</strong><br>filter<br>mapToName<br>flatMapToURL<br>mapToRequest</pre><pre><strong>// Item 2:</strong><br>filter</pre><pre><strong>// Item 3:</strong><br>filter<br>mapToName<br>flatMapToURL<br>mapToRequest</pre><pre><strong>// Item 4:</strong><br>filter</pre><pre><strong>// Item 5:</strong><br>filter<br>mapToName<br>flatMapToURL<br>mapToRequest</pre><h3>Bottom Line</h3><p>If we <strong>don’t</strong> use lazy;</p><ul><li>We iterate over the original array 4 times.</li><li>We create 3 redundant intermediate arrays.</li></ul><p>If we <strong>do</strong> use lazy;</p><ul><li>We iterate only once.</li><li>We get each element calculated through the pipe as we access them.</li></ul><h4>Note on Caching</h4><p>Beware that if we go over lazyImageRequests one more time, each item will be calculated again. So if you plan to access these items more than once, it’s recommended to cache them in a traditional array, just like we did in the example above.</p><h4>Note on Array Conversion</h4><p>We can also use the Array initializer to convert a lazy array to a normal array as below.</p><pre>let imageRequests: [Request] = Array(lazyImageRequests)</pre><p>I am not sure about the internals of lazy collections, but the code above doesn’t print the same call order as the for loop, for some reason. So keep in mind that using Array initializer for this purpose may not be as performant as expected.</p><p>If you’d like to try it out, implementation is available on <a href="https://github.com/gokselkoksal/LazyCollections">LazyCollections</a> repo.</p><p><strong>Thanks for dropping by!</strong> And, as usual, help spread the word. ❤️👏</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fa997564c1a3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Architecting iOS Apps with “Core”]]></title>
            <link>https://medium.com/nsistanbul/architecting-ios-apps-with-core-a7d769196b0a?source=rss-5c2696f0be42------2</link>
            <guid isPermaLink="false">https://medium.com/p/a7d769196b0a</guid>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[redux]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Göksel Köksal]]></dc:creator>
            <pubDate>Mon, 31 Jul 2017 07:31:07 GMT</pubDate>
            <atom:updated>2019-11-20T20:59:39.067Z</atom:updated>
            <content:encoded><![CDATA[<h4>Understanding architectures to the core…</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*-CUeCOl0P3mLFWS2t2WyJA.jpeg" /><figcaption>Bahá’í Temple of South America</figcaption></figure><p>In the last two years, I’ve had chances to experiment with architectures like MVC, MVVM and VIPER. What’s common among those is the V component, which represents the views in our application. In a perfect world, view component should only do the following:</p><ul><li>Delivers any user action (touches) to business layer.</li><li>Listens for state changes and updates itself.</li></ul><p>Nothing else. Unlike their differences, view component is actually the same in all architectures. It is dumb, isolated and therefore easily replaceable.</p><p>But honestly, are they? Look at any of your implementations and tell me… In most iOS applications, they are actually the strongest component. We inject every smart component (like view model, presenter and interactor) into view controllers. That means if a view controller dies, those smart components die too. View is actually the dumb muscular guy who dictates the whole flow with its lifecycle. Shouldn’t it be the other way around?</p><p>I don’t think there is a problem with architecture definitions, but I can’t say the same for how they are advertised and implemented.</p><h4>What are we really trying to achieve?</h4><p>If we abstract it further, an ideal architecture should look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WfPvtPKszh_kXUsqtcwi8A.png" /><figcaption>Information Flow with User</figcaption></figure><p>Assuming the UI component is designed by the book and Core includes all business logic, we can actually remove UI and replace it with anything… Like a test suite.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dG-eIlLIiDW0-yPENib4Bw.png" /></figure><p>If we achieve this, we can simulate every use-case with a test suite without needing any UI at all. Let’s have a look at login use-case:</p><p><strong>Login (from user perspective):</strong></p><ul><li>Enter username and password.</li><li>Tap on login.</li></ul><p><strong>Login (in test suite):</strong></p><pre>core.dispatch(LoginCommand(username: &quot;goksel&quot;, password: &quot;123&quot;))</pre><p>This would be cool, right?</p><h3>Enter “Core”</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xZByvaEcUx-YoSAfezJWrg.jpeg" /></figure><p>Our goal is to design a business layer that represents our app’s state without needing any UI component at all. Obviously, this is not possible unless we stop relying on view lifecycle. So we need another layer, which would simply be the source of life for our app. I’ll call this layer “Core”.</p><p>In our products, we generally have features like login, sign-up, movie-list, movie-detail etc. All of these features should ideally be self-functioning <strong>components</strong> which can be represented with a class. This class will contain that feature’s current <strong>state</strong> and will be able to process incoming <strong>actions</strong> to produce a <strong>new state</strong>. By doing this, we’ll have an isolated component for each feature, and all of those components and transitions will be managed by <strong>core</strong>.</p><p>The final picture would look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2Wg7DttPV12OXxmtjUL8bw.png" /></figure><p>As shown in the diagram;</p><ul><li><strong>Core</strong> is simply a box that represents our app.</li><li><strong>Actions</strong> are the changes that happen on the system. They travel through Core and trigger state changes on components.</li><li><strong>Components</strong> contain business logic for features and are able to process actions.</li><li><strong>Subscribers</strong> can be anything. It can be a console app. It can be an iOS app. It can be our test suite.</li></ul><p>Simple, right?</p><h3>Talk is cheap. Show me the code.</h3><p>It sounds good in theory (as always) but would this be easy enough to implement as well? Let’s implement a simple login screen with 2-factor authentication and see.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*8-MreAYOUvLE7XWsJ52Ghw.png" /></figure><p><strong>Requirements</strong>:</p><ul><li>Allow user 60 seconds to enter the security code. Pop back on timeout.</li><li>Verify security code with a web service once user taps on login button.</li><li>If verification is successful, push home component.</li><li>If verification is not successful, show an alert.</li><li>Show loading indicator when a network request is in progress.</li></ul><p>Easy peasy. Let’s dive in.</p><h4>1- Define the State</h4><blockquote>What makes the state of this component? What data do we need to render it on the screen?</blockquote><ul><li>We need a flag to show/hide loading indicator.</li><li>We need to keep track of timer status.</li><li>We need to keep track of the verification process.</li></ul><pre>struct LoginState: State {<br>  var isLoading = false<br>  var timerStatus: TimerStatus = .idle<br>  var verificationResult: Result&lt;Void&gt;?<br>}</pre><h4>2- Define Actions</h4><blockquote>What changes can occur on this screen?</blockquote><ul><li>Timer tick</li><li>Tap on verify button</li></ul><pre>enum LoginAction: Action {<br>  case tick<br>  case verifyOTP(String)<br>}</pre><h4>3- Define the Component</h4><p>Now we can define the component itself. All components will have a state and a process function. When an action is dispatched to core, all components will receive and react to it if necessary. If the state changes as a result of the dispatched action, component subscribers will be notified with the new state.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*P-W0ZcnnDSD39Uz_fet-gg.gif" /></figure><p><strong><em>Note</em></strong><em>: State is a readonly property on Component class, however, it can be updated using commit function. This is by design and to avoid too many state updates. So to change state; create a copy, make all the changes and call commit. This will set a new state, and notify all subscribers.</em></p><pre>class LoginComponent: Component&lt;LoginState&gt; {</pre><pre>  override func process(_ action: Action) {<br>    guard let action = action as? LoginAction else { return }<br>    switch action {<br>    case .tick:<br>      <strong>self.tick()</strong><br>    case .verifyOTP(let code):<br>      <strong>self.verifyOTP(code)</strong><br>    }<br>  }</pre><pre>  // ...</pre><pre>}</pre><p>So this simply is our component. By overriding process function, we can react to incoming actions when necessary. As you may have guessed, the real magic happens in tick and verifyOTP functions.</p><p>Let’s take a closer look: 🔍</p><pre>func verifyOTP() {<br><strong>  // Get a copy of the current state:</strong><br>  var state = self.state</pre><pre><strong>  // Start loading before network call:</strong><br>  state.isLoading = true</pre><pre><strong>  // Publish state:</strong><br>  commit(state)</pre><pre><strong>  // Start network call:</strong><br>  service.verifyOTP { result in</pre><pre><strong>    // Update state with response:</strong><br>    state.isLoading = false<br>    state.timerStatus = .finished<br>    state.result = result</pre><pre><strong>    // Publish new state (and navigation):</strong><br>    switch result {<br>    case .success():<br><strong>      // Navigate to home if success:</strong><br>      let nav = BasicNavigation.push(HomeComponent(), from: self)<br>      self.commit(state, nav)<br>    case .failure(_):<br>      self.commit(state)<br>  }<br>}</pre><p>Although this function does async work internally, it doesn’t have a completion block because state propagation is done by committing a new state to the component.</p><h4>4- Subscribe to the State</h4><p>So from a UI point of view, nothing is async. View just gets a new state whenever it’s available and update itself. For example, LoginViewController would look like this:</p><pre>class LoginViewController: Subscriber {</pre><pre>  var component: LoginComponent! // Injected by previous component.</pre><pre>  func viewWillAppear(animated: Bool) {<br>    super.viewWillAppear(animated)<br>    <strong>component.subscribe(self)</strong><br>  }</pre><pre>  func viewDidDisappear(animated: Bool) {<br>    super.viewDidDisappear(animated)<br>    <strong>component.unsubscribe(self)</strong><br>  }</pre><pre>  // MARK: - Actions</pre><pre>  func verifyTapped(field: UITextField) {<br>    <strong>core.dispatch(LoginAction.verifyOTP(field.text))</strong><br>  }</pre><pre>  // MARK: - Subscriber</pre><pre>  func update(with state: State) {<br>    guard let state = state as? LoginState else { return }<br>    <strong>// Update UI here.</strong><br>  }</pre><pre>  func perform(_ navigation: Navigation) {<br>    <strong>// Perform navigation here.</strong><br>  }</pre><pre>}</pre><h4>5- Define “Core”</h4><p>Core can be defined in global scope as below.</p><pre>let core = Core(rootComponent: LoginComponent())</pre><p>That’s it. After this point on, we are free to dispatch any action. 🎉</p><h3>Bottom Line</h3><p>Core can be seen as a Redux, Flux and MVVM hybrid. If we structure an app with Core, we’ll have Redux-like communication and state propagation. However, the component itself is very similar to MVVM’s view model which is very straightforward and easy to adapt.</p><h4><strong>Main differences between Core and Redux</strong></h4><ul><li><strong>Redux</strong> is static. It expects you to define a big fat structure that expresses the app state in compile time. This can be challenging if you have reusable controllers that you present here and there a number of times. Especially in cases where your application flow is altered by server responses, you cannot easily define your app state in compile time without hacking the architecture. <strong>Core</strong> is dynamic. You only need to define the state and actions for the component you are working on. Component transitions can be handled dynamically.</li><li>In <strong>Redux</strong>, there is no standard way to implement navigation between components. With <strong>Core</strong>, you get native navigation support.</li><li><strong>Redux</strong> focuses on application state, whereas <strong>Core</strong> focuses on isolated component state. In this regard, I find it easier to work in isolation on one component rather than getting lost in huge application state.</li><li>In <strong>Redux</strong>, since the state is global, it’s easy to forget to do state clean-up when a screen is popped from the navigation stack. In <strong>Core</strong>, since every component stores its own state, when you remove a component from the tree, state gets disposed along with it. This is handled internally by navigation mechanism.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*_0TFaTTM33jww7OC1fP8BQ.gif" /></figure><h4>Why should I use it?</h4><p>Because you get many things for free by doing roughly the same amount of work compared to other architectures.</p><ul><li><strong>Separation of concerns</strong>: Each and every box in Core diagram has a purpose and a clear definition.</li><li><strong>Easy to reason about</strong>: It forces you to model your components in a way that they become easy to reason about. By defining a state for each component, you are also documenting them.</li><li><strong>High testability</strong>: Since UI is just a reflection of the state stored in the core, you can test your components easily by replacing UI with a test class. This test class would simulate the user and dispatch actions into core then validate the resulting state.</li><li><strong>Reusability</strong>: You can develop business logic with no UIKit dependency at all. Therefore it becomes highly reusable between different platforms (iOS, macOS, watchOS, tvOS).</li><li><strong>Detailed bug reports</strong>: You can record user actions with a simple middleware implementation and attach action stack to your bug reports. This would help you reproduce the same exact state that crashed the app and save a lot of time. I mean… A LOT.</li></ul><p>However, this is not to say that Core is superior to every other architecture. There are no “right” way to solve problems in software development; it’s always about requirements and trade-offs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*ZYrSaLwfJbcXfS88jyPklg.gif" /><figcaption>Kent Beck Explaining Trade-Offs</figcaption></figure><p>So to choose the “right” architecture:</p><ul><li>Always keep yourself up to date but avoid <a href="https://blog.daftcode.pl/hype-driven-development-3469fc2e9b22">Hype Driven Development</a>.</li><li>Define your problem well and choose the right trade-offs to solve them.</li><li>And lastly… Avoid Massive-View-Controller — no matter what.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/504/1*5hVDI1CgvGxiC-eyFrKlkA.gif" /></figure><p><strong>Thanks for dropping by!</strong></p><p>Swift implementation for <a href="https://github.com/gokselkoksal/Core"><strong>Core</strong></a> is available on <a href="https://github.com/gokselkoksal/Core">GitHub</a>. Give it a try!</p><p>You are very welcome to share your opinions here or submit issues on GitHub. Help spread the word. ❤️</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a7d769196b0a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/nsistanbul/architecting-ios-apps-with-core-a7d769196b0a">Architecting iOS Apps with “Core”</a> was originally published in <a href="https://medium.com/nsistanbul">NSIstanbul</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>