<?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"><channel><title><![CDATA[Ramy's Blog]]></title><description><![CDATA[Nerdmaster by day 👨🏻‍💻
Hogwarts Geek by night 🧙‍♂️
Jedi Master in another matrix 😎
Chi Sao-er every Friday night 🥷
And a full-time meme addict 🤷‍♂️]]></description><link>https://blog.ahmedramy.me</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1641364756116/PU3Swz_-r.png</url><title>Ramy&apos;s Blog</title><link>https://blog.ahmedramy.me</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 15:05:57 GMT</lastBuildDate><atom:link href="https://blog.ahmedramy.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Implementing DDD: Ubiquitous Language, Domain Expert, and some Boundaries]]></title><description><![CDATA[The Dilemma of a Model
Previously on Implementing DDD, We briefly mentioned that we have so much Models, Domain Models, View Models, Plain Models, Data Models and seems like Models is just a generic word…
And how adding more context feels beneficial ...]]></description><link>https://blog.ahmedramy.me/implementing-ddd-ubiquitous-language-domain-expert-and-some-boundaries</link><guid isPermaLink="true">https://blog.ahmedramy.me/implementing-ddd-ubiquitous-language-domain-expert-and-some-boundaries</guid><category><![CDATA[#Domain-Driven-Design]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[software design]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Thu, 20 Feb 2025 05:40:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739652749463/270f381a-8d6d-498b-ac99-53c88de83ed8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-the-dilemma-of-a-model">The Dilemma of a Model</h2>
<p>Previously on <a target="_blank" href="https://blog.ahmedramy.me/implementing-domain-driven-design-model-domain-model-view-model">Implementing DDD</a>, We briefly mentioned that we have so much Models, Domain Models, View Models, Plain Models, Data Models and seems like Models is just a generic word…</p>
<p>And how adding more context feels beneficial over time.</p>
<h2 id="heading-why-are-we-writing-about-ddd-again">Why are we writing about DDD again?</h2>
<h3 id="heading-answering-the-where-about-writing-your-logic">Answering the “Where” about writing your logic</h3>
<p>Well… Quoting before in the <a target="_blank" href="https://blog.ahmedramy.me/series/architecture-homicide">Architecture Homicide</a> series, I stand firmly by this quote</p>
<blockquote>
<p><a target="_blank" href="https://blog.ahmedramy.me/architecture-homicide#:~:text=Software%20Design%20is%20all%20about%20knowing%20where%20to%20put%20what">"Software Design is all about knowing where to put what"</a></p>
</blockquote>
<p>Being Domain-Driven and being exposed to its concept gives you a better idea about where things should be, being an iOS Software Engineer, the question of “Is this Business or Presentation Logic” is very biased towards putting more logic into Presentation Layer.</p>
<p>Which ends up making your Domain Logic more empty… when it should be the other way around, and this tends to shine when you need to reuse a piece of logic, only to find it being too coupled to its current implementation, so you end up being lazy and just pick the <strong><em>“copy-pasta-driven development”</em></strong></p>
<p><img src="https://preview.redd.it/ozkspfp8nhh51.jpg?width=640&amp;crop=smart&amp;auto=webp&amp;s=923c250c35606e1672294615d5944432ef3aeebd" alt="Does this count? : r/memes" class="image--center mx-auto" /></p>
<h3 id="heading-tightens-the-gap-between-the-tech-amp-business">Tightens the gap between the Tech &amp; Business</h3>
<p>Well… all our code, dandy refactoring, shiny new stuff are there to serve one purpose, which is… providing, solving, benefitting our Business, and to do so, you need to understand more about the problems, live them, and breathe them…</p>
<p>Well probably you wouldn’t be able to, but sometimes you are lucky enough to have what we call…</p>
<h1 id="heading-the-domain-expert">The Domain Expert</h1>
<p>We also touched base a bit previously on the Domain Expert, saying things among the lines of someone who has deep knowledge and experience within a <strong>specific subdomain</strong> of a business rather than the entire industry.<br />While they may not know every detail of the broader business landscape, but they understand the intricacies of their specialized area like the back of their hand.</p>
<h2 id="heading-example-real-estate-agents">Example: Real Estate Agents</h2>
<p>A real estate agent who focuses on <strong>specific neighborhoods or towns</strong> knows everything about the pricing trends, local regulations, and buyer-seller behavior in that area. However, they might not be familiar with real estate practices in another city or country. This specialization allows them to provide <strong>highly accurate insights</strong> and make better business decisions within their domain.</p>
<h2 id="heading-but-what-about-us-software-engineer-folks">But what about us? Software Engineer Folks?</h2>
<p>Well, <strong>Product/Project Managers</strong> often act as domain experts, translating business needs into tech requirements. But hey! <strong>we</strong> can be Domain Experts ourselves too!</p>
<p>When we deeply understand the product, customer pain points, and the problem space beyond just code.</p>
<p>Heck, sometimes you’re that <strong>long-standing person</strong> in the team, you’ve seen the codebase being <strong>re-written twice</strong>, face <strong>rigorous changes</strong>, people <strong>coming &amp; leaving</strong>, making you the expert around the codebase</p>
<p>But, you can be that one expert as well who owns let’s say the Payment Service, you’re aware of <strong>interchange fees, chargeback rates, and fraud detection strategies</strong>, <a target="_blank" href="https://stripe.com/blog/idempotency">Idempotent APIs</a> &amp; real-life problems that are not immediately clear to others who lack experience.</p>
<p>This makes you a far more valuable individual than one who just implements payment APIs without context.</p>
<h1 id="heading-the-ubiquitous-language">The Ubiquitous Language</h1>
<p>At first glance, <strong>Ubiquitous Language</strong> might seem like a fancy term for “common language.” But in <strong>Domain-Driven Design (DDD)</strong>, it’s much more—it’s a <strong>shared vocabulary</strong> that aligns everyone, from developers to business stakeholders, ensuring clarity and consistency when discussing the domain.</p>
<h2 id="heading-so-why-the-fanciness-why-is-it-so-important"><strong>So Why the fanciness, Why is it so Important?</strong></h2>
<p>Well… excuse the french, but in a company with different departments, <strong>engineering, product, marketing, design, data</strong>… they all talk about the product, right?</p>
<p>but each often speak <strong>different dialects, different linguistics</strong> of the same language.</p>
<p>For example, speaking of our normal end user of the system (any system).</p>
<p>• <strong>Marketing</strong> calls it “a lead.”</p>
<p>• <strong>Product</strong> calls it “a potential customer.”</p>
<p>• <strong>Engineering</strong> calls it “a user.”</p>
<p>• <strong>Data science</strong> calls it “an entity with attributes X, Y, and Z.”</p>
<p>Without alignment, miscommunication happens:</p>
<p>• <strong>Marketing</strong> says: “We need to track leads.”</p>
<p>• <strong>Engineering</strong> builds: “A system that tracks sign-ups.”</p>
<p>• <strong>Marketing:</strong> “No, we meant people who showed interest but didn’t sign up yet.”</p>
<p>• <strong>Engineering:</strong> “Wait, that’s different?”</p>
<p><img src="https://content.imageresizer.com/images/memes/WaitWHAT-meme-10.jpg" alt="Wait...WHAT Meme Generator" class="image--center mx-auto" /></p>
<p>You see where the problem is, right?</p>
<p>This gap leads to <strong>wrong assumptions, wasted development cycles, and business misalignment</strong>. <strong>Ubiquitous Language ensures that when we say a term, everyone understands exactly what it means.</strong></p>
<p>Which takes us to a very important part…</p>
<blockquote>
<p>DDD is never about just how you write code, DDD is like Agile, it starts way back before any line of code is written, it starts at the problem first, understanding it, aligning over our grasp of it, if you deal with it as a purely technical book, it would fail you.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739653342028/38529ea6-a29c-443c-a969-65c1f8d4efed.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-when-user-becomes-a-problem">When “User” Becomes a Problem</h2>
<blockquote>
<p>Ahh… the “User” model… every iOS codebase has one of those</p>
</blockquote>
<p><em>“User”</em> is one of those <strong>vague, overused words</strong> that mean different things in different contexts. Consider a <strong>Food Delivery App</strong>:</p>
<p>• A <strong>pilot</strong> delivering food is a user.</p>
<p>• A <strong>customer</strong> waiting for food is a user.</p>
<p>• A <strong>restaurant owner</strong> managing orders is a user.</p>
<p>• A <strong>moderator</strong> handling complaints is a user.</p>
<blockquote>
<p>If we define all of that under one big umbrella and give it a name “User”, then boy we’re basically on a recipe for a <a target="_blank" href="https://refactoring.guru/refactoring/smells/bloaters">bloater</a></p>
</blockquote>
<h3 id="heading-isolating-contexts-helps"><strong>Isolating Contexts Helps</strong></h3>
<p>Instead of just “User,” we define <strong>context-specific roles</strong>:</p>
<p>• Customer – Places orders</p>
<p>• Courier – Delivers orders</p>
<p>• RestaurantOwner – Manages a restaurant</p>
<p>• Admin – Moderates disputes</p>
<p>This opens up our system to an interesting way of developing, <a target="_blank" href="https://www.youtube.com/watch?v=cCZ00b_RNyc">type-driven development</a>, where in short, the type Customer is only allowed to do specific sort of actions, which are only available to Customer, while for example, a customer can’t manage a restaurant</p>
<p>But this takes me to another question actually…</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🤔</div>
<div data-node-type="callout-text">Does This Conflict with “User” as an Entity in the Permission Domain?</div>
</div>

<p>Not necessarily. In <strong>Authentication &amp; Permissions</strong>, or sometimes “<strong>Identity</strong>”, “User” often refers to a system-wide entity with login credentials, sometimes access level to do a certain tasks. But in <strong>Domain Modeling</strong>, it’s better to give meaningful names to roles and entities, not only for the sake of avoiding confusions, but this allows us to rationale better about the context of this entity.</p>
<p>For example:</p>
<p>• User (Identity Service) → A system account.</p>
<p>• Customer, Courier, Admin (Domain Layer) → Roles with different behaviors.</p>
<p>This separation avoids ambiguity while maintaining the flexibility of a unified authentication system.</p>
<h1 id="heading-isolating-contexts-amp-creating-them"><strong>Isolating Contexts &amp; Creating Them</strong></h1>
<p>One of the core ideas in <strong>DDD</strong> is that a business is <strong>not one monolithic model</strong>, but rather <strong>multiple bounded contexts</strong> with their own <strong>language and rules</strong>.</p>
<p>Example: A <strong>Marketplace App</strong></p>
<p>• The <strong>Buying Context</strong> uses terms like Cart, Order, Checkout.</p>
<p>• The <strong>Selling Context</strong> uses terms like Listing, Inventory, Earnings.</p>
<p>• The <strong>Delivery Context</strong> uses terms like Courier, ETA, Drop-off Location.</p>
<p>These contexts might talk to each other, but they <strong>don’t share the same meaning</strong> for every entity. An <strong>“Order” in the Buyer Context</strong> is a purchase, while an <strong>“Order” in the Courier Context</strong> is a delivery task.</p>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>We touched-base about Bounded Contexts a bit, but starting from the next blog, we will be more focused over having a simple project where we start learning more about the book in flexible manner</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🤔</div>
<div data-node-type="callout-text">A good question to end this blog with, doesn’t having multiple representation of the “User” create some code duplication between the layers?</div>
</div>

<p>That’s a question to ponder about, so until next post!</p>
<p><img src="https://images7.memedroid.com/images/UPLOADED596/669e5987cdba9.jpeg" alt="The best Adios memes :) Memedroid" class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Implementing DDD: Domain Modeling]]></title><description><![CDATA[Hey everyone, back with another one series again!
This time, I reeeeeally wanted to re-inforce my learning from “Implementing Domain-Driven Design” book as a way of documenting my learning journey with the book!

So, let’s get started already! 😆
Bri...]]></description><link>https://blog.ahmedramy.me/implementing-domain-driven-design-model-domain-model-view-model</link><guid isPermaLink="true">https://blog.ahmedramy.me/implementing-domain-driven-design-model-domain-model-view-model</guid><category><![CDATA[#Domain-Driven-Design]]></category><category><![CDATA[software design]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Wed, 22 Jan 2025 20:25:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739652639746/abca46d3-8780-4b66-aa09-b83cad93fee8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey everyone, back with another one series again!</p>
<p>This time, I reeeeeally wanted to re-inforce my learning from “<a target="_blank" href="https://www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577">Implementing Domain-Driven Design</a>” book as a way of documenting my learning journey with the book!</p>
<p><img src="https://m.media-amazon.com/images/I/41l5OZxjiJL._SY445_SX342_.jpg" alt="Implementing Domain-Driven Design" class="image--center mx-auto" /></p>
<p>So, let’s get started already! 😆</p>
<h1 id="heading-brief-about-ddd-introduction">Brief about DDD Introduction</h1>
<p>First let’s discuss what’s Domain-Driven Design, Domain Expertise and then move from there to the Development part, our part!</p>
<h2 id="heading-whats-a-domain">What’s a Domain</h2>
<p>So, what’s a domain?</p>
<p><img src="https://i.pinimg.com/originals/ed/ad/d6/edadd67950ed04eec08efaa029f14495.jpg" alt="sukuna's domain" class="image--center mx-auto" /></p>
<blockquote>
<p>Nope, not this</p>
</blockquote>
<p>A domain, is a problem, like in CAFU, FUEL delivery, that’s our <strong>Core Domain</strong>, where each of our work one way or another revolves around, affects, branches out of it</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737486520719/8621c078-866a-4773-b9cc-2a7f5337fd87.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-subdomain-whats-that-again">Subdomain? What’s that again?</h2>
<p>So yea, we did mention that a domain represents a problem, but as you might have guessed, a Subdomain is like part of that domain, hence the “Sub” part prefixing the word 🤷‍♂️</p>
<p>Okay, but still, why is that a thing you might ask?</p>
<blockquote>
<p>“because a lot of software developers think it’s clever to bake everything possible into one system.”<br />— <strong>Vaughn Vernon “Implementing Domain-Design”</strong></p>
</blockquote>
<p>Well… yea, exactly, seems familiar to the <strong>SRP</strong> a bit, but breaking domains down into subdomains make the problem you wanna solve more manageable, and simpler, but to do so, this requires severe understanding of the problem/domain you’re trying to solve/improve, and usually requires an expert, a Domain Expert!</p>
<h2 id="heading-whos-the-expert-the-domain-expert">Who’s the Expert? The Domain Expert!</h2>
<p>being Domain-Driven, is all about living and breathing FUEL Delivery, knowing the customer’s pains, knowing the pilot’s pains, knowing very well what problems a customer may face, and what he thinks about when he faces them, and hence, be able to solve problems that are related to your domain</p>
<p>Familarizing yourself with the processes around delivering fuel, and hence become a Domain Expert</p>
<p>A domain expert may not specifically be us programmers/engineers, we have the product team for that, we have the founder, or probably someone we may have never met, however, having that person in your team and absorbing his knowledge about it, massively allows you to understand the domain and take better technical decisions</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737486447681/b0a4325a-dccd-4501-a5b6-690d0e2de457.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-why-is-this-important">Why is this important?</h2>
<p>When we start working, we need this guy. This is a person whom we depend on while developing, planning, and designing because at the cornerstone of our work, it’s very important to think about the problem and learn its edges and angles, so when we start developing (providing a solution), we make sure we solve the problem correctly</p>
<p>And when we try doing TDD or BDD, our domain knowledge allows us to formulate better acceptance criteria, which may translate to better test cases or better behavior with better integration tests, better challenging to the requirements, better suggestions and designs that really clicks with our users in terms of UX</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🤔</div>
<div data-node-type="callout-text">Yea yea, cool, cool, but how can we utilize this in iOS Development or Mobile in General? seems a little… Backend-ish kinda knowledge, Ramy</div>
</div>

<h2 id="heading-enough-were-here-for-models">Enough, We’re here for MODELS!</h2>
<p>So, coming from this brief background, as this will serve future blog entries, let’s go back to square 1</p>
<p>MVC, we get the View, we get the Controller, but why or what the heck is a model, and why is it called “THAT”?</p>
<p>This was actually discussed in Head First: Design Patterns, MVC section</p>
<p>The book goes by explaining the fact that no one liked the word “model”, because it didn’t make sense</p>
<p>A Model for what? is it the feature? is it the View? Is it some logic, or what???</p>
<h3 id="heading-what-exactly-is-a-model">What exactly is a Model?</h3>
<p>A Model is best described as, a "simplification", an interpretation of an abstracted real "thing", often you'd hear it at first as a "blueprint" for something that would solve a problem at hand, without caring much for details outside what it means</p>
<p>For example, the MVC recommended by Apple, regardless of the communication directions or patterns it suggested (be it notifications or delegates), it described logic. If you watch the first 3 videos of CS193P on YouTube, you will indeed find that the ‘M’ here is a place for logic, purely logic</p>
<p>Does that make it a “Logic” Model? maybe, does that make it a helper Model? Maybe</p>
<p>But in the terminology of design, this can go as the following names</p>
<ul>
<li><p>Domain Model</p>
</li>
<li><p>Usecase</p>
</li>
<li><p>Interactor</p>
</li>
<li><p><a target="_blank" href="https://www.swiftbysundell.com/articles/logic-controllers-in-swift/">Logic Controller</a></p>
</li>
</ul>
<p>But what should we call it?</p>
<h3 id="heading-what-to-call-a-model">What to call a model?</h3>
<p>According to Vaughn Vernon's "Implementing Domain-Driven Design," it's essential to differentiate between the execution of business logic and the domain model itself.</p>
<p>A <strong>domain model</strong> should:</p>
<ol>
<li><p>Be focused on representing business concepts.</p>
</li>
<li><p>Be independent of specific application logic.</p>
</li>
<li><p>Capture the essence of the problem domain.</p>
</li>
</ol>
<p>In contrast, application logic (e.g., workflows, orchestration) belongs to <strong>application services</strong>, which interact with the domain model to achieve business goals.</p>
<h2 id="heading-key-takeaways">Key Takeaways</h2>
<p>Understanding the distinction between domain models and application services allows us to:</p>
<ul>
<li><p>Keep our domain logic clean and focused.</p>
</li>
<li><p>Ensure our application is flexible and easier to maintain.</p>
</li>
<li><p>Align our code with real-world business needs.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Patterns: Command + Siri]]></title><description><![CDATA[Yes, it’s me again. I know you’re shocked, so am I. This post totally breaks my record of ‘one-and-done’ blog posts. 🤷‍♂️
I’m seriously surprised I’ve followed through. But hey, whenever the magical words Software Design, Optimization, Time-saving, ...]]></description><link>https://blog.ahmedramy.me/patterns-command-siri</link><guid isPermaLink="true">https://blog.ahmedramy.me/patterns-command-siri</guid><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Siri]]></category><category><![CDATA[AppIntent]]></category><category><![CDATA[command design pattern]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[Clean Architecture]]></category><category><![CDATA[mvc]]></category><category><![CDATA[MVVM]]></category><category><![CDATA[business logic]]></category><category><![CDATA[modularity]]></category><category><![CDATA[UIkit]]></category><category><![CDATA[SwiftUI]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Fri, 27 Dec 2024 11:49:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735300212728/2224a96d-9aac-4e9b-b853-2e4ecf868736.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Yes, it’s me again. I know you’re shocked, so am I. This post totally breaks my record of ‘one-and-done’ blog posts. 🤷‍♂️</p>
<p>I’m seriously surprised I’ve followed through. But hey, whenever the magical words <em>Software Design</em>, <em>Optimization</em>, <em>Time-saving</em>, and <em>Automation</em> get thrown into the mix, my gears start turning. We’re about to merge everything we love—Command Patterns, reuse, composability, <em>and…</em> Siri—for a healthy dose of engineering craziness.</p>
<p><img src="https://media.tenor.com/Cml8_--WKGMAAAAM/arcane-jinx-doing-something.gif" alt class="image--center mx-auto" /></p>
<p>In our <a target="_blank" href="https://blog.ahmedramy.me/patterns-commands">previous post on the Command Pattern</a>, we explored how the pattern looks in both <strong>MVC</strong> and <strong>MVVM</strong>, using <strong>UIKit</strong> and <strong>SwiftUI</strong>. We discussed how it helps us avoid the dreaded “Massive View Controller,” and how easy it is to shape everything like Legos to create reusable, composable building blocks. Perfect for containing your precious business logic in a tidy package.</p>
<h2 id="heading-siri-as-a-new-ui-looking-at-it-from-the-right-angle">Siri as a New UI (Looking at It from the Right Angle)</h2>
<p>Today, we’re highlighting how <strong>Siri</strong> can become a new UI if you think about it from the right angle. With <strong>iOS 16</strong>, Siri can be managed via <strong>AppIntents</strong>—more flexible than ever—and the same code can also be used with the Shortcuts app.</p>
<p>If you were to say, “Hey Siri, use my app to fuel my car,” you could hook into your internal business logic that’s already wrapped inside a Command Pattern. That means Siri is basically another entry point to a well-structured domain. Let’s see how.</p>
<h2 id="heading-appshortcutsprovider-teaching-siri-what-to-listen-to">AppShortcutsProvider: Teaching Siri What to listen to</h2>
<p>Below is a snippet of how you can register shortcuts with Siri. You create an <code>AppShortcutsProvider</code>, define the phrases users might say, and supply an <code>Intent</code> for Siri to call.</p>
<pre><code class="lang-swift"><span class="hljs-meta">@available</span>(iOS <span class="hljs-number">16.0</span>, *)
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SiriShortcutsProvider</span>: <span class="hljs-title">AppShortcutsProvider</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> appShortcuts: [<span class="hljs-type">AppShortcut</span>] {
        <span class="hljs-type">AppShortcut</span>(
            intent: <span class="hljs-type">OrderFuelIntent</span>(),
            phrases: [
                <span class="hljs-string">"Fuel my car"</span>,
                <span class="hljs-string">"Fuel my car at \(.$location)"</span>
            ],
            shortTitle: <span class="hljs-string">"Order Fuel"</span>,
            systemImageName: <span class="hljs-string">"fuelpump"</span>
        )
    }
}
</code></pre>
<h3 id="heading-orderfuelintent">OrderFuelIntent</h3>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">OrderFuelIntent</span>: <span class="hljs-title">AppIntent</span> </span>{
<span class="hljs-comment">// ...</span>
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> title: <span class="hljs-type">LocalizedStringResource</span> = <span class="hljs-string">"Order Fuel"</span>
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> description = <span class="hljs-type">IntentDescription</span>(
        <span class="hljs-string">"Quickly make a Fuel Order with Previously Used Vehicles and Fuel Settings based on latest Order at Home or Work"</span>,
        categoryName: <span class="hljs-string">"Fuel Ordering"</span>,
        searchKeywords: [<span class="hljs-string">"fuel"</span>, <span class="hljs-string">"order"</span>]
    )

    @<span class="hljs-type">Parameter</span>(
        title: <span class="hljs-string">"Location"</span>,
        requestValueDialog: <span class="hljs-string">"Where should the order be?"</span>,
        optionsProvider: <span class="hljs-type">SiriIntentLocationOptionsProvider</span>()
    )
    <span class="hljs-keyword">var</span> location: <span class="hljs-type">Location</span>
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Here, <code>location</code> is a parameter that Siri will prompt for when needed. Once you’ve set up the necessary data, your <code>perform</code> function is where the magic happens.</p>
<h3 id="heading-adding-the-location-enum"><strong>Adding the Location Enum</strong></h3>
<p>Below, you can see how we define the <code>Location</code> enum so Siri knows what “Home” or “Work” actually means in your domain model:</p>
<pre><code class="lang-swift"><span class="hljs-meta">@available</span>(iOS <span class="hljs-number">16.0</span>, *)
<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Location</span>: <span class="hljs-title">String</span>, <span class="hljs-title">CaseIterable</span> </span>{
    <span class="hljs-keyword">case</span> home = <span class="hljs-string">"Home"</span>
    <span class="hljs-keyword">case</span> work = <span class="hljs-string">"Work"</span>
}

<span class="hljs-comment">// MARK: AppEnum</span>

<span class="hljs-meta">@available</span>(iOS <span class="hljs-number">16.0</span>, *)
<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">Location</span>: <span class="hljs-title">AppEnum</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> typeDisplayRepresentation: <span class="hljs-type">TypeDisplayRepresentation</span> {
        <span class="hljs-type">TypeDisplayRepresentation</span>(name: <span class="hljs-string">"Order Location"</span>)
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> caseDisplayRepresentations: [<span class="hljs-type">Location</span>: <span class="hljs-type">DisplayRepresentation</span>] {
        [
            .home: <span class="hljs-type">DisplayRepresentation</span>(title: <span class="hljs-string">"Home"</span>),
            .work: <span class="hljs-type">DisplayRepresentation</span>(title: <span class="hljs-string">"Work"</span>),
        ]
    }
}

<span class="hljs-meta">@available</span>(iOS <span class="hljs-number">16.0</span>, *)
<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">Location</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">mapToDomainModel</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">AddressType</span> {
        <span class="hljs-keyword">switch</span> <span class="hljs-keyword">self</span> {
        <span class="hljs-keyword">case</span> .home:
            <span class="hljs-keyword">return</span> .home
        <span class="hljs-keyword">case</span> .work:
            <span class="hljs-keyword">return</span> .work
        }
    }
}
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🤔</div>
<div data-node-type="callout-text">You might be wondering, why <code>mapToDomainModel</code>, that’s because by isolating 3rd party entities and wrap them into our own, makes us agnostic of their changes, we covered it in more details while discussing <a target="_self" href="https://blog.ahmedramy.me/error-handling-error-flow#heading-apple-pay">Apple Pay during Error Handling</a></div>
</div>

<h2 id="heading-closer-look-at-the-perform-function">Closer look at the <code>perform()</code> function</h2>
<p>Wait a minute…, when you look at the perform function</p>
<pre><code class="lang-swift">    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">perform</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; some <span class="hljs-type">IntentResult</span> &amp; <span class="hljs-type">ProvidesDialog</span> {
        <span class="hljs-comment">// Logic Execution here</span>
    }
</code></pre>
<p>It doesn’t have any parameters, it executes logic based on the struct’s parameters… this looks familiar</p>
<p>This looks like our <code>AsyncUsecase</code> from previously on <a target="_blank" href="https://blog.ahmedramy.me/patterns-commands">Patterns</a>!</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">FetchPaymentMethodsUsecase</span>: <span class="hljs-title">AsyncUsecase</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">PaymentMethod</span>], <span class="hljs-type">BusinessError</span>&gt; {
        <span class="hljs-comment">// 1. Fetch payment methods</span>
        <span class="hljs-comment">// 2. Fetch wallet</span>
        <span class="hljs-comment">// 3. Preselect a favorite</span>
        <span class="hljs-comment">// 4. Disable unsupported methods</span>
        <span class="hljs-comment">// 5. Add Apple Pay (if supported)</span>
    }
}
</code></pre>
<p>When you call <code>execute()</code>, this use case already knows what to do. Siri’s <code>perform()</code> method is basically the same structure—it even returns a type that’s constrained to <code>IntentResult</code>.</p>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMGd2aHhpd3NhOWo1MHV4N3AyOTNrZTl1czJiemRuenUyYWMycnBsMyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/aYDQl23ITdiSdiS7A3/giphy.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-putting-it-all-together-with-siri">Putting It All Together with Siri</h2>
<p>When you think about it this way… perform can be a gathering ground for all the usecases to formulate new functionality!</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">perform</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; some <span class="hljs-type">IntentResult</span> &amp; <span class="hljs-type">ProvidesDialog</span> {
    <span class="hljs-comment">// Step 1: Update session with the selected delivery address</span>
    await <span class="hljs-type">UpdateUserAddressUsecase</span>(newAddress: location.asDomainModel())
        .execute()

    <span class="hljs-comment">// Step 2: Fetch the fuel type for the selected vehicle (98, 95, Diesel, or EV)</span>
    <span class="hljs-keyword">let</span> fuelType = <span class="hljs-keyword">try</span> await <span class="hljs-type">GetFuelTypeForVehicleUsecase</span>()
        .execute()
        .mapError { <span class="hljs-type">SiriIntentError</span>(reason: $<span class="hljs-number">0</span>.errorMessage).whileLogging() }
        .<span class="hljs-keyword">get</span>()

    <span class="hljs-comment">// Step 3: Fetch the selected vehicle</span>
    <span class="hljs-comment">// session is a means of Dependency Injection to mark user's selected preferences</span>
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> vehicle = session.selectedVehicles.first <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">throw</span> <span class="hljs-type">SiriIntentError</span>(reason: <span class="hljs-string">"Couldn't find your selected vehicle"</span>)
    }

    <span class="hljs-comment">// Step 4: Fetch the payment method</span>
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> paymentMethod = payment.session.availablePaymentMethods
        .first(<span class="hljs-keyword">where</span>: { $<span class="hljs-number">0</span> <span class="hljs-keyword">is</span> <span class="hljs-type">SiriPayable</span> }) <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">throw</span> <span class="hljs-type">SiriIntentError</span>(reason: <span class="hljs-string">"Couldn't find a Siri compatible method to pay with"</span>)
    }

    <span class="hljs-comment">// Step 5: Set up the order with a full tank of fuel</span>
    <span class="hljs-keyword">let</span> fuelQuantity: <span class="hljs-type">Quantity</span> = .fullTank
    <span class="hljs-keyword">let</span> product = <span class="hljs-type">CAFUProduct</span>(fuel: fuelType, quantity: fuelQuantity)
    session.order.products = [product]

    <span class="hljs-comment">// Step 6: Get the nearest available time slot for fuel delivery</span>
    <span class="hljs-keyword">let</span> timeslot = <span class="hljs-keyword">try</span> await <span class="hljs-type">NearestTimeSlotUseCase</span>(variantId: fuelType.variantId)
        .execute()
        .mapError { <span class="hljs-type">SiriIntentError</span>(reason: $<span class="hljs-number">0</span>.errorMessage).whileLogging() }
        .<span class="hljs-keyword">get</span>()

    product.timeSlot = timeslot
    payment.select(paymentMethod: paymentMethod)

    <span class="hljs-comment">// Step 7: Create a new order</span>
    <span class="hljs-keyword">try</span> await <span class="hljs-type">CreateOrderUsecase</span>()
        .execute()

    <span class="hljs-comment">// Step 8: Display to the user the order summary</span>
    <span class="hljs-keyword">try</span> await requestConfirmation(
        result: .result(
            view: <span class="hljs-type">OrderSummaryView</span>()
        ),
        confirmationActionName: .order,
        showPrompt: <span class="hljs-literal">false</span>
    )

    <span class="hljs-comment">// Step 9: Place the order after confirmation</span>
    <span class="hljs-keyword">try</span> await <span class="hljs-type">PlaceOrderUsecase</span>()
        .execute()

    <span class="hljs-comment">// Return success message</span>
    <span class="hljs-keyword">let</span> confirmationMessage = <span class="hljs-string">"Awesome! Your fuel order has been placed."</span>
    <span class="hljs-keyword">return</span> .result(dialog: <span class="hljs-type">IntentDialog</span>(stringLiteral: confirmationMessage))
}
</code></pre>
<h3 id="heading-notable-observations">Notable Observations</h3>
<ol>
<li><p>We rely on multiple use cases (<em>Commands</em>) such as <code>UpdateUserAddress</code>, <code>GetFuelTypeForVehicleUsecase</code>, etc.</p>
</li>
<li><p>Each use case has a single <code>execute()</code> method which encapsulates a distinct piece of business logic.</p>
</li>
<li><p>Siri calls <code>perform()</code>, which, in turn, calls our chain of commands. This is <em>the</em> definition of modular and reusable code.</p>
</li>
</ol>
<h2 id="heading-how-does-it-look-like">How does it look like?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735298353437/be9bc232-c2d6-4504-bbb4-c047e1901f52.gif" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🤖</div>
<div data-node-type="callout-text">There goes our girl, ordering on the go 🥹</div>
</div>

<h2 id="heading-now-about-testing"><strong>Now About Testing 🧪</strong></h2>
<p>One of the biggest advantages of using the Command Pattern (and a clean architecture approach) is how testable it all becomes. Here’s how you can tackle testing at various levels:</p>
<h3 id="heading-1-testing-each-use-case"><strong>1. Testing Each Use Case</strong></h3>
<ul>
<li><p><strong>Unit Tests</strong>: For each use case (e.g., <code>GetFuelTypeForVehicleUsecase</code>, <code>UpdateUserAddressUsecase</code>), you can write straightforward unit tests that verify the business logic in isolation.</p>
<ul>
<li><p><strong>Mock Dependencies</strong>: If your use case depends on a repository or a network service, inject a mock or fake. This ensures you test the logic without hitting a real backend.</p>
</li>
<li><p><strong>Error Cases</strong>: Test how each use case handles different failure scenarios (e.g., “No internet,” “Invalid vehicle ID,” etc.).</p>
</li>
</ul>
</li>
</ul>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">testGetFuelTypeForVehicle</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> {
    <span class="hljs-comment">// Given</span>
    <span class="hljs-keyword">let</span> vehicle = <span class="hljs-type">Vehicle</span>.stub(...)
    <span class="hljs-keyword">let</span> sut = <span class="hljs-type">GetFuelTypeForVehicleUsecase</span>(vehicle: vehicle, repository: <span class="hljs-type">MockFuelRepository</span>())

    <span class="hljs-comment">// When</span>
    <span class="hljs-keyword">let</span> result = await sut.execute()

    <span class="hljs-comment">// Then</span>
    <span class="hljs-keyword">switch</span> result {
    <span class="hljs-keyword">case</span> .success(<span class="hljs-keyword">let</span> fuelType):
        <span class="hljs-type">XCTAssertEqual</span>(fuelType, .gas98)
    <span class="hljs-keyword">case</span> .failure(<span class="hljs-keyword">let</span> error):
        <span class="hljs-type">XCTFail</span>(<span class="hljs-string">"Expected success, got \(error) instead"</span>)
    }
}
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">You can use SwiftyMocky for it to mock your protocols directly, saves you lots of boilerplate code in the future!</div>
</div>

<h3 id="heading-2-testing-the-siri-integration"><strong>2. Testing the Siri Integration</strong></h3>
<ul>
<li><p><strong>Integration Tests</strong>: Since Siri’s <code>perform()</code> acts as an entry point that orchestrates multiple use cases, you can run an integration test to confirm that everything plays nicely together.</p>
<ul>
<li><p><strong>Mock the Siri Environment</strong>: Apple doesn’t provide a direct unit test harness for SiriKit or AppIntents in Xcode. However, you can abstract away the domain logic from the Siri layer. Then, test the domain logic in a normal Xcode test target.</p>
</li>
<li><p><strong>Automated UI Testing (Optional)</strong>: If you want to test the voice-driven flow, you might consider an automated test setup (like UI tests), but that can get tricky. Usually, verifying your domain logic + making sure your Siri Intents are valid with the “Shortcuts” integration is enough.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-3-testing-the-flow-with-dependency-injection"><strong>3. Testing the Flow with Dependency Injection</strong></h3>
<ul>
<li><p><strong>Dependency Injection</strong>: Notice in the example code, we keep referencing <code>session</code> or <code>payment</code>. In production, these might be singletons or injected services. For tests, you can provide test doubles—like <code>TestSession</code> or <code>MockPaymentService</code>—to control the data.</p>
</li>
<li><p><strong>Verifying Side Effects</strong>: If <code>CreateOrderUsecase</code> triggers a network call or updates a database, you can check your mock objects to see if the correct methods were called with the right parameters.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The <strong>Command Pattern</strong> is powerful. By encapsulating each piece of business logic into its own “command,” we avoid cluttering our UI or Siri integration with domain knowledge. Siri (thanks to <strong>AppIntents</strong>) is just another consumer of our well-structured domain. That means:</p>
<ul>
<li><p><strong>Easier maintenance</strong>: We only need to manage business logic in one place.</p>
</li>
<li><p><strong>Better testing</strong>: Each Command/Usecase can be tested independently.</p>
</li>
<li><p><strong>Less code duplication</strong>: The same commands are called whether you’re interacting via the app’s UI <em>or</em> Siri.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Patterns: Commands]]></title><description><![CDATA[Hello, world! 👋 It’s been a while since I’ve shared something with you all, and today feels like the perfect day to dive into an old, yet very relevant, topic. Let’s talk about a classic architectural debate in iOS development and how its lessons ca...]]></description><link>https://blog.ahmedramy.me/patterns-commands</link><guid isPermaLink="true">https://blog.ahmedramy.me/patterns-commands</guid><category><![CDATA[iOS]]></category><category><![CDATA[SwiftUI]]></category><category><![CDATA[architecture]]></category><category><![CDATA[command design pattern]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Fri, 15 Nov 2024 13:32:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731677075994/85d2b822-d4d7-4fa1-8391-c3e5186f5cb5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello, world! 👋 It’s been a while since I’ve shared something with you all, and today feels like the perfect day to dive into an old, yet very relevant, topic. Let’s talk about a classic architectural debate in iOS development and how its lessons can help us avoid pitfalls with SwiftUI.</p>
<hr />
<h2 id="heading-the-problem-massive-view-controllers-mvcs-evil-twin">The Problem: Massive View Controllers (MVC’s Evil Twin)</h2>
<p>Before 2019, many of us were deep in the trenches of the infamous <a target="_blank" href="https://swifting.io/2016/09/07/Architecture-Wars-A-New-Hope.html"><strong>Architecture Wars</strong></a>, battling over patterns like MVC, MVVM, and VIPER. At the heart of it all was the struggle to properly <strong>separate concerns</strong> in our codebase.</p>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMXJnajJyNWo4ejdqZ25yaHBwa2kzM3BobG85cGh0eXpnYnY5dmNobyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/f9S2wp0VSJu0pgWnZt/giphy.gif" alt class="image--center mx-auto" /></p>
<p>We weren’t mad at <strong>MVC</strong> itself; we were frustrated by how easily it evolved into <strong>Massive View Controllers</strong>.</p>
<p>Let’s break it down. The humble <code>UIViewController</code> often became an all-you-can-eat buffet of logic, responsible for tasks like:</p>
<ol>
<li><p>Navigation logic</p>
</li>
<li><p>UI updates</p>
</li>
<li><p>Presentation logic</p>
</li>
<li><p>Business logic</p>
</li>
<li><p>Network requests</p>
</li>
<li><p>Caching mechanisms</p>
</li>
</ol>
<p>Before we knew it, our view controllers ballooned to over 1,000 lines of code. 🥲</p>
<hr />
<h3 id="heading-was-it-really-mvcs-fault">Was It Really MVC’s Fault?</h3>
<p>Nope! As <a target="_blank" href="https://www.linkedin.com/in/dave-poirier-a9b25a9/?lipi=urn%3Ali%3Apage%3Ad_flagship3_pulse_read%3BYJ%2FKvbiGSxCZDGmOnnAsTQ%3D%3D">Dave</a> delves into brilliantly in <a target="_blank" href="https://www.linkedin.com/pulse/apple-creating-massive-swiftui-views-dave-poirier-od7we/">this article</a>, the issue wasn’t the MVC pattern itself. It was <em>our interpretation</em> of where things should live.</p>
<p>Apple always recommended <strong>breaking things down</strong>:</p>
<ul>
<li><p><strong>Models:</strong> Split them into smaller reusable units.</p>
</li>
<li><p><strong>View Controllers:</strong> Divide and conquer! Use child view controllers.</p>
</li>
<li><p><strong>Views:</strong> Decompose complex layouts into smaller, reusable pieces.</p>
</li>
</ul>
<p>With SwiftUI, Apple continues to encourage <strong>breaking things down further</strong>, promoting better modularity.</p>
<p>When we follow that, we avoid falling into the same rabbit-hole over and over again</p>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExcmlwcmRwMGhlMmsxYTczZ3F2aGo3ZnZ5OXNxazF2ZXN4bDNnaW5waCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/T1GWTCSrTr2tnsvq4k/giphy.gif" alt class="image--center mx-auto" /></p>
<p>But today, I want to focus on tackling <strong>logic</strong>, or the "M" in any MVx pattern. Enter: <strong>Command Pattern</strong>.</p>
<hr />
<h2 id="heading-the-command-pattern-a-fresh-perspective">The Command Pattern: A Fresh Perspective</h2>
<p>At its core, the <strong>Command Pattern</strong> is about encapsulating logic into small, focused units. Think of it as a class (or struct) with a single responsibility: an <code>execute()</code> method.</p>
<p>Here’s an example:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">FetchPaymentMethods</span>: <span class="hljs-title">AsyncUsecase</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">PaymentMethod</span>], <span class="hljs-type">BusinessError</span>&gt; { 
        <span class="hljs-comment">// 1. Fetch payment methods</span>
        <span class="hljs-comment">// 2. Fetch wallet</span>
        <span class="hljs-comment">// 3. Preselect a favorite</span>
        <span class="hljs-comment">// 4. Disable unsupported methods</span>
        <span class="hljs-comment">// 5. Add Apple Pay (if supported)</span>
    }
}
</code></pre>
<p>This does a few things immediately:</p>
<ol>
<li><p><strong>Keeps the view controller or SwiftUI view clean.</strong></p>
</li>
<li><p><strong>Follows the Single Responsibility Principle (SRP).</strong> 🚀</p>
</li>
<li><p><strong>Improves readability and maintainability.</strong></p>
</li>
</ol>
<p>If this logic grows too complex, you can further break it down into smaller commands:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">FetchPaymentMethods</span>: <span class="hljs-title">AsyncUsecase</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">PaymentMethod</span>], <span class="hljs-type">BusinessError</span>&gt; { 
        await [
            <span class="hljs-type">FetchWallet</span>(),
            <span class="hljs-type">PreselectFavorite</span>(),
            <span class="hljs-type">DisableUnsupportedMethods</span>(),
            <span class="hljs-type">AddApplePayIfSupported</span>()
        ].asyncForEach { await $<span class="hljs-number">0</span>.execute() }
    }
}
</code></pre>
<hr />
<h2 id="heading-why-use-the-command-pattern">Why Use the Command Pattern?</h2>
<p><strong>Modular Expansion:</strong> Need to add a new step? No problem—just add a new command. Old implementations remain untouched.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🥳</div>
<div data-node-type="callout-text"><em>Achievement Unlocked: Open-Closed Principle (OCP).</em> 🚀</div>
</div>

<p><strong>Composability:</strong> Combine multiple commands to create complex workflows. For instance, placing an order might look like this:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">PlaceOrder</span>: <span class="hljs-title">AsyncUsecase</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Void</span>, <span class="hljs-type">BusinessError</span>&gt; {
        await [
            <span class="hljs-type">ApplyPromoCode</span>(),
            <span class="hljs-type">UpdatePaymentMethod</span>(),
            <span class="hljs-type">ValidateCheckout</span>()
        ].asyncForEach { await $<span class="hljs-number">0</span>.execute() }
    }
}
</code></pre>
<p><strong>Testability:</strong> Each command is a small, isolated unit—perfect for writing focused unit tests.</p>
<p><strong>Reusability:</strong> Commands are decoupled from the UI, making them reusable across different platforms, whether you’re building for iOS, macOS, or even CLI apps. 😄</p>
<hr />
<h2 id="heading-a-word-on-swiftui">A Word on SwiftUI</h2>
<p>While this pattern shines in UIKit, it’s equally valuable in SwiftUI. With SwiftUI’s declarative nature, logic can creep into views if you’re not careful. Using the <strong>Command Pattern</strong> ensures your business logic remains in its rightful place—clean, testable, and reusable.</p>
<h1 id="heading-example-time">Example Time</h1>
<p><img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExeDBrdDF2ZWQxdzNpZDkybXFmOGJpYmJuMWE4NXIweGxrMmp2azhneiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/10bxTLrpJNS0PC/giphy.gif" alt class="image--center mx-auto" /></p>
<p>So, now that we’re almost done, let’s give some examples about how can we make this possible</p>
<h2 id="heading-uikit-where-the-model-is-the-one-in-command">UIKit: Where the Model is the one in Command</h2>
<p>In MVC, the Model is responsible for managing the app’s data. By incorporating the Command Pattern, we can offload specific business logic into dedicated commands, keeping the Model lean and maintainable.</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Command to encapsulate the business logic</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">FetchPaymentMethodsUsecase</span>: <span class="hljs-title">AsyncUsecase</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">PaymentMethod</span>], <span class="hljs-type">BusinessError</span>&gt; {
        <span class="hljs-comment">// 1. Fetch payment methods</span>
        <span class="hljs-comment">// 2. Process wallet logic</span>
        <span class="hljs-comment">// 3. Preselect favorite payment method</span>
        <span class="hljs-comment">// 4. Disable unsupported methods</span>
        <span class="hljs-comment">// 5. Add Apple Pay if available</span>
    }
}

<span class="hljs-comment">// Model using the command</span>
<span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentModel</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> paymentMethods: [<span class="hljs-type">PaymentMethod</span>] = []
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> error: <span class="hljs-type">BusinessError?</span>
    <span class="hljs-comment">// Model communicates his output via Callbacks</span>
    <span class="hljs-comment">// This acts as a contract of communication and what to expect from the Model</span>
    <span class="hljs-comment">// Defining this is super important to reason about, as it defines how we can test our models</span>
    <span class="hljs-keyword">var</span> onPaymentMethodsUpdate: (([<span class="hljs-type">PaymentMethod</span>]) @<span class="hljs-type">MainActor</span> @<span class="hljs-type">Sendable</span> -&gt; <span class="hljs-type">Void</span>) 
    <span class="hljs-keyword">var</span> onError: ((<span class="hljs-type">BusinessError</span>) @<span class="hljs-type">MainActor</span> @<span class="hljs-type">Sendable</span> -&gt; <span class="hljs-type">Void</span>) 

    <span class="hljs-keyword">init</span>(…) { … }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchPaymentMethods</span><span class="hljs-params">()</span></span> async {
        <span class="hljs-keyword">let</span> result = await <span class="hljs-type">FetchPaymentMethodsUsecase</span>().execute()
        <span class="hljs-comment">// Further Business Logic may happen here, </span>
        <span class="hljs-comment">// like composing different Usecases together</span>
    }
}

<span class="hljs-comment">// ViewController (Controller in MVC)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentViewController</span>: <span class="hljs-title">UIViewController</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> paymentModel: <span class="hljs-type">PaymentModel</span>

    <span class="hljs-keyword">init</span>(…) { 
       paymentModel = <span class="hljs-keyword">init</span>(onPaymentMethodsUpdate: {…}, onError: {…})
       <span class="hljs-keyword">super</span>.<span class="hljs-keyword">init</span>(…)
    }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">viewDidLoad</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">super</span>.viewDidLoad()
        <span class="hljs-type">Task</span> { await paymentModel.fetchPaymentMethods() }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">displayPaymentMethods</span><span class="hljs-params">()</span></span> { 
       <span class="hljs-comment">// Here we can map/translate/render our Business Data Models towards UI representations</span>
    }
}
</code></pre>
<hr />
<h2 id="heading-swiftui-where-the-model-is-still-the-one-in-command">SwiftUI: Where the Model is <em>still</em> the one in Command</h2>
<p>In MVVM, the ViewModel acts as the mediator between the view and model. The Command Pattern fits naturally here, allowing the ViewModel to delegate logic cleanly.</p>
<pre><code class="lang-swift"><span class="hljs-comment">// Command remains the same</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">FetchPaymentMethodsUsecase</span>: <span class="hljs-title">AsyncUsecase</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">PaymentMethod</span>], <span class="hljs-type">BusinessError</span>&gt; {
        <span class="hljs-comment">// Business logic as before</span>
    }
}

<span class="hljs-comment">// Model using the command</span>
<span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentModel</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> paymentMethods: [<span class="hljs-type">PaymentMethod</span>] = []
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> error: <span class="hljs-type">BusinessError?</span>
    <span class="hljs-comment">// Model communicates his output via Callbacks</span>
    <span class="hljs-comment">// This acts as a contract of communication and what to expect from the Model</span>
    <span class="hljs-comment">// Defining this is super important to reason about, as it defines how we can test our models</span>
    <span class="hljs-keyword">var</span> onPaymentMethodsUpdate: (([<span class="hljs-type">PaymentMethod</span>]) @<span class="hljs-type">MainActor</span> @<span class="hljs-type">Sendable</span> -&gt; <span class="hljs-type">Void</span>) 
    <span class="hljs-keyword">var</span> onError: ((<span class="hljs-type">BusinessError</span>) @<span class="hljs-type">MainActor</span> @<span class="hljs-type">Sendable</span> -&gt; <span class="hljs-type">Void</span>) 

    <span class="hljs-keyword">init</span>(…) { … }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchPaymentMethods</span><span class="hljs-params">()</span></span> async {
        <span class="hljs-keyword">let</span> result = await <span class="hljs-type">FetchPaymentMethodsCommand</span>().execute()
        <span class="hljs-comment">// Further Business Logic may happen here, </span>
        <span class="hljs-comment">// like composing different Usecases together</span>
    }
}

<span class="hljs-comment">// ViewModel in MVVM</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> paymentMethods: [<span class="hljs-type">PaymentMethodUI</span>] = []
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> error: <span class="hljs-type">PresentableError?</span>

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">let</span> model: <span class="hljs-type">PaymentModel</span>

    <span class="hljs-keyword">init</span>(…) { … }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchPaymentMethods</span><span class="hljs-params">()</span></span> async {
        <span class="hljs-keyword">let</span> result = await <span class="hljs-type">FetchPaymentMethodsUsecase</span>().execute()
        <span class="hljs-comment">// Further Business Logic may happen here, </span>
        <span class="hljs-comment">// like composing different Usecases together</span>
    }
}

<span class="hljs-comment">// View in SwiftUI (MVVM)</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">PaymentView</span>: <span class="hljs-title">View</span> </span>{
    @<span class="hljs-type">StateObject</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> viewModel = <span class="hljs-type">PaymentViewModel</span>()

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">List</span>(viewModel.paymentMethods) { method <span class="hljs-keyword">in</span>
            <span class="hljs-type">Text</span>(method.title)
        }.task { 
            await viewModel.fetchPaymentMethods()
        }.alert(item: $viewModel.error) { … }
    }
}
</code></pre>
<h2 id="heading-key-takeaways"><strong>Key Takeaways</strong></h2>
<p>1. In <strong>MVC</strong>, the Command Pattern helps encapsulate business logic in the Model, keeping the ViewController clean and focused on its primary responsibilities.</p>
<p>2. In <strong>MVVM</strong>, the Command Pattern allows the ViewModel to manage logic, enabling clear communication between the View and Model.</p>
<p>By using the Command Pattern with either architecture, you enhance modularity, testability, and maintainability.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🤔</div>
<div data-node-type="callout-text">Key Question: Notice that Model is same in both approaches? while in MVC the UI mapping takes place within the ViewController, while in MVVM in takes place within the ViewModel?</div>
</div>

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Having it as such, decouples the View code from presentation logic, allowing for possibility of reusing it across different UI frameworks (be it UIKit, SwiftUI, macOS, watchOS, heck… even CLI if you want)</div>
</div>

<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>SwiftUI might feel like a fresh start, but without discipline, the same old traps of massive files and tangled logic await us. By adopting patterns like <strong>Command</strong>, we can keep our apps clean, maintainable, and a joy to work on.</p>
<hr />
<p>What do you think? Have you used the <strong>Command Pattern</strong> in your projects? Let’s discuss in the comments below! 🚀</p>
]]></content:encoded></item><item><title><![CDATA[Productivity Hacks: Terminal Warped]]></title><description><![CDATA[A New day... a new productive day where my tiny blog gains a new post!
https://tenor.com/view/terrific-tuesday-gif-25021333
 
Today is a bit of a quick one, its about a productivity tip you can imply if you work a lot with terminals, so without furth...]]></description><link>https://blog.ahmedramy.me/productivity-hacks-terminal-warped</link><guid isPermaLink="true">https://blog.ahmedramy.me/productivity-hacks-terminal-warped</guid><category><![CDATA[Productivity]]></category><category><![CDATA[Script]]></category><category><![CDATA[terminal]]></category><category><![CDATA[automation]]></category><category><![CDATA[AI]]></category><category><![CDATA[chatgpt]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Sat, 16 Dec 2023 19:59:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692729923863/4658cb62-2c42-4924-9447-d386c9861fe9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A New day... a new productive day where my tiny blog gains a new post!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://tenor.com/view/terrific-tuesday-gif-25021333">https://tenor.com/view/terrific-tuesday-gif-25021333</a></div>
<p> </p>
<p>Today is a bit of a quick one, its about a productivity tip you can imply if you work a lot with terminals, so without furtherado, let's hop into it!</p>
<h1 id="heading-problem">Problem</h1>
<p><img src="https://www.lifewire.com/thmb/oi30QVmTdyOZskNqWVlekY2n5cw=/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/how-to-save-terminal-commands-on-a-mac-51877871-904e2096e704422ab3fd353574322dc9.jpg" alt="How to Save Terminal Commands on a Mac" /></p>
<p>So we're all familiar with our vanilla macOS terminal, and familiar with the frustration of its readability, basicness, and... the 'shortcuts' we're so used to on Xcode that is... simply not there... ☹️</p>
<p>Perhaps you've also seen articles that reference oh-my-zsh, which offers you tons of plugins and can be paired with <code>iTerm2</code>, but the only thing is... it takes too much time to set up, and can break your environment... 🫣</p>
<p><img src="https://i.imgflip.com/7wkuk9.jpg" alt class="image--center mx-auto" /></p>
<h2 id="heading-enters-warp">Enters Warp</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692727957160/97352b9c-eefb-474a-b152-c3063067e5b2.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://app.warp.dev/referral/PXNV3Y">Warp</a> is an awesome terminal, I used to spend time on my terminal adding auto-complete plugins, fig, smart <code>cd &amp; ls</code>, memorize some commands in a side note</p>
<p>But the amount of time saved through its AI or plugins is so big!</p>
<p>Out of the box you get exciting stuff like syntax highlighting, smart suggestions from AI, and your little AI helper when things go wrong (which is not there for a manual customized approach)</p>
<h1 id="heading-my-personal-favorite">My personal favorite?</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1692730052157/f45151a3-2900-4a24-8677-c7f22841f3a7.png" alt class="image--center mx-auto" /></p>
<p>It's hard to decide between being able to run multiple commands and edits at the same time (and get notified at the end)</p>
<p>or when facing a weird error, one can just ask warp 🤔</p>
<h1 id="heading-thats-a-wrap">That's a Wrap!</h1>
<div data-node-type="callout">
<div data-node-type="callout-emoji">😆</div>
<div data-node-type="callout-text">Pun Intended</div>
</div>

<p>Well, it might have been a short one, but this tool has lots of good features which you can def. check here</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=XWQY8LgkiXM">https://www.youtube.com/watch?v=XWQY8LgkiXM</a></div>
]]></content:encoded></item><item><title><![CDATA[Error Handling: Defined Errors]]></title><description><![CDATA[Back at last!
Hello, Folks!Finally, this series is seeing its ending so I can move to other series!

😶‍🌫
I can hear you, you in the back, mentioning my lack of discipline, and dear kind sir, you're so spot on! 🫡


Well... you might have noticed th...]]></description><link>https://blog.ahmedramy.me/error-handling-defined-errors</link><guid isPermaLink="true">https://blog.ahmedramy.me/error-handling-defined-errors</guid><category><![CDATA[error handling]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Swift]]></category><category><![CDATA[software design]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Wed, 19 Jul 2023 09:38:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689759829986/03ad6ff3-ab04-4d25-8b9c-de6ed289b39e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-back-at-last">Back at last!</h1>
<p>Hello, Folks!<br />Finally, this series is seeing its ending so I can move to other series!</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">😶‍🌫</div>
<div data-node-type="callout-text">I can hear you, you in the back, mentioning my lack of discipline, and dear kind sir, you're so spot on! 🫡</div>
</div>

<p>Well... you might have noticed that async-await does indeed make code much more readable, and easier to handle. and the fact of allowing the compiler to help you define Race Conditions and Non-Thread-safe code via 'Sendable', Nonsendable, Actors, and Structured Concurrency... makes adopting async-await a very common goal for many tech teams these days... and today is a lesson I wanted to share with you what I've learned recently...</p>
<p>but before we start with our learning, I just wanna say...</p>
<p>Alright, Detectives, I've just binged-watched 6 seasons of Brooklyn 99, and today am <strong>Jake</strong> <strong>Peralta</strong>, and today, we are investigating...</p>
<p><strong>Defined Errors</strong> and how they can screw your design... title of your bug report</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1688915018426/b4379572-9cbf-4814-9abb-4a05d8604887.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-problem">Problem?</h1>
<p>The <code>throws</code> keyword in this statement</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchRecentWalletTransactions</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">Transaction</span>] { ... }
</code></pre>
<p>Now, don't get me wrong; after all, this is not an async-await series, nor am I asking you to ignore errors (it's an Error Handling Series after all 😬)</p>
<p>But as innocent, and tiny and so inline with the best practices of Clean Code &amp; Swift Documentation, this keyword, can do you bad in terms of software design and maintainability of your layers...</p>
<h3 id="heading-why-is-it-a-problem">Why is it a problem?</h3>
<p>How many errors can I throw from this method alone?</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">WalletTransactionFetchError</span>: <span class="hljs-title">Error</span> </span>{ 
    <span class="hljs-keyword">case</span> walletAccountNotSetup
    <span class="hljs-keyword">case</span> walletUnavailable(reason: <span class="hljs-type">String</span>)
    <span class="hljs-keyword">case</span> walletOnHold
    <span class="hljs-keyword">case</span> noTransactions
}
</code></pre>
<p>Well, Yep, seems like a good start... but is that all?</p>
<details><summary>Spoiler</summary><div data-type="detailsContent">No</div></details>

<p>You can throw anything that conforms to Error, and for now, that's ok, or so it seemed</p>
<p>Due to not being specific, we lost being specific about what's going wrong, and supplying to our dependents what actually happened, so they have to do some guesswork, and that's where we lost the way, so now we're here, in the crime scene (the codebase), and trying to identify our characters...</p>
<h2 id="heading-the-crime-scene">The Crime Scene</h2>
<ol>
<li><p>The method itself (<strong>Prime Suspect</strong>)</p>
</li>
<li><p>The invokers (<strong>Victims</strong>)</p>
</li>
<li><p>Expectations between layers (<strong>Witnesses</strong>)</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">🤷‍♂</div>
<div data-node-type="callout-text">After all, fetching happens in the Data layer, so you, the business layer may be expecting some fault scenarios, and given you sent an error that is undefined to it, the app goes into an invalid state like...</div>
</div>

<h3 id="heading-suspect-method-implementation">Suspect: Method Implementation</h3>
<p>Mostly here, there won't be much trouble found..., upon fetching, you found that there is an issue, and you begin to map it to the above enum cases, however, worst case scenario, you can say, <code>.walletUnavailable</code> with a reason, right?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684664365223/b88539f0-6477-4e4f-bf14-99b36f41df72.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-victim-invoker">Victim: Invoker</h3>
<p>Like any RPG or a story with multiple protagonists, each has their own side of the story, and let me tell you something, the Invoker is not HAPPY, about it...</p>
<p>I mean, you had <strong>one</strong> job! Fetching the transactions...</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TransactionWidgetViewModel</span> </span>{ 
    ...
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">onAppear</span><span class="hljs-params">()</span></span> async { 
        <span class="hljs-keyword">do</span> {
            async <span class="hljs-keyword">try</span> transactionsUsecase.fetchRecentWalletTransactions()
        } <span class="hljs-keyword">catch</span> <span class="hljs-keyword">let</span> error <span class="hljs-type">WalletTransactionFetchError</span> { 
            <span class="hljs-comment">// some handling</span>
        } <span class="hljs-keyword">catch</span> { 
            <span class="hljs-comment">// Default handling</span>
        }
    }
}
</code></pre>
<p>Now, this went quickly from 'handling the fetch error', to 'guess what broke'</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">😞</div>
<div data-node-type="callout-text">Which sometimes end up with 'something went wrong in the end' and a frustrated user</div>
</div>

<p>The problem here is... if there are multiple error types, that means the method we built above may be doing two things or more... which may be a sign of SRP violation...</p>
<p>Similarly, <strong>the default handling</strong> is another place we would like to avoid...</p>
<p>because if our code reached this point, that means there is an invalid state, the application is currently in, and to quickly recover from it, we map it into a something went wrong error...</p>
<p>Lastly, if we were to handle each case, and if there is a new case that popped up which require its own handling, we might also break the OCP, which is another word for a...</p>
<p><img src="https://media.tenor.com/BiiTsQ_0j7AAAAAC/mendokusai-what-a-drag.gif" alt="Mendokusai What A Drag GIF - Mendokusai What A Drag ..." class="image--center mx-auto" /></p>
<h3 id="heading-witnesses-expectations">Witnesses: Expectations</h3>
<p>Remember the <a target="_blank" href="https://hashnode.com/post/cl8rcyloy000209mneya70zjl"><strong>Error Flow</strong></a> episode?</p>
<p>We were mentioning how each layer would expect an error of some sort from its dependency, or layer... but now that the only thing we get is <code>any Error</code>, we gotta try to see if its the error we're expecting, or just wrap it inside a 'something went wrong', or an object with more metadata to describe it better later on (or not... since its a bit risky and some guess-work is involved)</p>
<p>so... in a nutshell, if we were to summarize all the above in one image... this one does a pretty good job at it 👇</p>
<p><img src="https://i.chzbgr.com/full/9328584960/hBB494AE7/up-big-time-charles-given-your-daily-life-experiences-youre-gonna-have-to-be-more-specific-dill" alt="32 Brooklyn Nine-Nine Memes &amp; Moments For The Superfans - Memebase - Funny  Memes" class="image--center mx-auto" /></p>
<h1 id="heading-solving-the-case-a-fix">Solving the case: A Fix</h1>
<p>Alright, now that we have an idea of what's wrong, let's check an approach that addresses it</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchRecentWalletTransactions</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">Transaction</span>], <span class="hljs-type">WalletTransactionFetchError</span>&gt; { ... }
</code></pre>
<p>A simple, non-fancy, and weird-looking solution would be to return to <code>Result&lt;Success, Failure&gt;</code></p>
<p>The reason for this is I can specify why this method can fail and the scenarios that follow it up... so the invokers can react accordingly</p>
<h3 id="heading-the-invokers-story">The Invoker's Story</h3>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">onAppear</span><span class="hljs-params">()</span></span> async { 
    <span class="hljs-keyword">let</span> result = async transactionUsecase.fetchRecentWalletTransactions()
    <span class="hljs-keyword">switch</span> result { 
        <span class="hljs-keyword">case</span> <span class="hljs-keyword">let</span> .success(...):
            ...
        <span class="hljs-keyword">case</span> <span class="hljs-keyword">let</span> .failure(error):
            handle(fetchError: error)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">handle</span><span class="hljs-params">(fetchError: WalletTransactionFetchError)</span></span> { ... }
</code></pre>
<p>It seems kinda familiar to how we used to handle errors when we depended on callbacks, and the syntax was kinda boring...</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">But the trade-off here is that we have better visibility and control over the errors we have to handle, more over, we are able to limit the amount of modifications</div>
</div>

<h1 id="heading-conclusion">Conclusion</h1>
<p>Now that we have learned Defined Errors and their importance, It's high time I start working on that blog about monitoring the errors and how important this is as a practice 👏</p>
]]></content:encoded></item><item><title><![CDATA[12 Lesson from my 
first Internship]]></title><description><![CDATA[Today was my 25th day at the internship and last day, and this is what I learned
1. Refactoring an anticipated change is always easier than sudden ones
Make a configuration file, make it hold all your constants, and reuse them over the codebase; this...]]></description><link>https://blog.ahmedramy.me/12-lesson-from-my-first-internship</link><guid isPermaLink="true">https://blog.ahmedramy.me/12-lesson-from-my-first-internship</guid><category><![CDATA[Career]]></category><category><![CDATA[life]]></category><category><![CDATA[Life experiences ]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Mon, 03 Apr 2023 21:18:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680556542072/239466b0-e4a1-4d3b-b5dc-03f58ef4abc6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today was my 25th day at the internship and last day, and this is what I learned</p>
<h2 id="heading-1-refactoring-an-anticipated-change-is-always-easier-than-sudden-ones">1. Refactoring an anticipated change is always easier than sudden ones</h2>
<p>Make a configuration file, make it hold all your constants, and reuse them over the codebase; this makes your life easier</p>
<h2 id="heading-2-base-layers-are-good-when-needed">2. Base Layers are good... when needed.</h2>
<p>put in the base layer the main thing and build on it, so if you want to change</p>
<p>the change affects everything rather than go over many things and change</p>
<h1 id="heading-3-less-over-engineering-more-yagni">3. Less Over-Engineering, More YAGNI</h1>
<p>Comments here and there was something I used to do, which is a sign of poor code</p>
<p>if the code is not comprehensible and self-explanatory, then it needs refining</p>
<h1 id="heading-4-stop-and-think-is-it-reusable-and-testable">4. Stop and Think, Is it reusable and testable?</h1>
<p>sometimes you want to add something over and over again, but you need to make sure this thing is testable</p>
<h1 id="heading-5-the-hare-who-lost-to-the-turtle">5. The Hare who lost to the turtle</h1>
<p>Step by step, one of my faults was trying to learn advanced topics to make use of it and build better projects</p>
<p>I was doing it rigorously and well, I still do because I love learning</p>
<p>One day you would see me learning about animations the other learning how to break the array with a race condition and trying to make a deadlock on purpose just to know what is bad.</p>
<p>this is not good sometimes, because you are disturbed, I can do it, I can focus on multiple things at a time and learn everything I see but some people can't and I love learning and teaching what I do with this blog, so things always sink in fast!</p>
<blockquote>
<p>Aaand me from the future disapproves... 😃 well... one was a teenager back then so not judging 😄</p>
</blockquote>
<h1 id="heading-6-avoid-the-hot-names">6. avoid the Hot names</h1>
<p>this was from my Sensei, @YoloAbdo</p>
<p>yea, it sounds cool to say I know how to avoid a cyclic dependency (deadlock); it's cool to say that I made an open-source project</p>
<p>but sometimes <code>cool</code> messes up priorities, and you might learn something that's not important at your knowledge level and leave more important things</p>
<h1 id="heading-7-mvc-doesnt-apply-for-code-only-it-can-apply-for-a-storyboard-too">7. MVC doesn't apply for code only, it can apply for a storyboard too</h1>
<blockquote>
<p>(MVC is Massive View Controller)</p>
</blockquote>
<p>My senior told me that he faced a problem before that made the Xcode unable to even open the project...</p>
<p>which was having tons of screens in one storyboard, which was the main.storyboard (<em>back then</em>)</p>
<p>this resulted in too much information for the XCode to handle (and also the hardware of the MacBook)</p>
<p>so the key to solving it was to utilize the power of xib files and "divide and conquer."</p>
<h1 id="heading-8-tapping-into-alamofires-internals">8. Tapping into Alamofire's internals</h1>
<blockquote>
<p>Don't import something you don't need or do something you can do without importing it (YAGNI)<br />-- Says My Senior</p>
</blockquote>
<p>When I told him I use Alamofire, he told me to forget Alamofire and build my own network layer; this made me tap into Alamofire and get some key things about how it works and what it does, also turning Abdo's layer into native components and removing Alamofire made lots of things clear</p>
<h1 id="heading-9-sometimes-code-is-not-everything">9. Sometimes code is not everything</h1>
<p>you have to make sure that your code serves other things other than functionality, like a good UX and good design is also important; UX is the most important part of your app, so handle it with care</p>
<h1 id="heading-10-think-twice-and-code-once">10. Think twice and Code once</h1>
<p>Sometimes you need to make sure you write best practices and avoid anti-patterns</p>
<p>you would think that it would take time, but actually, <s>clean code</s> well-planned code saves time and meet deadlines rather than your normal clean Ratatouille</p>
<h1 id="heading-11-always-leave-on-good-terms">11. Always leave on good terms</h1>
<p>that's My Friend Ahmed Itman who told me to always leave on good terms even if it was a liability to you so that people would want to work with you</p>
<h1 id="heading-12-expect-nothing-and-you-will-never-be-disappointed">12. Expect nothing, and you will never be disappointed</h1>
<blockquote>
<p>Don't devaluate yourself for a chance, if a chance doesn't come, it's not the end of the world, however, devaluating yourself for something, will always backfire</p>
</blockquote>
<p>All of this was thanks to the amazing Senior, Mr. Sameh Aly, who taught me all of this and took me under his shoulders. Thank you very much, Sir!<br />Hope to work with you again!</p>
]]></content:encoded></item><item><title><![CDATA[Patterns: Plug-ins]]></title><description><![CDATA[Heyyy 👋
Long time no see 😄
And last I checked 🧐, I have an unfinished series...

But, truth be told, it's a complex topic with lots of details, but I also intend on finishing it, so don't worry, all in due time 😄
Problem
So, what's up today? Toda...]]></description><link>https://blog.ahmedramy.me/patterns-plug-ins</link><guid isPermaLink="true">https://blog.ahmedramy.me/patterns-plug-ins</guid><category><![CDATA[design patterns]]></category><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[software design]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Fri, 09 Dec 2022 22:24:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670624619530/7gjPrXgNQ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Heyyy 👋</p>
<p>Long time no see 😄</p>
<p>And last I checked 🧐, I have an unfinished series...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669717645468/p-0MCJio6.png" alt="CleanShot 2022-11-29 at 12.26.41@2x.png" class="image--center mx-auto" /></p>
<p>But, truth be told, it's a complex topic with lots of details, but I also intend on finishing it, so don't worry, all in due time 😄</p>
<h1 id="heading-problem">Problem</h1>
<p>So, what's up today? Today is a very good day to discuss one of the bloaters we all know very well, The big guy, <code>AppDelegate</code>, it starts small, and a couple of integrations later, it's almost unreadable anymore</p>
<p>I know I had some AppDelegates that I really didn't like at all, sometimes it was refactored to a Facade, and sometimes it was left with comments and MARKs all over the file to make it easier to navigate. However, there is still this kind of background pain from going into this file, and then... <strong>it clicked!</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669717994198/5oajGrixQ.png" alt="image.png" class="image--center mx-auto" /></p>
<blockquote>
<p>What if I told you that patterns can be combined?</p>
</blockquote>
<h1 id="heading-what-are-we-trying-to-achieve">What are we trying to achieve?</h1>
<p>Refactoring is always about asking the right questions. What am I trying to get after being done with this part of the code?</p>
<blockquote>
<p>Something that is easier to read, and maintain, so I need to separate some stuff</p>
</blockquote>
<p>So how to separate it?</p>
<h1 id="heading-but-how">But... How?</h1>
<p>Let's break down the AppDelegate for a second</p>
<p>The AppDelegate is made for a couple of things... like notifying us when a lifecycle event occurred, a notification was received, a deep link triggered our app, and so on.</p>
<p>And unfortunately for us, these methods get bloated with code. Surely we can add private methods to ease our burden, but what if we broke down the app delegate itself? Cut it into different reusable parts, that instead of "it" handling everything for us, it provides its APIs, and different implementors get called, as if it were... a Plug-in?</p>
<h2 id="heading-abstracting-the-appdelegate">Abstracting the AppDelegate</h2>
<p>Since we're trying to break it down, it makes sense that each implementer adheres to the same protocol. So, let's say -&gt;</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">ApplicationPlugin</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(
        <span class="hljs-number">_</span> application: UIApplication,
        willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: <span class="hljs-keyword">Any</span>]?)</span></span> -&gt; <span class="hljs-type">Bool</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(
        <span class="hljs-number">_</span> application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: <span class="hljs-keyword">Any</span>]?)</span></span> -&gt; <span class="hljs-type">Bool</span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(
        <span class="hljs-number">_</span> application: UIApplication,
        <span class="hljs-keyword">continue</span> userActivity: NSUserActivity,
        restorationHandler: @escaping <span class="hljs-params">([UIUserActivityRestoring]?)</span></span></span> -&gt; <span class="hljs-type">Void</span>) -&gt; <span class="hljs-type">Bool</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> app: UIApplication, <span class="hljs-keyword">open</span> url: URL, options: [UIApplication.OpenURLOptionsKey: <span class="hljs-keyword">Any</span>])</span></span> -&gt; <span class="hljs-type">Bool</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">applicationProtectedDataWillBecomeUnavailable</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication)</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">applicationProtectedDataDidBecomeAvailable</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication)</span></span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">applicationWillTerminate</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication)</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">applicationDidReceiveMemoryWarning</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication)</span></span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: <span class="hljs-keyword">Any</span>])</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)</span></span>
}
</code></pre>
<p>This move allowed us to have multiple implementations, each to their own concern of that event, but they have to adhere to the way the AppDelegate works. In other words, if we have to support Firebase, Deeplinks, Push Notifications, and Google Maps</p>
<p>Instead of having one gigantic AppDelegate, we would have mini App Delegates but specific to these, something like this...</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppearancePlugin</span>: <span class="hljs-title">ApplicationPlugin</span> </span>{ ... }
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UtilsPlugin</span>: <span class="hljs-title">ApplicationPlugin</span> </span>{ ... }
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FirebasePlugin</span>: <span class="hljs-title">ApplicationPlugin</span> </span>{ ... }
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotificationPlugin</span>: <span class="hljs-title">ApplicationPlugin</span> </span>{ ... }
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GMSPlugin</span>: <span class="hljs-title">ApplicationPlugin</span> </span>{ ... }
</code></pre>
<blockquote>
<p>Starting to make sense, eh? 😁</p>
</blockquote>
<h2 id="heading-gluing-parts-together">Gluing parts together</h2>
<blockquote>
<p>Ok, Ramy, the concept is ok, but how do you tell the AppDelegate to call your plugins or break itself?</p>
</blockquote>
<p>Well, that's the neat part... you don't</p>
<p>You actually change the perception of AppDelegate with our own</p>
<blockquote>
<p>Huh?</p>
</blockquote>
<p>See, any iOS App (and any other language or framework that has the concept of an <a target="_blank" href="https://en.wikipedia.org/wiki/Entry_point">entry-point</a>) needs to see this annotation to know which class is the delegate that it needs to send lifecycle updates</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669719361353/tbipuWRUS.png" alt="CleanShot 2022-11-29 at 12.55.48@2x.png" class="image--center mx-auto" /></p>
<p>And that's what we're going to do, so...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669719460771/IJe2WsVc4.png" alt="image.png" class="image--center mx-auto" /></p>
<h2 id="heading-creating-the-plugins-host">Creating the Plugins host</h2>
<p>Since the vanilla AppDelegate is incompetent in hosting our Plugins, we'll give it some superpowers.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">open</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationPluggableDelegate</span>: <span class="hljs-title">UIResponder</span>, <span class="hljs-title">UIApplicationDelegate</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">var</span> window: <span class="hljs-type">UIWindow?</span>

    <span class="hljs-comment">/// List of application plugins for binding to `AppDelegate` events</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">private</span>(<span class="hljs-keyword">set</span>) <span class="hljs-built_in">lazy</span> <span class="hljs-keyword">var</span> pluginInstances: [<span class="hljs-type">ApplicationPlugin</span>] = plugins()

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">init</span>() {
        <span class="hljs-keyword">super</span>.<span class="hljs-keyword">init</span>()

        <span class="hljs-comment">// Load lazy property early</span>
        <span class="hljs-number">_</span> = pluginInstances
    }

    <span class="hljs-comment">/// List of application plugins for binding to `AppDelegate` events</span>
    <span class="hljs-keyword">open</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">plugins</span><span class="hljs-params">()</span></span> -&gt; [<span class="hljs-type">ApplicationPlugin</span>] { [] } <span class="hljs-comment">// Override</span>
}
</code></pre>
<p>And now that the PluggableDelegate is defined, we're going to implement each method and make it call the plugins so they can do their work.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">ApplicationPluggableDelegate</span> </span>{
    <span class="hljs-keyword">open</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(
        <span class="hljs-number">_</span> application: UIApplication,
        willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: <span class="hljs-keyword">Any</span>]? = <span class="hljs-literal">nil</span>)</span></span>
        -&gt; <span class="hljs-type">Bool</span> {
        <span class="hljs-comment">// Ensure all delegates called even if condition fails early</span>
        pluginInstances.<span class="hljs-built_in">reduce</span>(<span class="hljs-literal">true</span>) {
            $<span class="hljs-number">0</span> &amp;&amp; $<span class="hljs-number">1</span>.application(application, willFinishLaunchingWithOptions: launchOptions)
        }
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> app: UIApplication, <span class="hljs-keyword">open</span> url: URL, options: [UIApplication.OpenURLOptionsKey: <span class="hljs-keyword">Any</span>] = [:])</span></span> -&gt; <span class="hljs-type">Bool</span> {
        pluginInstances.<span class="hljs-built_in">reduce</span>(<span class="hljs-literal">true</span>) {
            $<span class="hljs-number">0</span> &amp;&amp; $<span class="hljs-number">1</span>.application(app, <span class="hljs-keyword">open</span>: url, options: options)
        }
    }

<span class="hljs-comment">// ... (they're kind of a lot, so feel free to copy the approach from the Github link)</span>
}
</code></pre>
<h2 id="heading-building-the-plugins">Building the Plugins</h2>
<p>Now, for the fun part, to not barrage the post with lots of code, let's focus on a tiny piece that is easy to digest, the part where you define the Appearances for your core UIKit/SwiftUI parts, like Tabbars &amp; NavigationBars (...etc.)</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> UIKit.UIApplication

<span class="hljs-comment">// MARK: - AppearancePlugin</span>

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">AppearancePlugin</span> </span>{ }

<span class="hljs-comment">// MARK: ApplicationPlugin</span>

<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">AppearancePlugin</span>: <span class="hljs-title">ApplicationPlugin</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span>: UIApplication, didFinishLaunchingWithOptions <span class="hljs-number">_</span>: [UIApplication.LaunchOptionsKey: <span class="hljs-keyword">Any</span>]?)</span></span> -&gt; <span class="hljs-type">Bool</span> {
        addTabBarAppearances()
        addNavigationBarAppearance()
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
    }
}

<span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">AppearancePlugin</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addTabBarAppearances</span><span class="hljs-params">()</span></span> {
        <span class="hljs-type">UITabBar</span>.appearance().unselectedItemTintColor = .greysSpaceGrey
        <span class="hljs-type">UITabBar</span>.appearance().tintColor = .primaryBluberry
        <span class="hljs-type">UITabBar</span>.appearance().shadowImage = <span class="hljs-type">UIImage</span>()
        <span class="hljs-type">UITabBar</span>.appearance().backgroundImage = <span class="hljs-type">UIImage</span>()
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addNavigationBarAppearance</span><span class="hljs-params">()</span></span> {
        <span class="hljs-type">UINavigationBarAppearance</span>().configureWithTransparentBackground()
    }
}
</code></pre>
<p>See, in this part, usually, the appearance logic would be encapsulated inside private methods in a larger file (which is a common way of implementing the AppDelegate), but here, we're more focused on the appearance, which makes it easier to read and understand mentally.</p>
<p><img src="https://media.giphy.com/media/3oxOCCjVreWgdcfQiI/giphy.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-appdelegate-hosting-the-plugins">AppDelegate: Hosting the Plugins</h2>
<p>Now for the wrap-up and the part which looks like a Command pattern combined with a flavor of Composite pattern...</p>
<pre><code class="lang-swift">@main
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppDelegate</span>: <span class="hljs-title">ApplicationPluggableDelegate</span> </span>{
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">plugins</span><span class="hljs-params">()</span></span> -&gt; [<span class="hljs-type">ApplicationPlugin</span>] {
        [
            <span class="hljs-type">ServicesPlugin</span>(),
            <span class="hljs-type">AppearancesPlugin</span>(),
            <span class="hljs-type">UtilsPlugin</span>(),
            <span class="hljs-type">FirebasePlugin</span>(),
            <span class="hljs-type">GoogleMapsPlugin</span>(),
            <span class="hljs-type">NotificationsPlugin</span>()
        ]
    }
}
</code></pre>
<p>This is the actual interface of what the AppDelegate does. Any logic involved is separated across two parts, the PluggableDelegate &amp; the Plugin itself.</p>
<p>So, in a nutshell, this is what is happening from a higher-level perspective.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670597136633/BYEHUn_OZ.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-improvement-2-interface-segregation">Improvement: #2 Interface Segregation</h1>
<p>So, you may think that we have reached an acceptable level of improvement, which is true, btw. Our goal from the start was to separate things using a couple of patterns to the degree that makes dealing with the logic even easier, but there is indeed one improvement we can make, segregation if I may say</p>
<p><img src="https://media.giphy.com/media/fd1TSJqq3b4GI/giphy.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-categorizing-is-a-good-rule-of-thumb-for-segregation">Categorizing is a good rule of thumb for segregation</h2>
<p>Let's clear things out first. Let's agree that an AppDelegate like we said above, is a receptor of any events, but since events can be categorized, so does our protocol. For example, our protocol handles 3 parts, Lifecycle events, Deeplinking Events, and Push Notifications Events</p>
<p>Which, in the end, gives us conformation to the ISP (Interface Segregation Principle)</p>
<blockquote>
<p>Good Rule of 👍 is, whenever there's some methods to categorize, is an indicator that you can apply the <strong>ISP</strong>.</p>
</blockquote>
<p>And if I were to use Firebase Messaging. In that case, I'd only be interested in just the Remote Notifications delegate methods, similarly for Deeplinking Events which are not "necessarily" coupled to Lifecycle, so segregating the delegate methods in our tiny protocol gives us the ability to be more flexible with our 3rd party integrations and allow ourselves to write more clean and concise code, now doesn't that sound "cool"?</p>
<blockquote>
<p>My manager would disagree since we hit the goal already and should focus on something more important to the business, and we can iterate when needed (be wiser than me 😂)</p>
</blockquote>
<h2 id="heading-segregating-notification-methods">Segregating Notification Methods</h2>
<p>So, let's see this on diagrams first, so it paves the way for easier understanding.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670597989700/FJDUCUJ_V.png" alt class="image--center mx-auto" /></p>
<p>So, this is how this segregation made our diagram look like this ☝️</p>
<blockquote>
<p>Disclaimer, I am not very adept at UML diagraming, barely have a grasp over all the arrow types and such, but I figured this may be simpler and easier to explain with, so let me know if you think so, or should I really learn UML arrow types &amp; legends if that would help 🙏</p>
</blockquote>
<p>As you can see, now we have our ApplicationPlugin Protocol broken and segregated into 3 different protocols, and now we can compose them, even more to make for a flexible design</p>
<h2 id="heading-implementation-time">Implementation time</h2>
<p><img src="https://media.giphy.com/media/umYMU8G2ixG5mJBDo5/giphy.gif" alt class="image--center mx-auto" /></p>
<p>Let's start by defining and default implementing our RemoteNotification Protocols</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">ApplicationNotificationPlugin</span>: <span class="hljs-title">AnyObject</span>, <span class="hljs-title">ApplicationPlugin</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: <span class="hljs-keyword">Any</span>])</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)</span></span>
}

<span class="hljs-comment">// Then we define a default implementation so Plugins later on can pick which method to implement according to its needs</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">ApplicationNotificationPlugin</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span>: UIApplication, didReceiveRemoteNotification <span class="hljs-number">_</span>: [AnyHashable: <span class="hljs-keyword">Any</span>])</span></span> { }
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span>: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken <span class="hljs-number">_</span>: Data)</span></span> { }
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span>: UIApplication, didFailToRegisterForRemoteNotificationsWithError <span class="hljs-number">_</span>: Error)</span></span> { }
}
</code></pre>
<p>Then, back to our backend of the AppDelegate, let's instruct it on how to utilize the NotificationCenter's delegate methods</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">ApplicationPluggableDelegate</span>: <span class="hljs-title">UNUserNotificationCenterDelegate</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : <span class="hljs-keyword">Any</span>], fetchCompletionHandler completionHandler: @escaping <span class="hljs-params">(UIBackgroundFetchResult)</span></span></span> -&gt; <span class="hljs-type">Void</span>) {
        <span class="hljs-comment">// Hmmm, how to call the plugins?</span>
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)</span></span> {
        <span class="hljs-comment">// Hmmm, how to call the plugins?</span>
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)</span></span> {
        <span class="hljs-comment">// Hmmm, how to call the plugins?</span>
    }
}
</code></pre>
<p>Now that the PluggableDelegate knows about the <code>UNUserNotificationCenterDelegate</code>, it can channel those events to its children's plugins. A good way of doing this is <code>.compactMap { ... }</code></p>
<blockquote>
<p>A neat functional trick where u can filter &amp; typecast a sequence without much hassle, and in 1 shot</p>
</blockquote>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">application</span><span class="hljs-params">(<span class="hljs-number">_</span> application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)</span></span> {
        pluginInstances.<span class="hljs-built_in">compactMap</span> { $<span class="hljs-number">0</span> <span class="hljs-keyword">as</span>? <span class="hljs-type">ApplicationNotificationPlugin</span> }.forEach {
            $<span class="hljs-number">0</span>.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
        }
    }
</code></pre>
<p>Now, similarly, we can follow the same approach with other types of segregation</p>
<blockquote>
<p>But, where is the fun in that, when you, my dear reader, can do that yourself, and make sure you understood the above concepts, and I can get back to GOW: Ragnarok?</p>
</blockquote>
<p><img src="https://i.pinimg.com/736x/be/c1/9d/bec19d77eac8c07dceec143483309138.jpg" alt="Pin on ϟ|ANIME ICONS|ϟ" class="image--center mx-auto" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<h3 id="heading-quick-recap">Quick Recap</h3>
<p>So, this article, was a tough one, ngl. This is because you're not seeing a specific Design Pattern in action. If I counted correctly, you're seeing around 5 patterns combined, each taking an idea from the other until we reach the part where we end up with something easy to read, edit and extend, and probably that's what you'd want to gain from design patterns in general.</p>
<h3 id="heading-quick-breakdown">Quick Breakdown</h3>
<p>But, to make it easier to grasp, some of the very obvious patterns (apart from the Delegate, of course) are the <code>Command</code> &amp; <code>Composite</code> Patterns, which are the secret sauce of this recipe; however, more patterns were also inspired, like Builder patterns and the Factory, which you can find in the array of plugins, and the abstraction layer between each type; lastly, the strategy itself of which Plugin to run, which was the final segregation we've made.</p>
<p><img src="https://i.kym-cdn.com/photos/images/original/001/036/999/212.gif" alt="hai | 60's Spider-Man | Know Your Meme" class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Error Handling: Error Flow]]></title><description><![CDATA[Hello, how’s it going? 👋 
It’s time to finally write about the next part of the series “Error Handling”
This time we gonna discuss what we can call “Error Flow”, how error propagates from one part, area, or layer of the code, into another
Hence, cre...]]></description><link>https://blog.ahmedramy.me/error-handling-error-flow</link><guid isPermaLink="true">https://blog.ahmedramy.me/error-handling-error-flow</guid><category><![CDATA[error handling]]></category><category><![CDATA[Clean Architecture]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Sun, 02 Oct 2022 13:07:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1664715711049/szOHjZ_e8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello, how’s it going? 👋 
It’s time to finally write about the next part of the series “Error Handling”
This time we gonna discuss what we can call “Error Flow”, how error propagates from one part, area, or layer of the code, into another
Hence, creating… a “Flow”
We gonna also think about types of errors, like what we saw in the last post, when we wrapped Apple’s canceled error, we were able to categorize this error into a type that can be ignored, and a couple of goodies on the way that we can make use of</p>
<h1 id="heading-what-are-we-building">What are we building?</h1>
<p>Today, we are going to build a payment method selection screen, and like last time, we have a “Why” here, on why are we building a payment method screen</p>
<ol>
<li>Having various payment methods with different implementations can have different types of errors, and hence, different handlings</li>
<li>The variations also allow us to think differently about how to display those methods since not all methods can be displayed the same</li>
<li>Also, each type of method has its own way of business logic, which might result in different ways of handling errors per screen, so we're going to look into that as well</li>
<li>Lastly, it’s a good opportunity to integrate with Apple Pay</li>
</ol>
<p>And, here is a glimpse of the final screen (since I enjoy this part when watching a tutorial tbh 😃)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1663664778374/M_mfb3X-t.png" alt="image.png" /></p>
<blockquote>
<p>Note: We’ll be focusing only on fetching our methods, and handling Apple Pay’s states</p>
</blockquote>
<h1 id="heading-a-refresher-of-uncle-bobs-clean-architecture">A Refresher of Uncle Bob’s Clean Architecture</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1663664793389/q6-8ffSxL.png" alt="image.png" />
So, basically speaking we’re going to have our architecture layered into 4 layers
The View’s -&gt; The Presentation’s -&gt; The business’s -&gt; The data’s</p>
<p>Or, something like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1663664803318/TrOcYZvHk.png" alt="image.png" /></p>
<p>Similar to how each layer is supposed to handle its responsibilities (in other words, the happy path), they also need to learn how they can handle their errors…</p>
<blockquote>
<p>🤔 But what kind of errors should they handle?</p>
<p>💡 Let’s break this into two categories</p>
<ol>
<li><p>Layer-specific errors</p>
</li>
<li><p>Types of errors in general</p>
</li>
</ol>
</blockquote>
<h1 id="heading-types-of-errors">Types of errors</h1>
<p>Let’s break this one into 2 categories.</p>
<ol>
<li>Layer-specific errors (like Network errors where connectivity may be lost)</li>
<li>General types of errors (Like an error that can be ignored (cancelled error))</li>
</ol>
<h2 id="heading-general-types-of-errors">General Types of Errors</h2>
<h3 id="heading-ignorable-errors">Ignorable Errors</h3>
<p>Similar to the last post, we had Apple throwing us an error when the user cancels Apple Sign In</p>
<h3 id="heading-recoverable-errors">Recoverable Errors</h3>
<p>For example, when a token expires, you can still recover from that backend error by refreshing your token first, then continue on with the original request</p>
<h3 id="heading-unhandleable-errors">Unhandleable Errors</h3>
<p>Which are kinds of errors that can not be handled in the current layer, but can be handled in another layer, for example, you can’t fetch data from a repository, but  the business layer may choose to omit this data or reformulate the response (aka, work its way around it) so its no longer an error (more on that later in this post)</p>
<h3 id="heading-default-errors">Default Errors</h3>
<p>This is the last line of defense, the worst has happened, you can’t handle the error, and now we gonna need to tell the user there is something wrong</p>
<h2 id="heading-layer-specific-errors">Layer-specific Errors</h2>
<p>Some layers may have a set of common errors, like Datasources, the most common one would be, I couldn’t fetch the data (with mentioning a reason, optionally), while others require being more specific when throwing an error
Like trying to check your profile, and <strong>whoops!</strong> no profile created</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1663665032961/PmmtlGErC.png" alt="image.png" /></p>
<h3 id="heading-to-error-or-not-to-error">To Error or not to error?</h3>
<p>The thing about layer-specific errors is, sometimes, an error would be treated as an error in some use cases, and sometimes it would be treated as a normal behavior without a need to make a fuss of it</p>
<blockquote>
<p>🤔 Dude…?</p>
</blockquote>
<p>Yep, bare with me, so for example, let’s say you’re trying to pay for something, and in the system, you can pay with your wallet, but guess what? You didn’t create a wallet for yourself in this system, so when paying, you can still pay with other methods and no need to tell you there is an error, right?</p>
<p>But, let’s say you’re visiting your wallet page for the first time, and there is no wallet, that’s when the error makes sense, where you don’t have a wallet error makes sense to be dealt with</p>
<p>Ok, too much reading, let’s start</p>
<h1 id="heading-getting-started">Getting Started</h1>
<p>So our happy scenario involves opening this screen and fetching our methods, and they all succeed, but we’re not here for happy scenarios, are we?
<img src="https://media.giphy.com/media/YmVcWIUOX3KgNCvH21/giphy.gif" alt /></p>
<h1 id="heading-the-flow">The Flow</h1>
<h2 id="heading-the-data-layer">The Data Layer</h2>
<p>So, in the data layer, we got sources for these data, like the network &amp; cache &amp; databases, but for now, we are going to skip the sources, and talk directly about the repository layer</p>
<p><img src="https://user-images.githubusercontent.com/31904352/193454515-a0847d42-ae10-4a9d-aff2-311ba25a5e62.png" /></p>
<blockquote>
<p>💡 Note: I talked about Network briefly <a target="_blank" href="https://blog.ahmedramy.me/test-driven-development-3-testing-network">here</a> in the TDD series</p>
</blockquote>
<h3 id="heading-the-wallet">The Wallet</h3>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">WalletRepositoryProtocol</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchWallet</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; <span class="hljs-type">Wallet</span>
}
</code></pre>
<ol>
<li>We expect a wallet (duhh)</li>
<li>It can throw an error (yea yea, error handling series, what a surprise 🙄)</li>
<li>It's async (cuz it takes time to call an imaginary wallet endpoint)</li>
</ol>
<p>so, let's start by addressing our Error flow first</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">WalletRepositoryError</span>: <span class="hljs-title">RepositoryError</span> </span>{
    <span class="hljs-keyword">case</span> noWalletFound
    <span class="hljs-keyword">case</span> banned
    <span class="hljs-keyword">case</span> inReview(<span class="hljs-number">_</span> state: <span class="hljs-type">ReviewState</span>)
}

<span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">WalletRepositoryError</span> </span>{
    <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">ReviewState</span> </span>{
      <span class="hljs-keyword">case</span> pending
      <span class="hljs-keyword">case</span> beingProcessed
    }
}
</code></pre>
<p>So, there can be no wallet, it could be banned, or it could be in review state with some more info about where it is now in the process, so as a Repository, I need to know what errors that can happen, so it's possible for me to handle them or not, and it's up to the next layer (the caller), to decide if he's interested in the errors I couldn't handle or not</p>
<p>Let's peek into the UseCase for the payment methods</p>
<pre><code class="lang-swift"><span class="hljs-keyword">fileprivate</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addWalletIfPossible</span><span class="hljs-params">(<span class="hljs-number">_</span> methods: <span class="hljs-keyword">inout</span> [PaymentMethod])</span></span> async {
    <span class="hljs-keyword">if</span> flags.wallet {
      <span class="hljs-keyword">do</span> {
        methods.append(<span class="hljs-keyword">try</span> await walletRepository.fetchWallet())
      } <span class="hljs-keyword">catch</span> <span class="hljs-keyword">let</span> error <span class="hljs-keyword">as</span> <span class="hljs-type">WalletRepositoryError</span> {
        <span class="hljs-type">LoggersManager</span>.error(error)
      } <span class="hljs-keyword">catch</span> {
        <span class="hljs-type">LoggersManager</span>.error(message: <span class="hljs-string">"Unknown error caught: \(error)"</span>)
      }
    }
  }
</code></pre>
<p>So, the Usecase here is interested in knowing whether the Wallet succeeded or not, and in case of failure, it would just log the error without failing the whole request made by the user</p>
<blockquote>
<p>💡 Note: Notice that in the above example, since we're providing the user with his payment methods only, failing to fetch the wallet here means that we're not returning it as a payment method, while in a different example like a Wallet page, there must be a wallet or an error to tell the user he needs to create a wallet, and that's where the extra details of the error come in handy</p>
</blockquote>
<h3 id="heading-apple-pay">Apple Pay</h3>
<p>Now, Apple Pay is a bit different than your normal, usecase - repo - network call, it's a service of its own, and wrapping it would help us a lot in terms of reusing it, and also define how to handle its errors</p>
<p>So in here, we're going to define 2 things, ApplePay as a Payment Method, and ApplePay Service, which is a wrapper around ApplePay's API itself</p>
<blockquote>
<p>💡 Note: Aside from being able to testing, having a wrapper allows us to bridge its errors, allowing us to handle its failures even better isA</p>
</blockquote>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">ApplePayServiceProtocol</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchApplePay</span><span class="hljs-params">()</span></span> <span class="hljs-keyword">throws</span> -&gt; <span class="hljs-type">ApplePayProtocol</span>
}

<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">ApplePayError</span>: <span class="hljs-title">Error</span> </span>{
    <span class="hljs-keyword">case</span> serviceNotAvailable
}
</code></pre>
<p>I believe this is what I need to handle from the ApplePayService for now, and all that is left is how the UI would deal with ApplePay, like if its status needsSetup or is it available for use, because later on, that would decide the flow if the user picked it as a payment method</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchApplePay</span><span class="hljs-params">()</span></span> <span class="hljs-keyword">throws</span> -&gt; <span class="hljs-type">ApplePayProtocol</span> {
        <span class="hljs-keyword">guard</span> <span class="hljs-type">PKPaymentAuthorizationController</span>.canMakePayments() <span class="hljs-keyword">else</span> { <span class="hljs-keyword">throw</span> <span class="hljs-type">ApplePayError</span>.serviceNotAvailable }
        <span class="hljs-keyword">let</span> isItSetup = <span class="hljs-type">PKPaymentAuthorizationController</span>.canMakePayments(usingNetworks: supportedNetworks)
        <span class="hljs-keyword">return</span> <span class="hljs-type">ApplePay</span>(status: isItSetup ? .needsSetup : .available)
    }
</code></pre>
<p>So, now that our repositories &amp; services has been defined, let's jump into the business layer, and see how these 2 layers would interact with each other, <strong>BUT</strong>, first let's check where we are on the diagrams so it's easy to follow along.</p>
<p><img src="https://user-images.githubusercontent.com/31904352/192192963-e43f2826-92e8-4784-b2e5-501aa72bb089.png" /></p>
<h2 id="heading-the-domain">The Domain</h2>
<p><img src="https://user-images.githubusercontent.com/31904352/192193252-b3dc9938-5ab9-4922-80e5-1515f071201d.png" alt="image" /></p>
<p>Now that an error made it into the domain layer (the use case), it's up to this class to decide what to do with it</p>
<blockquote>
<p>🤭 And no, fortunately we're not bounding anyone's soul here</p>
</blockquote>
<p>But, let's first think about what do we need, we have 3 sources for payment methods</p>
<ol>
<li>The Wallet</li>
<li>The Payment Cards</li>
<li>Apple Pay</li>
</ol>
<p>So, we're going to depend on these 3 sources in our UseCase and its our job there to decide what to do if they fail</p>
<pre><code class="lang-swift"><span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">process</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">PaymentMethod</span>] {
    <span class="hljs-keyword">var</span> methods: [<span class="hljs-type">PaymentMethod</span>] = []

    await addWalletIfPossible(to: &amp;methods)
    await addPaymentCardsIfPossible(to: &amp;methods)
    await addApplePayIfPossible(to: &amp;methods)

    <span class="hljs-keyword">guard</span> !methods.isEmpty <span class="hljs-keyword">else</span> { <span class="hljs-keyword">throw</span> <span class="hljs-type">PaymentUsecaseError</span>.noPaymentMethodsFound }

    <span class="hljs-keyword">return</span> methods
  }
</code></pre>
<p>So, we're basically adding our methods if possible, but we're not really interested in failing the request unless its empty</p>
<blockquote>
<p>🤔 Can't we return an empty array &amp; be done with it?</p>
<p>💡 We can, there is no shame in it, but there are 4 reasons for this</p>
<ol>
<li>similarly to the backend response when you're asking for an array of resources, the better practice is to send a 404, not a 200 and an empty array</li>
<li>similar to real life, if you're asking your local shopkeeper for some Avocados, and there is no avocados, he won't give you an empty bag, he would tell you they're not there</li>
<li>I believe being explict is key, so instead of returning empty array or a false boolean to indicate that you couldn't find or do something, it's better to throw an error where you can give more details (Check Uncle Bob's Chapter 7: Error Handling)</li>
<li>This is an Error Handling series, so we're trying to make a point here</li>
</ol>
</blockquote>
<p>Now, since our Usecase has its goal sorted out 👏, it's time to move to...</p>
<h2 id="heading-the-presentation">The Presentation</h2>
<p><img src="https://media.giphy.com/media/3o6MbtNxMykKAAAym4/giphy.gif" alt /></p>
<p>So, in the view model, we're interested in couple of things, having our <code>State</code> defined in a way that makes effort for the View minimal to display</p>
<pre><code class="lang-swift">  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">State</span> </span>{
    <span class="hljs-keyword">var</span> wallet: <span class="hljs-type">WalletPaymentMethodUIModel?</span>
    <span class="hljs-keyword">var</span> paymentCards: [<span class="hljs-type">PaymentCardMethodUIModel</span>] = []
    <span class="hljs-keyword">var</span> applePay: <span class="hljs-type">ApplePayPaymentMethodUIModel?</span>

    <span class="hljs-keyword">var</span> isEmpty: <span class="hljs-type">Bool</span> = <span class="hljs-literal">true</span>

    <span class="hljs-keyword">var</span> error: <span class="hljs-type">PresentationError?</span>
    <span class="hljs-keyword">var</span> message: <span class="hljs-type">SuccessMessage?</span>
  }
</code></pre>
<p>It allows the view to ask for Payment methods</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchPaymentMethods</span><span class="hljs-params">()</span></span> {
    <span class="hljs-type">Task</span> {
        <span class="hljs-keyword">do</span> {
            updateState(<span class="hljs-keyword">try</span> await <span class="hljs-type">PaymentUsecase</span>().execute())
        } <span class="hljs-keyword">catch</span> { ... }
    }
}
</code></pre>
<p>And lastly, it handles the errors and updates the state accordingly</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">fetchPaymentMethods</span><span class="hljs-params">()</span></span> {
    ...
    <span class="hljs-keyword">do</span> { ... } 
    <span class="hljs-keyword">catch</span> <span class="hljs-type">PaymentUsecaseError</span>.noPaymentMethodsFound {
        state.isEmpty = <span class="hljs-literal">true</span>
    } <span class="hljs-keyword">catch</span> <span class="hljs-keyword">is</span> <span class="hljs-type">UnknownBusinessError</span> {
        state.error = .<span class="hljs-keyword">default</span>
    } <span class="hljs-keyword">catch</span> {
        state.error = .<span class="hljs-keyword">default</span>
    }
}
</code></pre>
<p>Now that our state is configured, the flow should move to the view
<img alt="CleanShot 2022-10-02 at 14 50 40@2x" src="https://user-images.githubusercontent.com/31904352/193454880-93f4f70b-df98-4b39-b260-a535c9d6f6c1.png" /></p>
<p>By the time any errors make it past the Presentation, the view can do minimal effort to display it, telling our users exactly what went wrong, but what if that error demanded us to change our current flow? for example, what if the user is no longer authenticated and must re-login?</p>
<p>That's a question for our next blog post, Error Handlers!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We now know that Error Handling is not all about some do catch blocks, sometimes it takes more effort and more design on paper to learn how to deliver something mature enough to help in delivering the best experience to the user, and even when things go south, it's still possible to give a reason for that</p>
<p>And like always, feel free to check out that git repo that hosts the code to this proejct <a target="_blank" href="https://github.com/ARamy23/ErrorHandling/tree/post/error-flow/payment-methods">Error Flow Code</a></p>
<p><img src="https://media.giphy.com/media/m9eG1qVjvN56H0MXt8/giphy.gif" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Error Handling: Wrapping]]></title><description><![CDATA[Hello, hello! 🙌
Been a long time, I know (guilty as charged), it’s been a rough month, and I barely had time to set things up, so today (thank god) is the day we finally continue talking about Error Handling!
TL;DR
You can directly go to this branch...]]></description><link>https://blog.ahmedramy.me/error-handling-wrapping</link><guid isPermaLink="true">https://blog.ahmedramy.me/error-handling-wrapping</guid><category><![CDATA[error handling]]></category><category><![CDATA[Clean Architecture]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Sun, 21 Aug 2022 06:03:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1661061793144/yQGfS1cIR.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello, hello! 🙌</p>
<p>Been a long time, I know (guilty as charged), it’s been a rough month, and I barely had time to set things up, so today (thank god) is the day we finally continue talking about Error Handling!</p>
<h1 id="heading-tldr">TL;DR</h1>
<p>You can directly go to this <a target="_blank" href="https://github.com/ARamy23/ErrorHandling/tree/post/wrapping/auth">branch</a> and just read the code from there</p>
<h1 id="heading-plan-setting-time">Plan setting time</h1>
<p>Let’s first agree that 3rd party modules are not always controllable, so to get over this, we wrap it into our wrappers and build upon these wrappers, and in some cases, we map it into our implementations.</p>
<blockquote>
<p>💡 You may find wrappers are sort of like Facades, but we don’t want to use confusing smart words now do we? (Actually, we do, so you might wanna google what a <a target="_blank" href="https://refactoring.guru/design-patterns/facade">Facade</a> is in case you don’t 😁)</p>
</blockquote>
<p>So…
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661052764117/8CRZY-C_g.gif" alt="tenor.gif" class="image--center mx-auto" /></p>
<h2 id="heading-what-are-we-building-today">What are we building today?</h2>
<p>Today, we’re building a simple <strong>Sign In with Apple</strong> app
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661052771200/PCecWka6L.png?width=500" alt class="image--center mx-auto" /></p>
<p><strong>But!</strong> before we start there are a couple of disclaimers</p>
<ul>
<li>UI was mainly built by <a target="_blank" href="https://github.com/imodeveloperlab/dskit">DSKit</a>, I haven’t done much except play around with it</li>
<li>No actual Sign-in takes place, so don’t expect that we’re going to authenticate you somewhere, or do anything with your credentials 😊</li>
</ul>
<h2 id="heading-the-problem">The Problem</h2>
<p>So, why the Sign In with Apple?</p>
<p>It has lots of potential for today’s topic, where you may find yourself kinda coupled to putting its logic inside the ViewController or View just because it needs a <code>presentationContextProvider</code> or the <code>delegate</code></p>
<p>So why not wrap that delegate inside our workflow?</p>
<blockquote>
<p>💡 For this post (probably like every other post), we're going to use <code>MVVM</code>, but this time we're going to utilize a bit of <code>Combine</code></p>
</blockquote>
<h2 id="heading-wrapping-time">Wrapping Time</h2>
<h3 id="heading-defining-our-wrapper-facade">Defining our Wrapper (Facade)</h3>
<p>Since all we want from Apple Sign-in is getting to know when it succeeded, and when it failed, along with the success response, and the error resulted, for the sake of this post, I'll be interested in the error only (well, since it's a topic around Error Handling, so... yep 🤷‍♂️)</p>
<p>So, let's create our API contract!</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">AppleAuthUIDelegateProtocol</span>: <span class="hljs-title">ASAuthorizationControllerDelegate</span> </span>{
  <span class="hljs-keyword">var</span> onSuccess: <span class="hljs-type">VoidCallback</span> { <span class="hljs-keyword">get</span> <span class="hljs-keyword">set</span> }
  <span class="hljs-keyword">var</span> onError: <span class="hljs-type">Callback</span>&lt;<span class="hljs-type">ASAuthorizationError</span>&gt; { <span class="hljs-keyword">get</span> <span class="hljs-keyword">set</span> }
}
</code></pre>
<blockquote>
<p>💡 Whatever comes after this is just a conformer, so I can fake this to drive something I want to see/test specifically</p>
<p>💡 You may notice that we mentioned that we're wrapping the UIDelegate and called it a Facade, so what's going on?</p>
<p>As it seems that we're doing 3 different things, but they're all the same</p>
<ul>
<li>We're wrapping Apple's Delegate for the Apple Sign In</li>
<li>We're facade-ing it, so it's simpler</li>
<li>And the delegate hasn't changed, so nothing changed here</li>
</ul>
</blockquote>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppleAuthUIDelegate</span>: <span class="hljs-title">NSObject</span>, <span class="hljs-title">AppleAuthUIDelegateProtocol</span> </span>{
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">var</span> onSuccess: <span class="hljs-type">VoidCallback</span>
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">var</span> onError: <span class="hljs-type">Callback</span>&lt;<span class="hljs-type">ASAuthorizationError</span>&gt;

  <span class="hljs-keyword">public</span> <span class="hljs-keyword">init</span>(onSuccess: @escaping <span class="hljs-type">VoidCallback</span>, onError: @escaping <span class="hljs-type">Callback</span>&lt;<span class="hljs-type">ASAuthorizationError</span>&gt;) {
    <span class="hljs-keyword">self</span>.onSuccess = onSuccess
    <span class="hljs-keyword">self</span>.onError = onError
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">authorizationController</span><span class="hljs-params">(controller <span class="hljs-number">_</span>: ASAuthorizationController, didCompleteWithAuthorization <span class="hljs-number">_</span>: ASAuthorization)</span></span> {
    onSuccess()
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">authorizationController</span><span class="hljs-params">(controller <span class="hljs-number">_</span>: ASAuthorizationController, didCompleteWithError error: Error)</span></span> {
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> error = error <span class="hljs-keyword">as</span>? <span class="hljs-type">ASAuthorizationError</span> <span class="hljs-keyword">else</span> {
      onError(.<span class="hljs-keyword">init</span>(.unknown))
      <span class="hljs-keyword">return</span>
    }

    onError(error)
  }
}
</code></pre>
<h3 id="heading-reusing-apple-sign-ins-presentation-logic">Reusing Apple Sign-In's Presentation Logic</h3>
<p>Sure, we can put all that logic inside a <code>LoginViewModel</code>, no problem, but what if you wanted to reuse it, and export it into its own module, segregating sure does like a good idea</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppleSignInViewModel</span> </span>{
  ...
  <span class="hljs-comment">// 👇 UI Delegate added with a couple of handlers</span>
  <span class="hljs-keyword">private</span> <span class="hljs-built_in">lazy</span> <span class="hljs-keyword">var</span> uiDelegate: <span class="hljs-type">AppleAuthUIDelegateProtocol</span> = <span class="hljs-type">AppleAuthUIDelegate</span>(
    onSuccess: onSuccessHandler,
    onError: onErrorHandler)

  <span class="hljs-keyword">private</span> <span class="hljs-built_in">lazy</span> <span class="hljs-keyword">var</span> onSuccessHandler: <span class="hljs-type">VoidCallback</span> = { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] <span class="hljs-keyword">in</span>
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> <span class="hljs-keyword">self</span> = <span class="hljs-keyword">self</span> <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
    ...
  }

  <span class="hljs-keyword">private</span> <span class="hljs-built_in">lazy</span> <span class="hljs-keyword">var</span> onErrorHandler: <span class="hljs-type">Callback</span>&lt;<span class="hljs-type">ASAuthorizationError</span>&gt; = { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] error <span class="hljs-keyword">in</span>
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> <span class="hljs-keyword">self</span> = <span class="hljs-keyword">self</span> <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
    ...
  }
 ...
}
</code></pre>
<p>So, now that we have our ui delegate &amp; a couple of handlers to catch the delegate methods results, we can start defining how we're going to handle the errors</p>
<p>let's quickly define some struct that represents our UI state for AppleSignIn, so far, its easy enough to wrap inside an enum, so let's do so</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">AppleSignInViewModel</span> </span>{
  <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">State</span> </span>{
    <span class="hljs-keyword">case</span> idle
    <span class="hljs-keyword">case</span> success
    <span class="hljs-keyword">case</span> failure(errorMessage: <span class="hljs-type">String</span>)
  }
}
</code></pre>
<p>Now back to the <code>onErrorHandler</code> so it can propagate the failure state to the <code>LoginViewModel</code> and then to the <code>View</code></p>
<pre><code class="lang-swift">...
  <span class="hljs-keyword">private</span> <span class="hljs-built_in">lazy</span> <span class="hljs-keyword">var</span> onErrorHandler: <span class="hljs-type">Callback</span>&lt;<span class="hljs-type">ASAuthorizationError</span>&gt; = { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] error <span class="hljs-keyword">in</span>
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> <span class="hljs-keyword">self</span> = <span class="hljs-keyword">self</span> <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
    <span class="hljs-keyword">self</span>.state = .failure(errorMessage: error.localizedDescription)
  }
...
</code></pre>
<p>Now, let's try our Error Pipeline</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661063540365/aJD1leX9A.png?width=500" alt="CleanShot 2022-08-21 at 06.28.00.gif" class="image--center mx-auto" /></p>
<p>And Voil..., wait a minute...
why does <code>localizedDescription</code> look so cryptic?</p>
<p><img src="https://media.giphy.com/media/cPKWZB2aaB3rO/giphy.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-defining-our-own-error">Defining our own Error</h3>
<p>You may have noticed that Apple sends <code>ASAuthorizationError</code>, and its <code>.localizedDescription</code> is not very, um... localized?
but also, to our own code, it's not a 1st party error, and controlling it is a bit tricky if dealt with directly, so defining it in our own context is a good idea</p>
<blockquote>
<p>🤔 Apple's own error not being a 1st party error? does he realize that we're building on their own platform?</p>
<p>💡 Yep, while you're indeed building above Apple's Foundation &amp; UIKit, but not above <code>AuthenticationServices</code> adapting <code>ASAuthorizationError</code> into your own Error gives you a couple of things, more control, the ability to specify the <code>localizedDescription</code></p>
</blockquote>
<p>So, let's define our <code>AppleSignInError</code></p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">AppleSignInError</span>: <span class="hljs-title">PresentationError</span> </span>{
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">let</span> title: <span class="hljs-type">String</span>
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">let</span> description: <span class="hljs-type">String?</span>
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">let</span> type: <span class="hljs-type">PresentationMethod</span>
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">let</span> icon: <span class="hljs-type">UIImage?</span>

  <span class="hljs-keyword">public</span> <span class="hljs-keyword">init</span>(title: <span class="hljs-type">String</span>, description: <span class="hljs-type">String?</span> = <span class="hljs-literal">nil</span>, type: <span class="hljs-type">PresentationMethod</span> = .indicator, icon: <span class="hljs-type">UIImage?</span> = <span class="hljs-literal">nil</span>) {
    <span class="hljs-keyword">self</span>.title = title
    <span class="hljs-keyword">self</span>.description = description
    <span class="hljs-keyword">self</span>.type = type
    <span class="hljs-keyword">self</span>.icon = icon
  }
}
</code></pre>
<blockquote>
<p>👀 We will talk more about <code>PresentationError</code> in a later post and what role it plays</p>
</blockquote>
<p>Now that we have our <code>AppleSignInError</code>, let's add some adaption code from <code>ASAuthorizationError</code> -&gt; <code>AppleSignInError</code></p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">AppleSignInError</span> </span>{
  <span class="hljs-keyword">init</span>(<span class="hljs-number">_</span> authError: <span class="hljs-type">ASAuthorizationError</span>) {
    <span class="hljs-keyword">switch</span> authError.code {
    <span class="hljs-keyword">case</span> .unknown:
      <span class="hljs-keyword">self</span> = .<span class="hljs-keyword">init</span>(title: <span class="hljs-string">"Something went wrong"</span>, description: <span class="hljs-string">"with an unknown reason"</span>)
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">self</span> = .<span class="hljs-keyword">init</span>(title: <span class="hljs-string">"Sign in failed"</span>)
    }
  }
}
</code></pre>
<p>And now we can ignore firing an error from the ViewModel if it doesn't make sense from a presentation POV, like a <code>canceled</code> error for example 😄</p>
<pre><code class="lang-swift"><span class="hljs-keyword">private</span> <span class="hljs-built_in">lazy</span> <span class="hljs-keyword">var</span> onErrorHandler: <span class="hljs-type">Callback</span>&lt;<span class="hljs-type">ASAuthorizationError</span>&gt; = { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] error <span class="hljs-keyword">in</span>
    <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> <span class="hljs-keyword">self</span> = <span class="hljs-keyword">self</span> <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
    <span class="hljs-keyword">guard</span> error.code != .canceled <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
    <span class="hljs-keyword">self</span>.state = .failure(.<span class="hljs-keyword">init</span>(error))
  }
</code></pre>
<h2 id="heading-wrapping-it-up">Wrapping it up</h2>
<p>Now, if we ran our project again and tried to cancel, we no longer get an error when we cancel the sign-in process using Apple</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661063950896/EaIezT1On.gif" alt="CleanShot 2022-08-21 at 08.38.50.gif" class="image--center mx-auto" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>We've cut a lot of ground today, not only did we discuss Facading and wrapping 3rd party code into our own code, but we set a strong foundation for the coming post which is going to take a good turn in defining Error Handling responsibility among different layers in Clean Architecture</p>
<p>You can follow the project <a target="_blank" href="https://github.com/ARamy23/ErrorHandling">here</a> on GitHub</p>
<p><strong>Aaand, It's a wrap!</strong></p>
<p><img src="https://media.giphy.com/media/zZZlwysKnOMD4BRJ2v/giphy.gif" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Error Handling: Loggings]]></title><description><![CDATA[Have you ever been in a situation where your manager approaches you and mentions that there is a critical bug on production, and upon hearing the details, you’ve no idea what’s going on “out there”?
You open up Xcode, try to reproduce the issue, and ...]]></description><link>https://blog.ahmedramy.me/error-handling-loggings</link><guid isPermaLink="true">https://blog.ahmedramy.me/error-handling-loggings</guid><category><![CDATA[logging]]></category><category><![CDATA[error handling]]></category><category><![CDATA[monitoring]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Wed, 20 Jul 2022 13:08:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658321843898/zHTvqjlz2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever been in a situation where your manager approaches you and mentions that there is a critical bug on production, and upon hearing the details, you’ve no idea what’s going on “out there”?</p>
<p>You open up Xcode, try to reproduce the issue, and you can’t seem to find what he’s talking about? You try to trace the code, try to “manually” test harder, but to no avail?</p>
<p>Then it hits ya, you ask a friend, and he asks, “Did you check the logs?”, and you be like…</p>
<blockquote>
<p>What?</p>
</blockquote>
<h2 id="heading-logs">Logs</h2>
<p>Like a dear diary, with their colorful way of expressing how your day went, the same thing in Software Development, the only difference is, they sound robotic, they’re labeled with file names, line numbers, sometimes method names
They’re colored somehow, but when the color is red, you know it’s going to be a looong day
So why are they important? Well, they are some sorts of hints to when an issue takes place</p>
<h2 id="heading-story-time">Story Time!</h2>
<p>Like our previous post, the marketing team decided to launch a campaign on Facebook, and suddenly all the products they’re referring to in the ads are not accessible through the ad, you spend some time trying to replicate the issue, but the <code>deeplinking</code> does work on your machine, what seems to be the problem?
Turns out Bob, the marketing guy, had a typo in the <code>deeplink</code> URL he used, and that wasn’t obvious when debugging, it took a while figuring this out, but the campaign is saved, and you live to fight another bug, but what would it be like if you had “Logs”?</p>
<h3 id="heading-another-dimension-where-you-had-logs">Another Dimension where you had Logs</h3>
<p>So, day 1 in the campaign, Bob presses the <code>confirm</code> button, users start to interact with the ad, and 1 day later, the issue is later reported to your manager, and you learn of it
As a smart engineer, you already had logs installed, you find a bunch of red-colored messages saying…
<code>coudln't unwrap yourapp:/product_details?id=123 as a URL for handling it.</code>
 and you managed to discover that there is an issue with the <code>deeplink</code> you’re receiving from the marketing guy, you ask them to edit it to the correct format, and the day is saved</p>
<h3 id="heading-dr-strange">Dr. Strange</h3>
<p>Back to your own dimension after work, you went to do your laundry and you met Dr. Strange there
<img src="https://media.giphy.com/media/8yqQgiEzdvonSqM403/giphy.gif" alt /></p>
<p>Turns out, all that multiverse madness didn’t give him enough time to do his laundry and now he have a chance to, you both strike a conversation and somehow, you got to let him show you how did you do in other realities, you find that in one reality you had logs installed and that helped ya solve the bug quickly without much stress that you had today, now you want to install one too, and that’s what we will do today!</p>
<h2 id="heading-time-to-add-a-diary-system">Time to add a diary system</h2>
<p>So, let’s first define some structure and focus on a system we already have in place, the <code>print</code> statement, it would be nice if we could add more info to it, like severity, its place in the code, maybe some emojis since the console doesn’t support colors, so let’s define one</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SystemLogger</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> main: <span class="hljs-type">SystemLogger</span> = .<span class="hljs-keyword">init</span>()
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">init</span>() {}

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">info</span><span class="hljs-params">(<span class="hljs-number">_</span> message: String,
                               metaData: [String: Encodable]? = <span class="hljs-literal">nil</span>,
                               file: String = #file,
                               function: String = #function,
                               line: UInt = #line)</span></span> {
        #<span class="hljs-keyword">if</span> <span class="hljs-type">DEBUG</span>
            <span class="hljs-built_in">print</span>(message.withPrefix(<span class="hljs-string">"ℹ️ "</span>), <span class="hljs-string">"Details: \(file), \(function), \(line)"</span>)
        #endif
    }

    ...
}
</code></pre>
<p>Well, now we have more control, and it makes sense that the logger be accessible through a singleton, but only problem is, we only have access to those logs during development 🤔
Turns out we can add another Logger that we can utilize, like <a target="_blank" href="https://github.com/SwiftyBeaver/SwiftyBeaver">SwiftyBeaver</a>, so we go on, and replicate what we did…</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SwiftyBeaverLogger</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> main: <span class="hljs-type">SwiftyBeaverLogger</span> = .<span class="hljs-keyword">init</span>()
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">init</span>() {}

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">info</span><span class="hljs-params">(<span class="hljs-number">_</span> message: String,
                               metaData: [String: Encodable]? = <span class="hljs-literal">nil</span>,
                               file: String = #file,
                               function: String = #function,
                               line: UInt = #line)</span></span> {
        ...
    }

    ...
}
</code></pre>
<p>During working with our two new loggers, you found that you wanted to log to both at the same time, after putting in some thoughts, you noticed that both implementations are too close to Strategy pattern, where they just differ in how they do their work, so you decide to add a protocol, to be later used inside a Manager class where you call it and the manager invokes all the strategies (Loggers)</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">LogEngine</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">info</span><span class="hljs-params">(message: String,
              metaData: [String: Encodable]?,
              file: String = #file,
              function: String = #function,
              line: UInt = #line)</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">warn</span><span class="hljs-params">(message: String,
              metaData: [String: Encodable]?,
              file: String = #file,
              function: String = #function,
              line: UInt = #line)</span></span>
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">error</span><span class="hljs-params">(message: String,
              metaData: [String: Encodable]?,
              file: String = #file,
              function: String = #function,
              line: UInt = #line)</span></span>
}
</code></pre>
<p>You conform the Loggers to the <code>LogEngine</code> protocol</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SystemLogger</span>: <span class="hljs-title">LogEngine</span> </span>{ ... }
<span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SwiftyBeaverLogger</span>: <span class="hljs-title">LogEngine</span> </span>{ ... }
<span class="hljs-type">And</span> add the `<span class="hljs-type">LoggersManager</span>`
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">LoggersManager</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> engines: [<span class="hljs-type">LogEngine</span>] {
        [<span class="hljs-type">SystemLogger</span>.main,
        <span class="hljs-type">SwiftyBeaverLogger</span>.main]
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">info</span><span class="hljs-params">(message: String,
              metaData: [String: Encodable]?,
              file: String = #file,
              function: String = #function,
              line: UInt = #line)</span></span> {
        engines.forEach { 
            $<span class="hljs-number">0</span>.info(
                message: message,
                  metaData: metaData,
                  file: file,
                  function: function,
                  line: line)
 }
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">warn</span><span class="hljs-params">(message: String,
              metaData: [String: Encodable]?,
              file: String = #file,
              function: String = #function,
              line: UInt = #line)</span></span> {
        engines.forEach { 
            $<span class="hljs-number">0</span>.warn(
                message: message,
                  metaData: metaData,
                  file: file,
                  function: function,
                  line: line)
         }
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">error</span><span class="hljs-params">(message: String,
              metaData: [String: Encodable]?,
              file: String = #file,
              function: String = #function,
              line: UInt = #line)</span></span> {
        engines.forEach { 
            $<span class="hljs-number">0</span>.error(
                message: message,
                  metaData: metaData,
                  file: file,
                  function: function,
                  line: line)
        }
    }
}
</code></pre>
<p>So back to our previous example, we can now do some edits</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">handle</span><span class="hljs-params">(deeplink: String)</span></span> {
  <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> deeplinkUrl = <span class="hljs-type">URL</span>(string: deeplink) <span class="hljs-keyword">else</span> { 
<span class="hljs-comment">//    debugPrint("coudln't unwrap \(deeplink) as a URL for handling it.")</span>
    <span class="hljs-type">LoggersManager</span>.error(<span class="hljs-string">"coudln't unwrap \(deeplink) as a URL for handling it."</span>)
    <span class="hljs-keyword">return</span>
  }
  ...
}
</code></pre>
<p>And now, we have something like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658321373304/5CXrWgNLM.png" alt="image.png" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You decide to persuade Dr. Strange to watch other dimensions and, actually, you found another one where issues are monitored, and reported way before it may reach the users (or Bob’s mischievous-evilly-cursed-little-fingers), next time we will discuss the importance of having Error Monitoring tools like <code>Sentry</code>, and how you can use them to not just monitor errors and logs, but also gain more insights on the user’s environment which will help in having better Error Handling</p>
]]></content:encoded></item><item><title><![CDATA[Error Handling: Silent Bullets]]></title><description><![CDATA[Hello there! 👋
It’s been a while, and I really missed writing a blog early in the morning!
Now that I have some sort of free time, I wanted to discuss some techniques in Error handling over the coming days that I learned, and well, thought it would ...]]></description><link>https://blog.ahmedramy.me/error-handling-silent-bullets</link><guid isPermaLink="true">https://blog.ahmedramy.me/error-handling-silent-bullets</guid><category><![CDATA[error handling]]></category><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[scalability]]></category><category><![CDATA[maintenance]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Tue, 19 Jul 2022 08:48:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658234741644/AMxJlzaSu.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello there! 👋</p>
<p>It’s been a while, and I really missed writing a blog early in the morning!
Now that I have some sort of free time, I wanted to discuss some techniques in Error handling over the coming days that I learned, and well, thought it would be interesting to share! 😄</p>
<p>I wanted to start with something that may not be obvious all the time, especially when you prefer to be safe away from crashes, which is unwrapping optional variables</p>
<h2 id="heading-the-problem">The Problem 💥</h2>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">handle</span><span class="hljs-params">(deeplink: String)</span></span> {
  <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> deeplinkUrl = <span class="hljs-type">URL</span>(string: deeplink) <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
  ...
}
</code></pre>
<p>In the current context of the above method, you need to make sure that the URL is unwrapped after receiving the <code>deeplink</code>, and if the <code>deeplink</code> is invalid for whatever reason, we won’t continue executing the method</p>
<blockquote>
<p>Seems… kinda normal, right?</p>
</blockquote>
<p>Nope, it’s not always okay to early return silently, while it may not affect the program’s execution or create any bug (not always)…
It may be a sign of something went wrong, without firing any alarms, like a bug hiding in plain sight, like a...</p>
<h2 id="heading-silent-bullet">Silent Bullet 🔫</h2>
<p>Silent Bullets are parts of your code that fail without firing any warnings, and the pattern where you unwrap a variable without handling the case where its indeed nil may create weird behaviors, and we, the developers, should be notified when something like this goes wrong</p>
<h2 id="heading-remedy">Remedy 🌿</h2>
<p>Logging such behavior should be what you do in such case, to give you a second pair of eyes when something goes wrong, be it a technical issue, bad usage from another team, or a glitch in the matrix</p>
<p><img src="https://media.giphy.com/media/wwg1suUiTbCY8H8vIA/giphy-downsized-large.gif" alt="Cat walking in Matrix" /></p>
<p>For the scope of this post, we will stop at just printing this issue, in the next post we will talk more about Logs and why you need them, then walk you through a better approach than just printing it</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">handle</span><span class="hljs-params">(deeplink: String)</span></span> {
  <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> deeplinkUrl = <span class="hljs-type">URL</span>(string: deeplink) <span class="hljs-keyword">else</span> { 
    <span class="hljs-built_in">debugPrint</span>(<span class="hljs-string">"coudln't unwrap \(deeplink) as a URL for handling it."</span>)
    <span class="hljs-keyword">return</span>
  }
  ...
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Not always unwrapping optional parameters may be a good thing, when reviewing/writing unwrapping code, ask yourself, is it normal for my use case that this variable may become nil by design? Or if it became nil that indicates a problem? 🤔</p>
<p>Happy Coding!
<img src="https://media.giphy.com/media/3oriO8vwmRIZO6kcNO/giphy.gif" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Life: The other side of War]]></title><description><![CDATA[Hi all, this article is more of a reflection on what happened today at SWVL (where I work) and how it felt like seeing your close friends and teammates go, and what lessons I saw in them… it won't be long, but I hope you find it useful
What it means ...]]></description><link>https://blog.ahmedramy.me/the-other-side-of-war</link><guid isPermaLink="true">https://blog.ahmedramy.me/the-other-side-of-war</guid><category><![CDATA[life]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Tue, 31 May 2022 01:12:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1653959195203/0lYIEagen.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi all, this article is more of a reflection on what happened today at SWVL (where I work) and how it felt like seeing your close friends and teammates go, and what lessons I saw in them… it won't be long, but I hope you find it useful</p>
<h2 id="heading-what-it-means-to-be-downsized">What it means to be downsized</h2>
<p>It’s bad, you always read about it from time to time, you feel people in LinkedIn, you may interact with people who got them from other companies, and it’s all good until you find yourself in a position where you suddenly have to say goodbye two days after you do some technical planning to a feature with your teammates</p>
<h2 id="heading-its-sudden">It’s sudden</h2>
<p>No one expects to wake up one day to find himself at risk of losing his job, especially when things are not clear who is staying and who’s going, we work full-time in the hopes of having job security and other benefits like work-life balance, but there is always a lesson</p>
<h2 id="heading-panic-and-grief">Panic and grief</h2>
<p>When we first learned that there will be downsizing, everything went from very good to panic mode, and until things settled, and we learned who was going, we basically turned to grief, like being in a war where you find that you’re not dead by the end of it, but you can’t live on, knowing that your friends won’t come back, and that’s where grief started</p>
<h2 id="heading-reflection">Reflection</h2>
<p>I always asked, what would I do if I was laid off? Would I be able to keep my composure? Think straight? Everyone has his responsibilities towards his family/himself y'know?</p>
<p>And unfortunately, I couldn’t find an answer, however, there was something to tell myself</p>
<blockquote>
<p>“In the moments of crisis, panic does nothing, harness it, let it serve you” — Kratos, God of War Ragnarok Trailer</p>
</blockquote>
<p>My Sifu (Kung fu Master) always tell us in training to never do two things</p>
<blockquote>
<ol>
<li>Back away from your enemy/opponent</li>
<li>Give your back to an enemy/opponent</li>
</ol>
</blockquote>
<p>And those are the key to anything in life, hardships happen, that’s normal, but panicking does nothing, instead of panicking, use fear/anger to become hungrier than ever, and fight your way to the top again</p>
<p>Never back away and despair and let life get the best of you, you’re your only salvation, so don’t give up on yourself and ask “what am I gonna do?”</p>
<p>And this is my message to all my friends at SWVL that were laid off today, stay strong, we were and are a family, you are strong and smart, so don't let this get the best of you, it's a storm that will pass</p>
]]></content:encoded></item><item><title><![CDATA[Problem Solving: Introduction]]></title><description><![CDATA[Introduction
Hello, Hello 👋 
It's been a while since I last added something to my humble blog 😄
This time, I am not teaching, but rather documenting my learnings, hoping that I become ready for FAANG-level thinking or hopefully helping whoever read...]]></description><link>https://blog.ahmedramy.me/problem-solving-introduction</link><guid isPermaLink="true">https://blog.ahmedramy.me/problem-solving-introduction</guid><category><![CDATA[problem solving skills]]></category><category><![CDATA[data structures]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Fri, 20 May 2022 13:00:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652811141678/demxEiT95.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Hello, Hello 👋 
It's been a while since I last added something to my humble blog 😄</p>
<p>This time, I am not teaching, but rather documenting my learnings, hoping that I become ready for FAANG-level thinking or hopefully helping whoever reads this. I am starting pretty simple here to get my hands going with the writing, so let's dive deep!</p>
<h2 id="heading-lets-start-with-the-why">Let's start with the "Why"</h2>
<blockquote>
<p>What's with the nerdy approach? Why start with theories when you can jump straight to the problems?</p>
</blockquote>
<p>Because you're not going to be interviewed to solve a weird problem that is hard to be read and understand, let alone solve, you're here to communicate how your brain ticks, and if its ticking is good at solving problems or it will bail out if it hit a roadblock and start calling for help?</p>
<p>So instead of calling it 'nerdy' or 'academic', I like to call it strategic, so let's see our options</p>
<h2 id="heading-first-things-first">First things first</h2>
<p>My first thing to focus on is some pointers I did fail at in couple of interviews I had in the past when it came to Problem Solving</p>
<p>I messed up at two things... </p>
<ol>
<li>How to break the problem down into small problems</li>
<li>Communicate my thoughts to my interviewers</li>
</ol>
<blockquote>
<p>But solving the problems was never the deal breakers</p>
</blockquote>
<p>When I returned to my mentor and asked him where did I go wrong, and shouldn't be intensive study of System Designs and Architecture be sufficient...</p>
<blockquote>
<p>To me, they were... 😂</p>
</blockquote>
<p>but his answer was really insightful, they're both two skills that feed each other, but they're completely different when training them</p>
<p>and his advice was to learn about data structure first, read about it a bit and understand them, then start solving your way to the hard problems, solving only 1 easy problem a day until you can find yourself comfortable</p>
<p>So, I curated some rough headlines I would study and write about so it can enforce the learning</p>
<h2 id="heading-sources-we-need-first-for-a-solid-foundation-on-what-we-need-to-solve-problems">Sources we need first for a solid foundation on what we need to solve problems</h2>
<blockquote>
<p>And... TADA! 🎉 </p>
</blockquote>
<ol>
<li>Learn about Data structure, and what are they?, in a basic and simple manner</li>
<li>Learn about complexity and measuring it, memory-wise &amp; processing-wise</li>
<li>Learn about <code>Big O Notion</code></li>
<li>Learn about Logarithm</li>
<li>Start dissecting the Data Structures into categories of...<ol>
<li>Array</li>
<li>Linked Lists</li>
<li>Hash Tables (or Dictionaries)</li>
<li>Stacks &amp; Queues</li>
<li>Strings</li>
<li>Graphs</li>
<li>Trees</li>
</ol>
</li>
</ol>
<p>In the next blog post, we will start with what are Data structure</p>
]]></content:encoded></item><item><title><![CDATA[Test-Driven Development: #7 Navigation]]></title><description><![CDATA[Introduction
Hey hey, so we’re back for a quick one today, which is navigation, let’s start it with a good question 🙋‍♂️ 

Did you try implementing last blog post’s challenge of doing it on your own?


Well, fear not, because we’re here to fix that!...]]></description><link>https://blog.ahmedramy.me/test-driven-development-7-navigation</link><guid isPermaLink="true">https://blog.ahmedramy.me/test-driven-development-7-navigation</guid><category><![CDATA[TDD (Test-driven development)]]></category><category><![CDATA[Testing]]></category><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[navigation]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Mon, 21 Mar 2022 15:29:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647874558488/MwgByVl65.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>Hey hey, so we’re back for a quick one today, which is navigation, let’s start it with a good question 🙋‍♂️ </p>
<blockquote>
<p>Did you try implementing last blog post’s challenge of doing it on your own?
<img src="https://c.tenor.com/4WZm1vgS_-8AAAAS/the-simpsons-homer-simpson.gif" alt /></p>
</blockquote>
<p>Well, fear not, because we’re here to fix that!
<img src="https://c.tenor.com/rPOqhxQBOz0AAAAS/all-might-my-hero-academia.gif" alt /></p>
<h1 id="heading-enters-navigation">Enters Navigation</h1>
<p>Last time we talked was about displaying alerts, since we have a private access to the current visible Controller, we can do navigation access on it, all while encapsulating it, but first, let’s imagine how our tests would be, so you can also learn the thought process</p>
<h2 id="heading-imagining-the-code-in-tests">Imagining the Code in Tests</h2>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">testGivenUserLogsInSuccessfully_WhenSuccessHappens_ThenHeShouldBeNavigatedToHomeScreen</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Given</span>
    <span class="hljs-keyword">let</span> email = <span class="hljs-string">"valid_email@gmail.com"</span>
    <span class="hljs-keyword">let</span> password = <span class="hljs-string">"Somevalid1Password"</span>

    <span class="hljs-comment">// When</span>
    sut.login(email: email, password: password)

    <span class="hljs-comment">// Then</span>
    <span class="hljs-type">XCTAssertTrue</span>(
      router.actions.<span class="hljs-built_in">contains</span>(
        .present(
          <span class="hljs-type">HomeViewController</span>.<span class="hljs-keyword">self</span>,
          presentationStyle: .fullScreen
        )
      )
    )
  }
</code></pre>
<p>So what I want at the end is something that tells me, hey, the type of the controller u passed is <code>HomeViewController</code>, and the presentation style is <code>fullScreenPresentation</code></p>
<blockquote>
<p>💡 For those reading outside iOS background, the fullScreen presentation is needed here as there are two types of presenting a screen, so we specify that here to avoid returning back to the login screen without a need, hence reinforcing our navigation logic</p>
</blockquote>
<p>Now that we have an imagination in place of how our APIs would look like, let’s try to implement them</p>
<h2 id="heading-making-it-real">Making it real</h2>
<pre><code class="lang-swift"><span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">extension</span> <span class="hljs-title">LoginViewModel</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">validate</span><span class="hljs-params">(<span class="hljs-number">_</span> email: String, <span class="hljs-number">_</span> password: String)</span></span> {
    ...
    router.alertWithAction(
      title: <span class="hljs-string">"Validation Errors"</span>,
      message: errors.<span class="hljs-built_in">map</span> { $<span class="hljs-number">0</span>.text }.joined(separator: <span class="hljs-string">"\n"</span>),
      alertStyle: .actionSheet,
      actions: [
        (title: <span class="hljs-string">"Ok"</span>, style: .<span class="hljs-keyword">default</span>, action: { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] <span class="hljs-keyword">in</span>
          <span class="hljs-keyword">self</span>?.state.send(.idle) &lt;- <span class="hljs-type">Added</span>
        })
      ]
    )
  }
}
</code></pre>
<p>First, let’s reset our state to <code>idle</code> once the user dismissed the alert sheet, this way we can have a better state handling</p>
<h2 id="heading-sneak-peak-into-the-future-of-this-series">Sneak peak into the future of this Series</h2>
<p>Second, in our <code>login method</code>, we can edit the implementation to go to a pre-built ViewController called <code>HomeViewController</code> where we will later on build an mini part of an E-Commerce app, so that we can later on test Common E-Commerce logic</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">login</span><span class="hljs-params">(email: String, password: String)</span></span> {
    validate(email, password)

    <span class="hljs-keyword">guard</span> state.value.errors.isEmpty <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }

    <span class="hljs-type">ServiceLocator</span>.main.network.call(
      api: <span class="hljs-type">AuthEndpoint</span>.login(email: email, password: password),
      model: <span class="hljs-type">AccessToken</span>.<span class="hljs-keyword">self</span>
    ).sink(receiveCompletion: { onComplete <span class="hljs-keyword">in</span>
      <span class="hljs-keyword">guard</span> <span class="hljs-keyword">case</span> <span class="hljs-keyword">let</span> .failure(error) = onComplete <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
      <span class="hljs-keyword">self</span>.state.send(.failure([error.toOError()]))
    }, receiveValue: { [<span class="hljs-keyword">weak</span> <span class="hljs-keyword">self</span>] token <span class="hljs-keyword">in</span>
      <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> <span class="hljs-keyword">self</span> = <span class="hljs-keyword">self</span> <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
      <span class="hljs-keyword">try</span>? <span class="hljs-type">ServiceLocator</span>.main.cache.save(value: token, <span class="hljs-keyword">for</span>: .accessToken)

    <span class="hljs-comment">// Addition starts</span>
      <span class="hljs-keyword">self</span>.router.present(
        <span class="hljs-type">HomeViewController</span>(),
        presentationStyle: .fullScreen
      )
    <span class="hljs-comment">// Addition ends</span>
    }).store(<span class="hljs-keyword">in</span>: &amp;cancellables)
  }
</code></pre>
<p>You will notice the pattern that we’re trying to reach now, we are testing if <code>Home</code> screen was pushed to the UI after a successful login</p>
<blockquote>
<p>Note: We don’t call an actual API, WE’RE THE API 😎
Just kidding, indeed we don’t have an API, but that’s the power of Fake, where we can later on have our API installed in a backend server, and we can replace the contract with ease 🎉</p>
</blockquote>
<h2 id="heading-green-checkmarks">Green Checkmarks</h2>
<p>What comes next is seeing the green check marks ticking into our tests, and a safety net if something broke
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647874261262/UoCSZvaIU.png" alt /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>What we did today was a good way of integration testing, as you can see we are testing if the user gets routed correctly as per the business, when logging in, there might be a case that I decided to not do in the current project since it’s too simple and lots of setup is needed to make it possible which is <code>automatically routing the user to Home after he logs in correctly</code>
If you’re looking for pointers on how to do this, here are some steps you can follow and some ideas</p>
<ol>
<li>Programmatically launch Home or Login if the user already logged in once by finding the Access Token in the Cache/Storage</li>
<li>Introduce the concept of Coordinator, which programmatically (not in the Interface builder) determines which screen is required to be present</li>
</ol>
<p>I think it’s time to close down this series 🥲</p>
<p><img src="https://c.tenor.com/2jwpBY5ujg8AAAAC/loki-very.gif" alt /></p>
<p>Anyway, I’ve been thinking on writing a series on The Composable Architecture (TCA), and it’s time to introduce a video series about building a chat app using it 😆</p>
<p>It’s been exciting dealing with TCA so far and how it makes it easy to work with SwiftUI</p>
<p>So next stop is returning to the good old <code>Redux</code> series</p>
]]></content:encoded></item><item><title><![CDATA[Test-Driven Development: #6 Testing Alerts, Popups, and Messages]]></title><description><![CDATA[Introduction
It's been a long time!
Really happy that I have time to write about TDD again, and with an interesting topic from which we can know if our users had seen an alert, popups, or simply seen a message (toast) appearing to him
The Point?
How ...]]></description><link>https://blog.ahmedramy.me/test-driven-development-6-testing-alerts-popups-and-messages</link><guid isPermaLink="true">https://blog.ahmedramy.me/test-driven-development-6-testing-alerts-popups-and-messages</guid><category><![CDATA[TDD (Test-driven development)]]></category><category><![CDATA[UI]]></category><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Sat, 12 Mar 2022 09:09:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647076110553/6-tNXqY5m.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>It's been a long time!
Really happy that I have time to write about TDD again, and with an interesting topic from which we can know if our users had seen an alert, popups, or simply seen a message (toast) appearing to him</p>
<h1 id="heading-the-point">The Point?</h1>
<p>How is this important, you ask?</p>
<p>Well, Imagine that our user is trying to log in but he is giving us an invalid email without him noticing, it would be nice to either show a message to him, saying that he missed a '@' in the email field</p>
<p>But what if after a couple of iterations over our app, and somewhere in version '1.4.3', this broke, and users no longer get a hint about why their email is not getting accepted, especially for an old user of our app, it might get irritating</p>
<p>However, if a test covers this; before we even launch any new version, this issue would be well on our issue tracker.</p>
<p>So this post we will cover how to cover such cases with a unit test coverage, and I think it would be interesting in showing how do I handle issues in my project in another post</p>
<p>Without further ado, let's get rolling 😎</p>
<p><img src="https://media.giphy.com/media/1q1HFsghu6TqSFjAfo/giphy.gif" alt="Dr. Eggman getting ready" /></p>
<h1 id="heading-revisiting-the-project-after-some-changes">Revisiting the project after some changes</h1>
<p>Remember that last demo video I put on <a target="_blank" href="https://blog.ahmedramy.me/test-driven-development-5-refactoring-validation">the previous post of this series?</a></p>
<p>Well, I did promise you guys that I will make improvements to the refactoring and I did,</p>
<p>It now utilizes my open-source <a target="_blank" href="https://github.com/ARamy23/OrdiKit">OrdiKit</a> which is a fast way for me to put files I use from time to time, or just wanna test an idea or probably launch a project, it utilizes SwiftUI and UIKit</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647070794023/LZn_G-RB1.png" alt="Showing Ordikit in the project" /></p>
<p>I don't want to spend much time on what went on in the Refactoring, but there is an interesting part I believe, which is called <code>ServiceLocator</code></p>
<p>It's a pattern from Game Development and is a bit strange in iOS development as it uses <a target="_blank" href="https://refactoring.guru/design-patterns/singleton">Singletons</a></p>
<p>Before you throw any knives in the comments, let's take a step back and see why is this put here</p>
<p>If we think about <code>Network</code> and <code>Cache</code>, normally these are 2 dependencies where the app depends on</p>
<p>They shouldn't be repeated or recreated, in fact, that would create a problem if am tracking the progress of some network calls, or am storing 2 stuff simultaneously on the disk</p>
<p>So it makes sense to have this as a single instance inside the <code>ServiceLocator</code>.</p>
<p>Other than that, we're ready to go test our side-effects in form of alerts</p>
<p>If we return to our Testing file <code>TDDTests/Login/LoginTests</code></p>
<p>We can add a test function like so…</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">test_GivenInvalidEmail_WhenLogin_UserSeesAnAlert</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Given</span>
    <span class="hljs-keyword">let</span> email = <span class="hljs-string">""</span>
    <span class="hljs-keyword">let</span> password = <span class="hljs-string">"Somevalid1Password"</span>

    <span class="hljs-comment">// When</span>
    sut.login(email: email, password: password)

    <span class="hljs-comment">// Then</span>
    <span class="hljs-type">XCTAssertEqual</span>(
      router.routingAction,
      <span class="hljs-type">RoutingAction</span>.alert(<span class="hljs-type">ValidationError</span>.empty(.email).errorDescription)
    )
  }
</code></pre>
<p>You will find that we want to have a new dependency called <code>router</code>, ideally the router would have its own state or action, so we can check if that action corresponds to what we want to verify, in our case, when the user forgets to pass his email, in such case we would want to show an alert (just for sake of simplicity for now), that he can’t leave his email blank</p>
<p>As of now, we don’t have such functionality so let’s start adding it to our production code</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-keyword">typealias</span> <span class="hljs-type">AlertAction</span> = (title: <span class="hljs-type">String</span>, style: <span class="hljs-type">UIAlertAction</span>.<span class="hljs-type">Style</span>, action: () -&gt; <span class="hljs-type">Void</span>)

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">RouterProtocol</span>: <span class="hljs-title">AnyObject</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">present</span><span class="hljs-params">(<span class="hljs-number">_</span> view: UIViewController)</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">startActivityIndicator</span><span class="hljs-params">()</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">stopActivityIndicator</span><span class="hljs-params">()</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">dismiss</span><span class="hljs-params">()</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">pop</span><span class="hljs-params">(animated: Bool)</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">popToRoot</span><span class="hljs-params">()</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">popTo</span><span class="hljs-params">(vc: UIViewController)</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">push</span><span class="hljs-params">(<span class="hljs-number">_</span> view: UIViewController)</span></span>
  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">alertWithAction</span><span class="hljs-params">(
    title: String?,
    message: String?,
    alertStyle: UIAlertController.Style,
    actions: [AlertAction]
  )</span></span>
}
</code></pre>
<p>This is how our Routing functionality is going to provide, now let’s wait here and think what is going on</p>
<p>What we want, is an encapsulated access to our ViewController from the presentation layer, in our case, the <code>LoginViewModel</code> this encapsulation provides us with scoping to just the navigation functionality, so I can control the ViewController’s navigation from here, without having any access on the ViewController itself, let’s see how with extra details, by defining our Router Implementor</p>
<pre><code class="lang-swift"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Router</span>: <span class="hljs-title">RouterProtocol</span> </span>{
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">weak</span> <span class="hljs-keyword">var</span> presentedView: <span class="hljs-type">UIViewController!</span>

  <span class="hljs-keyword">init</span>(<span class="hljs-number">_</span> view: <span class="hljs-type">UIViewController</span>) {
    presentedView = view
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">present</span><span class="hljs-params">(<span class="hljs-number">_</span> view: UIViewController)</span></span> {
    presentedView?.present(view, animated: <span class="hljs-literal">true</span>, completion: <span class="hljs-literal">nil</span>)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">dismiss</span><span class="hljs-params">()</span></span> {
    presentedView?.dismiss(animated: <span class="hljs-literal">true</span>, completion: <span class="hljs-literal">nil</span>)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">pop</span><span class="hljs-params">(animated: Bool)</span></span> {
    <span class="hljs-number">_</span> = presentedView?.navigationController?.popViewController(animated: animated)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">popToRoot</span><span class="hljs-params">()</span></span> {
    <span class="hljs-number">_</span> = presentedView?.navigationController?.popToRootViewController(animated: <span class="hljs-literal">true</span>)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">popTo</span><span class="hljs-params">(vc: UIViewController)</span></span> {
    <span class="hljs-number">_</span> = presentedView?.navigationController?.popToViewController(vc, animated: <span class="hljs-literal">true</span>)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">push</span><span class="hljs-params">(<span class="hljs-number">_</span> view: UIViewController)</span></span> {
    presentedView?
      .navigationController?
      .pushViewController(view, animated: <span class="hljs-literal">true</span>)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">alertWithAction</span><span class="hljs-params">(
    title: String?,
    message: String?,
    alertStyle: UIAlertController.Style,
    actions: [AlertAction]
  )</span></span> {
    <span class="hljs-keyword">let</span> alert = <span class="hljs-type">UIAlertController</span>(title: title, message: message, preferredStyle: alertStyle)
    actions.<span class="hljs-built_in">map</span> { action <span class="hljs-keyword">in</span>
      <span class="hljs-type">UIAlertAction</span>(title: action.title, style: action.style, handler: { (<span class="hljs-number">_</span>) <span class="hljs-keyword">in</span>
        action.action()
      })
    }.forEach {
      alert.addAction($<span class="hljs-number">0</span>)
    }

    presentedView?.present(alert, animated: <span class="hljs-literal">true</span>)
  }
}
</code></pre>
<p>Notice the <code>private</code> access modifier before the controller? Exactly what we’re looking for</p>
<h1 id="heading-giving-our-viewmodel-the-power-of-navigation">Giving our ViewModel The Power of Navigation</h1>
<p>If we get back to our ViewModel, we can now hand it a router by dependency injection, and have it show the view an alert when needed</p>
<pre><code class="lang-swift">
...
  <span class="hljs-keyword">var</span> cancellables = <span class="hljs-type">Set</span>&lt;<span class="hljs-type">AnyCancellable</span>&gt;()
  <span class="hljs-keyword">var</span> router: <span class="hljs-type">RouterProtocol</span>

  <span class="hljs-keyword">init</span>(router: <span class="hljs-type">RouterProtocol</span>) {
    <span class="hljs-keyword">self</span>.router = router
  }
...
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">validate</span><span class="hljs-params">(<span class="hljs-number">_</span> email: String, <span class="hljs-number">_</span> password: String)</span></span> {
    ...
    <span class="hljs-keyword">guard</span> !errors.isEmpty <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }
    state.send(.failure(errors))
    router.alertWithAction(
      title: <span class="hljs-string">"Validtion Errors"</span>,
      message: errors.<span class="hljs-built_in">map</span> { $<span class="hljs-number">0</span>.text }.joined(separator: <span class="hljs-string">"\n"</span>),
      alertStyle: .actionSheet,
      actions: [
        (title: <span class="hljs-string">"Ok"</span>, style: .<span class="hljs-keyword">default</span>, action: { })
      ]
    )
  }
</code></pre>
<p>If we ran and tested our code…</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647075483526/KYYzcSNct.png" alt="image.png" /></p>
<blockquote>
<p>Voilà </p>
</blockquote>
<h1 id="heading-faking-our-router-until-we-make-it">Faking our Router until we make it</h1>
<p>Now comes our testing code’s turn</p>
<p>First, we need to create a <code>FakeRouter</code> that gives us information about the navigation state
In order for us to have access to our navigation stack, we need to define a state enum, which holds the actions given to the router</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">RoutingAction</span>: <span class="hljs-title">Equatable</span> </span>{
  <span class="hljs-keyword">case</span> present(<span class="hljs-number">_</span> vc: <span class="hljs-type">UIViewController</span>.<span class="hljs-type">Type</span>)
  <span class="hljs-keyword">case</span> push(<span class="hljs-number">_</span> vc: <span class="hljs-type">UIViewController</span>.<span class="hljs-type">Type</span>)
  <span class="hljs-keyword">case</span> dismiss
  <span class="hljs-keyword">case</span> pop
  <span class="hljs-keyword">case</span> popToRoot
  <span class="hljs-keyword">case</span> popToVC
  <span class="hljs-keyword">case</span> popTo(<span class="hljs-number">_</span> vc: <span class="hljs-type">UIViewController</span>.<span class="hljs-type">Type</span>)
  <span class="hljs-keyword">case</span> alertWithAction((title: <span class="hljs-type">String</span>, message: <span class="hljs-type">String</span>))

  <span class="hljs-keyword">static</span> <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">func</span> ==<span class="hljs-params">(lhs: RoutingAction, rhs: RoutingAction)</span></span> -&gt; <span class="hljs-type">Bool</span> {
    <span class="hljs-keyword">switch</span> (lhs, rhs) {
      <span class="hljs-keyword">case</span> <span class="hljs-keyword">let</span> (.popTo(a), .popTo(b)): <span class="hljs-keyword">return</span> a == b
      <span class="hljs-keyword">case</span> <span class="hljs-keyword">let</span> (.present(a), .present(b)): <span class="hljs-keyword">return</span> a == b
      <span class="hljs-keyword">case</span> <span class="hljs-keyword">let</span> (.push(a), .push(b)): <span class="hljs-keyword">return</span> a == b
      <span class="hljs-keyword">case</span> <span class="hljs-keyword">let</span> (.alertWithAction(a), .alertWithAction(b)):
        <span class="hljs-keyword">return</span> a.title == b.title &amp;&amp; a.message == b.message
      <span class="hljs-keyword">case</span> (.dismiss, .dismiss),
        (.pop, .pop),
        (.popToRoot, .popToRoot),
        (.popToVC, .popToVC):
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>
      <span class="hljs-keyword">default</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
    }
  }
}
</code></pre>
<p>This way, we can have an in-memory storage that we can use it later on, to test against whether the user did present a view, did push to a view, or simply gave an alert</p>
<p>And to wrap it up so we can continue on with testing…</p>
<pre><code class="lang-swift"><span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FakeRouter</span>: <span class="hljs-title">RouterProtocol</span> </span>{
  <span class="hljs-keyword">var</span> actions: [<span class="hljs-type">RoutingAction</span>] = []
  <span class="hljs-keyword">var</span> alertActions: [<span class="hljs-type">AlertAction</span>] = []

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">popToRoot</span><span class="hljs-params">()</span></span> {
    actions.append(.popToRoot)
  }

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">popTo</span><span class="hljs-params">(vc: UIViewController)</span></span> {
    actions.append(.popToVC)
  }

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">push</span><span class="hljs-params">(<span class="hljs-number">_</span> view: UIViewController)</span></span> {
    actions.append(.push(type(of: view)))
  }

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">present</span><span class="hljs-params">(<span class="hljs-number">_</span> view: UIViewController)</span></span> {
    actions.append(.present(type(of: view)))
  }

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">dismiss</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">self</span>.actions.append(.dismiss)
  }

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">alertWithAction</span><span class="hljs-params">(
    title: String?,
    message: String?,
    alertStyle: UIAlertController.Style,
    actions: [AlertAction]
  )</span></span> {
    <span class="hljs-keyword">self</span>.actions.append(.alertWithAction((title ?? <span class="hljs-string">""</span>, message ?? <span class="hljs-string">""</span>)))
    <span class="hljs-keyword">self</span>.alertActions.append(contentsOf: actions)
  }

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">pop</span><span class="hljs-params">(animated: Bool)</span></span> {
    <span class="hljs-keyword">self</span>.actions.append(.pop)
  }
}
</code></pre>
<p>Notice how we append the type to the <code>actions</code> array?, similar to our <code>FakeCache</code>, we just register it until the test has run, so we can later on test against if it indeed has a certain action that we expect it to be, or not.</p>
<p>Back to our tests, now we need to supply our SUT with a FakeRouter so we can test it</p>
<h1 id="heading-wrapping-it-up">Wrapping it up</h1>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoginViewModelTests</span>: <span class="hljs-title">XCTestCase</span> </span>{

  <span class="hljs-keyword">var</span> network: <span class="hljs-type">FakeNetworkManager!</span>
  <span class="hljs-keyword">var</span> cache: <span class="hljs-type">FakeCache!</span>
  <span class="hljs-keyword">var</span> router: <span class="hljs-type">FakeRouter!</span> <span class="hljs-comment">// &lt;- Changed</span>
  <span class="hljs-keyword">var</span> sut: <span class="hljs-type">LoginViewModel!</span>

  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">setUp</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">super</span>.setUp()
    network = .<span class="hljs-keyword">init</span>()
    cache = .<span class="hljs-keyword">init</span>()
    router = .<span class="hljs-keyword">init</span>() <span class="hljs-comment">// &lt;- Changed</span>

    <span class="hljs-type">ServiceLocator</span>.main = .<span class="hljs-keyword">init</span>(network: network, cache: cache)

    sut = .<span class="hljs-keyword">init</span>(router: router) <span class="hljs-comment">// &lt;- Changed</span>
  }

  <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">tearDown</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">super</span>.tearDown()
    network = <span class="hljs-literal">nil</span>
    cache = <span class="hljs-literal">nil</span>
    router = <span class="hljs-literal">nil</span> <span class="hljs-comment">// &lt;- Changed</span>
    sut = <span class="hljs-literal">nil</span>
  }
</code></pre>
<p>Now that our LoginViewModel knows how to use our <code>FakeRouter</code>, let’s fix some of our test code below</p>
<pre><code class="lang-swift"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">test_GivenInvalidEmail_WhenLogin_UserSeesAnAlert</span><span class="hljs-params">()</span></span> {
    <span class="hljs-comment">// Given</span>
    <span class="hljs-keyword">let</span> email = <span class="hljs-string">""</span>
    <span class="hljs-keyword">let</span> password = <span class="hljs-string">"Somevalid1Password"</span>

    <span class="hljs-comment">// When</span>
    sut.login(email: email, password: password)

    <span class="hljs-comment">// Then</span>
    <span class="hljs-type">XCTAssertEqual</span>(
      router.actions,
      [
        <span class="hljs-type">RoutingAction</span>.alertWithAction((
          title: <span class="hljs-string">"Validation Errors"</span>,
          message: <span class="hljs-string">"Email can't be empty"</span>
        ))
      ]
    )
  }
</code></pre>
<p>And that’s it!</p>
<p><img src="https://media.giphy.com/media/cXblnKXr2BQOaYnTni/giphy.gif" alt="Michael from The Office Saluting you" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Now that we have a way of testing our Alerts, Popups, and Messages… or simply what I like to call them, Async Views, where a view cuts through the flow for the user to take an action then return to the normal flow
We can now go to our next stop which is testing the our navigation flow, which by now you can guess how it really can be easy</p>
<blockquote>
<p>Tell you what, how about you try to implement this on your own? You will be amazed by how easy it is now to test your navigation, and next stop we will go over it quickly and talk about something really important, which by now, the ViewModel became somewhat big, so let’s talk about how we can dissect it even further, so we can avoid going from ‘MVC’ to ‘MVVM’ (aka, massive view controller, to massive view model) 😉</p>
</blockquote>
<p>And if you’re an eager one and wants to know our progress on Github, feel free to see the <a target="_blank" href="https://github.com/ARamy23/TDD">code here</a></p>
]]></content:encoded></item><item><title><![CDATA[Mindset Books: The 5 AM Club]]></title><description><![CDATA[Sure waking up is early and sleeping early is essential and healthy, but let’s be more specific by learning from ‘Robin Sharma’
What to expect?
Robin speaks about how waking up early at 5 AM, and investing that time into learning and doing complicate...]]></description><link>https://blog.ahmedramy.me/mindset-books-the-5-am-club</link><guid isPermaLink="true">https://blog.ahmedramy.me/mindset-books-the-5-am-club</guid><category><![CDATA[Productivity]]></category><category><![CDATA[habits]]></category><category><![CDATA[books]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[General Advice]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Sat, 26 Feb 2022 07:40:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645861139949/9K_piTx_p.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sure waking up is early and sleeping early is essential and healthy, but let’s be more specific by learning from ‘Robin Sharma’</p>
<h1 id="heading-what-to-expect">What to expect?</h1>
<p>Robin speaks about how waking up early at 5 AM, and investing that time into learning and doing complicated tasks is a good idea, and why successful people like Jeff Bezos, Elon Musk, Steve Jobs, and many more have had great, on-going success that may have exceeded their lifetime</p>
<h1 id="heading-concepts-are-taken-from-5-am-club">Concepts are taken from 5 AM Club</h1>
<ol>
<li>Pick who you choose to be around very carefully</li>
<li>Appreciate the little things you’ve, you never know what was yesterday a “taken for granted”, to be “good ol’ days”</li>
<li>Waking up @ 5 AM is not just healthy, it’s phenomenal</li>
<li>5 AM work sometimes can shortcut days of work in mere hours or sometimes minutes</li>
<li>Success comes from tiny details</li>
<li>Avoiding distractions and focusing on what’s important </li>
<li>Labeling and prioritizing important things to do is an important skill (yet, not the most obvious)</li>
<li>Life is short, focus on leaving a good memory of a life well-spent</li>
</ol>
<h1 id="heading-my-summary">My summary</h1>
<h2 id="heading-how-to-reach-your-goals-andamp-how-your-environment-affects-that">How to reach your goals &amp; how your environment affects that</h2>
<p>During the early chapters, Robin explains how important your inner circle is, explaining the effect of your environment on you, from befriending negative people to people who inspire you &amp; encourage you to become better</p>
<blockquote>
<p>If you want to become something, befriend people who already have it</p>
</blockquote>
<h2 id="heading-key-to-fulfillment-andamp-wealth">Key to fulfillment &amp; Wealth</h2>
<p>True wealth and fulfillment comes from uplifting and positively affecting other people’s lives, in the rush of today’s technology, appreciating little things becomes common, hence becoming accustomed to them, labeling them as ‘Ordinary’, hence feeling dissatisfied even if you have everything one would wish for</p>
<p><img src="https://media.giphy.com/media/OgfejiBYdTHXO/giphy.gif" alt="Two avocados dancing" /></p>
<h2 id="heading-the-secret-5-am-club">The secret ‘5 AM Club’</h2>
<p>Waking up every day @ 5 AM not only is healthy, but a good investment in your mind that can easily be translated into physical wealth and an extra bonus of Wisdom</p>
<p><img src="https://media.giphy.com/media/hj8eOHrXqoLntsCyWz/giphy.gif" alt="Meme from Office" /></p>
<h2 id="heading-fixation-on-goals-save-time-energy-andamp-money-and-vice-versa">Fixation on goals save time, energy &amp; money (and vice versa)</h2>
<p>Our brains tend to feel in control and really great when we have simple, trackable goals in front of us, all our brain resources are put into it, and hence, we gain a sense of assurance
However, when we are surrounded by lots of distractions and multiple, unrelated goals, chaos happens, because our brains don’t feel in control anymore, and we fall into prioritization hell, shorter focus life-span and eventually get burnt out at a higher rate (mostly by not noticing that we haven’t had a break in a long time due to all the things we need to finish)</p>
<h2 id="heading-productivity-is-not-just-a-great-mental-andamp-physical-state">Productivity is not just a great mental &amp;  physical state</h2>
<p>We often think that productivity is related to sleeping well and/or being present or active, however, there are other factors to it, for instance, human is not just an <a target="_blank" href="https://en.wikipedia.org/wiki/Intelligence_quotient">IQ</a> or a <a target="_blank" href="https://en.wikipedia.org/wiki/Body_mass_index">BMI</a>, there comes also how you’re doing <code>emotionally</code> and <code>spiritually</code>
So make sure you take care of those besides setting your schedule and sticking to it 😄</p>
<p><img src="https://media.giphy.com/media/xUNd9EJ6B6pczBelYA/giphy.gif" alt="I'm more than that" /></p>
<h2 id="heading-true-potential-gain-lies-outside-your-comfort-zone">True Potential gain lies outside your comfort zone</h2>
<p>Like muscles, challenging them with working out can lead to them growing and improving, similarly with your mind and personalities</p>
<blockquote>
<p>It turns out that the human brain has a great potential for something called neuronal plasticity, or in other words, being highly malleable. It appears that challenging our brains — for example, by learning a new skill — leads to actual changes in the adult brain. — <a target="_blank" href="https://www.health.harvard.edu/blog/challenge-your-mind-and-body-to-sharpen-your-thinking-skills-201510298507">A Harvard’s Health Blog</a></p>
</blockquote>
<h2 id="heading-waking-up-early-is-not-enough">Waking up early is not enough</h2>
<p>Waking up at 5 AM may not be enough, either as a goal, or an achievement, however, what you do when you wake up, is what matters the most to you and your future goals
Robin took the approach of breaking down the first hour into 3 parts </p>
<h2 id="heading-the-3-pockets">The 3 Pockets</h2>
<blockquote>
<p>The 3 Pockets is basically a <strong>20/20/20 Rule</strong> of chunking your first hour into 3 activities of 20 minutes each.</p>
</blockquote>
<p>Robin advises to chunk it like this</p>
<ul>
<li>The 1st 20 mins could be invested into exercising</li>
<li>The 2nd 20 mins could be invested into meditation</li>
<li>The 3rd 20 mins could be invested into learning</li>
</ul>
<p><img src="https://media.giphy.com/media/usz0fqhUiVxSs6IUKB/giphy.gif" alt /></p>
<h1 id="heading-action-time">Action Time! 👏</h1>
<p>I have two problems to tackle, so I planned a system to get over it</p>
<h3 id="heading-sleeping-early">Sleeping early</h3>
<blockquote>
<p>I mean, c’mon we’re programmers, we tend to tick late @ night, right?
Nope, that’s a lie from my subconscious to steal another episode or do something I’ll end up regretting 4 hrs later after being completely tired and no longer able to maintain opening my eyes</p>
</blockquote>
<p>So, I am doing something simple to not overcomplicate it</p>
<ol>
<li>Begin Wind down routine at 9:00 <code>preparing some warm drink, brushing teeth, etc…</code></li>
<li>By 9:30, my phone goes into a parental mode where only select apps are allowed<ol>
<li>[Balance]</li>
<li>[Sleep Cycle]</li>
</ol>
</li>
<li>I meditate to release any tension or stress while remembering what to be grateful about<h3 id="heading-fighting-the-just-5-more-mins">Fighting the ‘Just 5 more mins’</h3>
</li>
<li>Making sure I don’t break my sleep cycles ([read more about it here])</li>
<li>As soon as I am conscious that I woke up, immediately remove any blanket and run my hand over my face as If I was washing it</li>
<li>Keep my phone away (I usually fail here and end up cold in winter after I noticed that I didn’t get out of bed, rather woke up to sync myself with Twitter’s feed or Facebook’s 😆)</li>
</ol>
<h1 id="heading-conclusion">Conclusion</h1>
<p>All in all, this happened to be my first book to ever finish, as much as I’m excited, as much as I really loved sharing and grooming my thoughts about it</p>
<p>If you wanted to get the book, you can find it here on <a target="_blank" href="https://amzn.to/3M6y21Z">Amazon</a>, however, just a disclaimer so I put this off my chest, any link to any book in this series is an <code>affiliate</code> link</p>
]]></content:encoded></item><item><title><![CDATA[The Journey of the 50 Books]]></title><description><![CDATA[Hey all 👋
They say the best way to learn is to teach, and since this year I want to up my reading game by reading more, I decided to return to a couple of books that I read and share my notes, my summary & points that I was able to implement
What is...]]></description><link>https://blog.ahmedramy.me/the-journey-of-the-50-books</link><guid isPermaLink="true">https://blog.ahmedramy.me/the-journey-of-the-50-books</guid><category><![CDATA[Productivity]]></category><category><![CDATA[books]]></category><category><![CDATA[challenge]]></category><category><![CDATA[life]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Sat, 26 Feb 2022 07:24:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645860129245/c-938aPwy.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey all 👋
They say the best way to learn is to teach, and since this year I want to up my reading game by reading more, I decided to return to a couple of books that I read and share my notes, my summary &amp; points that I was able to implement</p>
<h1 id="heading-what-is-this-about">What is this about?</h1>
<p>In early 2021, I took part in a productivity course by none other than <a target="_blank" href="https://www.youtube.com/c/aliabdaal">Ali Abdaal</a>, the guy was really charismatic and really organized, and he was my favorite YouTuber that year, and he recommended lots of techniques that were foundational to me in this year</p>
<p>Not only did he share his notes-taking techniques, but also shared some books that I managed to read</p>
<p>So, in the upcoming series of books reviews, I’ll share my notes, but in the end, I’ll also share my Obsidian vault, which generally illustrates indexed &amp; searchable notes that are also linked together</p>
<h1 id="heading-so-whats-the-plan-capain">So, what’s the plan, Cap’ain?</h1>
<p>I think I have around 26 Books read by now, and what we can do is share them every week just to get started, each categorized between <code>Mindsets</code>, <code>Financial Literacy</code>, <code>Trading</code>, <code>Investing</code>, <code>Negotiations</code>, <code>Entrepreneurship</code>, and <code>Emotional Intelligence</code></p>
<p>So, am going to have 5 Lists along with this one, so you can either look up something without necessary being tracked down into a specific category, however, since some books may fall into more than one category, I think it would be a good idea to dissect the review as per the note’s category, hence shorter articles to read quick &amp; at the same time, the book itself may have its own series between its categories</p>
<h1 id="heading-alright-but-do-we-have-a-timeline-or-a-roadmap-for-this">Alright, but do we have a timeline or a roadmap for this?</h1>
<p>Oh, we do, and you can see it here 😉👇</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645859744784/e7wEwKeX3.png" alt="image.png" /></p>
<blockquote>
<p>How to read this?
Each sub-node contains a category, each category contains a book which I already read and summarized, so the process for those 26 books is to release 1-2 summaries per week, I’ll share notes about this book, some of my notes and at the end, a poll of which category should we do next</p>
</blockquote>
<h1 id="heading-where-to-go-from-here">Where to go from here?</h1>
<p>Let’s not waste time, and start our discussion about the first book together,
called <code>The 5 AM Club</code></p>
]]></content:encoded></item><item><title><![CDATA[Architecture Homicide: The Time Machine]]></title><description><![CDATA[I’d spend a couple of hours studying, planning, and understanding a problem, just to solve it in minutes.

The Time Machine
What If I told you that, there is a ball of crystal that when u do strange and funny hand moves saying non-sense in front of i...]]></description><link>https://blog.ahmedramy.me/architecture-homicide-the-time-machine</link><guid isPermaLink="true">https://blog.ahmedramy.me/architecture-homicide-the-time-machine</guid><category><![CDATA[Swift]]></category><category><![CDATA[authentication]]></category><category><![CDATA[iOS]]></category><category><![CDATA[software design]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Wed, 23 Feb 2022 15:20:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645629611455/tCgXXQ93w.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>I’d spend a couple of hours studying, planning, and understanding a problem, just to solve it in minutes.</p>
</blockquote>
<h1 id="heading-the-time-machine">The Time Machine</h1>
<p>What If I told you that, there is a ball of crystal that when u do strange and funny hand moves saying non-sense in front of it and suddenly a cloud of (usually) purple floats magically from below it to say what bugs are you going to face early on, how bad your ad-hoc design inside the code is, how miserable the company is going to be... once you get to the 3rd month and how the first 3 months are going to be so happy and proudful, only to find people waiting for you to move this button from here to there? (replace here and there with a login wall and you will automatically get the point ;))</p>
<p><img src="https://media.giphy.com/media/l4FGoqz0vObvTMvfi/giphy.gif" alt="Magic Ball" /></p>
<p>What am talking about is not really Disney (whispers: I was indeed imagining them)</p>
<p>What am talking about is...</p>
<p>Draw.io!</p>
<p>or your sketchbook, or your iPad where u can draw</p>
<p>but since up there we mentioned that Software Design is an art, so we should get sketchin'!</p>
<p>Let's tackle down an Authentication Flow that does the following</p>
<p>It integrates with our BE through, Email and Password
Phone and Password
Continue as a guest
FaceID and QR Code Scanning
Facebook, Twitter, Pinterest, LinkedIn, Github, Apple, Google, Reddit, and every authentication provider there is to integrate with</p>
<p>Of course, if you had something required like this, you should leave the job since neither r u a bank to be this secure, nor are you a god damn hub of getting people together from all around the world, what you are right now is someone who is about to learn how the hell do we detect which design pattern to use for this task and how can you assign 3 engineers (including urself of course) to finish it, in a timely manner of under... 3 days would be a good estimate I think (guess what, first 2 days are in the foundation, 0.85 days in the implementation and 0.15 days in testing what u did ;) (btw this is not TDD, it would take shorter than this if it was TDD or BDD) (also BDD makes more sense in mobile)</p>
<p>If we go back to the reference of what we want to do basically, is one button may trigger something, another button may trigger a different flow, a 3rd one may trigger something completely different than the other 3</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636261615120/EGSjnkcgt.png" alt="CleanShot 2021-11-07 at 07.06.44@2x.png" /></p>
<p>but it all boils down to one big funnel, which is...</p>
<p>Logging the user in!</p>
<p>What if I told you is what we are talking about is a game of strategies? which strategy will we use, to get the guy into our app in the quickest way possible?</p>
<p>Strategy Pattern: Did someone say Strategy Pattern?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636258807107/YIohQgsYj.png" alt="CleanShot 2021-11-07 at 06.19.55@2x.png" /></p>
<blockquote>
<p>Shout out to my Sensei right here, <a class="user-mention" href="https://hashnode.com/@yoloabdo">Abdoelrhman</a> 🙌 for making it a possibility to learn that pattern 🙏</p>
</blockquote>
<p>Let's start with the why by answering how many SOLID principles are done through this pattern in this use case?</p>
<p>but first, let's do that on a sketch, shall we?</p>
<blockquote>
<p>Give those diagrams 2 looks, 1 quick look, another is deep and zoom into the annotations I wrote to clarify the bits and pieces</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636260705561/8KKfHEmOk.png" alt="CleanShot 2021-11-07 at 06.47.00@2x.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636260669300/WDDfseatN.png" alt="CleanShot 2021-11-07 at 06.37.46@2x.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636260682020/7ndfMbffY.png" alt="CleanShot 2021-11-07 at 06.40.16@2x.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636260689438/obJh_bLX3.png" alt="CleanShot 2021-11-07 at 06.45.04@2x.png" /></p>
<blockquote>
<p>Tip: If you see this, you may find that this is just a piece of the puzzle, and that's exactly what is needed here, you don't have to draw the whole picture in 1 go, just a step by step, slow and steady wins the race (YAGNI, remember?)</p>
</blockquote>
<p>Now, ask yourself, how can I do this and instead of worrying and letting your emotions get over you, build one now, you can get back to these if you want, but always remember, you are talking at a very high level now, no details are allowed, just pure simple rectangles and arrows that represent communications, ownership, responsibilities and a direction of where everything is going and how the data flows (regardless of whether u use delegates, callbacks, Observables, AnyPublisher or Subjects, or KVO, or just pure notifications (1 quick note here, do not reference the previous layer in a deeper layer, the deeper you go, the more independent you should be, and hence more reusable (or Modular)))</p>
<blockquote>
<p>Did that? GREAT JOB! get yourself a cookie 🍪 </p>
</blockquote>
<p>now what if I tell you right now, absolutely right now, that if you want to open-source this whole thing, and have your name is written behind the largest authentication pod/package/library/framework that combines all of these and give the end-user (us programmers) just one method to use and that is "<code>authenticate()</code>" (am assuming usage of Promises here :P)
then you can just take the whole authentication module, and put it on Github 😉, and whatever goes on Github goes on any future project for you to finish that 3 days task in... 3 mins? (an exaggeration, but unless you are a UI ninja known as the Yellow Flash, or UI is already built, then it may be doable)</p>
<blockquote>
<p>Because it's modular</p>
</blockquote>
<p>And being modular allows for being testable </p>
<p>So how will we test this? </p>
<p>Remember Liskov?</p>
<p>She said that a system may behave the same way if I replace one component with another</p>
<p>and since we want to test behavior, not syntax, which part of this diagram do you think we can replace with a fake/mock/stub (every part does something different but for sake of simplicity, just consider them all as one, and that none of them is going to call any backend of-what-so-ever)</p>
<p>So, in Unit Testing, let's fake that AuthProvider, and make it trigger certain behavior through fake flags and assertions thru spies</p>
]]></content:encoded></item><item><title><![CDATA[Architecture Homicide: Red Alert]]></title><description><![CDATA[I’d spend a couple of hours studying, planning, and understanding a problem, just to solve it in minutes.

Why asking for people that know MVVM is a red flag in job posts and what should be written instead from my humble POV?
Sure in a team of people...]]></description><link>https://blog.ahmedramy.me/architecture-homicide-red-alert</link><guid isPermaLink="true">https://blog.ahmedramy.me/architecture-homicide-red-alert</guid><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[software design]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Ahmed Ramy]]></dc:creator><pubDate>Wed, 23 Feb 2022 15:16:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645628786257/sN-Vte2p6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>I’d spend a couple of hours studying, planning, and understanding a problem, just to solve it in minutes.</p>
</blockquote>
<h1 id="heading-why-asking-for-people-that-know-mvvm-is-a-red-flag-in-job-posts-and-what-should-be-written-instead-from-my-humble-pov">Why asking for people that know MVVM is a red flag in job posts and what should be written instead from my humble POV?</h1>
<p>Sure in a team of people who work with a specific stack is logical to invite people who are good at it, but MVVM shouldn’t be your main concern, you want to invite people who are dependable in that stack or any other, so where the red flag might be u say?</p>
<p>It’s in how revered MVVM is around the whole project if the project is big and may contain different combined features like Social media and e-commerce (This is famous btw since u want to build a community around what u r selling)</p>
<p>Using MVVM with a reactive paradigm would be very great in Social media since you’ll need streams and real-time logic in place</p>
<p>However, the same might not be the case with e-commerce unless u r doing Auctions that includes real-time changes for example</p>
<p>But if u notice, we haven’t really talked about anything but presentation up till now, which is…. A design pattern to solve an issue ;)</p>
<p>So what issues do MVC, MVP, MVVM, or whatever u may find suitable?</p>
<p>Start with the class diagrams</p>
<p>Understand the flow</p>
<p>Understand the communication </p>
<p>Learn the slightest details and understand why we do this, that way</p>
<p>Why for instance, must not, under any circumstances, a ViewModel be directly linked with the previous layer? (May it the view, or an intermediary layer between them)</p>
<p>Why do we have dotted lines that represent a weak or an indirect reference to the previous layer?</p>
<p>Why the flow must be unidirectional?</p>
<p>Why implementing an offline-first is tricky and how your design might foresee future issues?</p>
<p>In the next section, we will learn those</p>
]]></content:encoded></item></channel></rss>