<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Atri</title>
    <description>The latest articles on DEV Community by Atri (@atriiy).</description>
    <link>https://dev.to/atriiy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F361127%2Fe588b2b9-9c48-4468-8a9f-9e09894183ee.jpg</url>
      <title>DEV Community: Atri</title>
      <link>https://dev.to/atriiy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/atriiy"/>
    <language>en</language>
    <item>
      <title>My understanding of MVI architecture</title>
      <dc:creator>Atri</dc:creator>
      <pubDate>Mon, 26 Jun 2023 13:38:17 +0000</pubDate>
      <link>https://dev.to/atriiy/my-understanding-of-mvi-architecture-1c7n</link>
      <guid>https://dev.to/atriiy/my-understanding-of-mvi-architecture-1c7n</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;Recently, I’ve been attempting to construct an RSS reader app on the iOS platform. Despite my limited experience in iOS development, I’ve utilized the MVVM pattern to structure my code due to its simplicity.&lt;/p&gt;

&lt;p&gt;However, as the development process unfolded, I discovered the challenge in managing and understanding data flow when dealing with multiple views. I also faced difficulty when certain actions necessitated the modification of multiple states, without a straightforward method to illustrate these changes. Although I sought to encapsulate the state updating logic, achieving this proved difficult.&lt;/p&gt;

&lt;p&gt;Fortunately, during a knowledge-sharing session at work, a mobile developer colleague introduced a potent architecture for iOS development: the MVI pattern.&lt;/p&gt;

&lt;p&gt;Subsequently, I’ve devoted time to studying this architecture via resources like ChatGPT 😉 and Google. I’ve successfully transitioned my code to this new architecture. Even though my daily responsibilities do not involve mobile development, the learning journey provided insightful concepts. As such, I’ve compiled these findings into this article to provide a succinct overview.&lt;/p&gt;

&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;While it’s essential for an article to concentrate on a single topic, I intend to explore multiple themes in this piece, given their significance in elucidating my understanding.&lt;/p&gt;

&lt;p&gt;Initially, I plan to delve into the mechanics of the modern UI framework. Regardless of whether the framework is employed on a browser or mobile platform, employing different technologies, these exist shared principles underpinning it.&lt;/p&gt;

&lt;p&gt;Drawing on the discourse around the UI framework, we will then address the fundamental challenge that front-end development aims to overcome.&lt;/p&gt;

&lt;p&gt;Following that, I’ll outline the mental model pertaining to the MVI architecture. We won’t devote extensive time to specific MVI concepts, as they are not the crux of our discussion. Instead, we’ll delve into the precise functionality of this architecture and how it aids in reducing system complexity.&lt;/p&gt;

&lt;h1&gt;
  
  
  UI framework
&lt;/h1&gt;

&lt;p&gt;There exists a multitude of UI frameworks worldwide. Given that different platforms utilize different languages, the frameworks for mobile platform differ from those for the web. However, if we disregard the technical specifics, what is the primary function of a UI framework?&lt;/p&gt;

&lt;p&gt;The answer lies in &lt;strong&gt;maintaining synchronization between the UI and the state&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Contrasted with the framework of decade ago, today’s UI developers handle an enormous amount of data. This data comes from varied sources and possesses different structures. Our task extends beyond merely retrieving a static array from the backend and wrap it within a series of &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;. Our focus lies in &lt;strong&gt;generating data from rendering&lt;/strong&gt;. Hence, the UI framework assumes the remaining responsibility: maintaining synchronization between the UI and the data (state).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1apfob9fwwtgg1twd2yy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1apfob9fwwtgg1twd2yy.png" alt="UI framework"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the way, the &lt;em&gt;state&lt;/em&gt; referred to here denotes data that induces side effects by updating the UI.&lt;/p&gt;

&lt;p&gt;If you find this topic engaging, here’s &lt;a href="https://medium.com/dailyjs/the-deepest-reason-why-modern-javascript-frameworks-exist-933b86ebc445" rel="noopener noreferrer"&gt;an amazing article&lt;/a&gt; offering a detailed information.&lt;/p&gt;

&lt;h1&gt;
  
  
  The difficult in UI development
&lt;/h1&gt;

&lt;p&gt;As previously mentioned, the UI framework updates the UI based on the state, making our task the production of data usable by the UI framework. Sounds straightforward, doesn’t it? However, it’s actually the most complex part of the process.&lt;/p&gt;

&lt;p&gt;The first challenge is the &lt;strong&gt;diversity&lt;/strong&gt; of data sources. We need to render data originating from the Backend, and user actions can also create new data impacting existing data.&lt;/p&gt;

&lt;p&gt;The second challenge lies in the dynamism of the data. Backend data may be changed by other systems, and users can also modify the data. In other words, the data transitions into a data stream, requiring us to update the state based on this stream. This introduces logical mutability to the state. Regardless of the framework or platform in use, a pressing question arises: how to comprehend the logic of state changes within a large system?&lt;/p&gt;

&lt;p&gt;The third challenge is that a single UI update might involve multiple states. For instance, when we dispatch a network request to the backend, we usually need to disable the submit button, display a loading animation, and upon receiving the response, render the UI based on the results. Sometimes, an error screen might also be required. As can be seen, the states are interdependent and operate collectively in various scenarios.&lt;/p&gt;

&lt;p&gt;From the above discussion, you may discern that the crux of UI development challenges is how to devise an architecture that facilitates our understanding and testing of &lt;strong&gt;state changes&lt;/strong&gt; with ease.&lt;/p&gt;

&lt;h1&gt;
  
  
  MVI architecture
&lt;/h1&gt;

&lt;p&gt;MVI, the most recent addition to the MV* family, structures an application into three components.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Model: Represents the states for the UI&lt;/li&gt;
&lt;li&gt;View: Represents the UI itself&lt;/li&gt;
&lt;li&gt;Intent: Represents actions triggering state updates&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following diagram provides a comprehensive overview of the MVI architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxyz41h6epneg3w8vj0yx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxyz41h6epneg3w8vj0yx.png" alt="MVI pattern"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The term “someone” at the bottom of the diagram refers to any entity that could potentially alter the UI, such as user input, network requests, or asynchronous work.&lt;/p&gt;

&lt;p&gt;Under the MVI architecture, these entities are disallowed from directly modifying the state. Instead, they generate an intent. This intent essentially comprises logic designed to update several states based on the intent’s function, which is crucial to understanding the MVI architecture.&lt;/p&gt;

&lt;p&gt;Consider the following code as a typical intent function. Note that in actually development, we wouldn’t write code exactly like this; it’s purely to illustrate the function of intent.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewOnAppear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;networkService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.example.com/api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
      &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The code demonstrates a scenario where we wish to perform certain actions when the view appears. Consequently, we have a function named &lt;code&gt;viewOnAppear&lt;/code&gt; to execute these tasks, which includes displaying a loading screen, fetching data from an API, and assigning data or showing an error screen depending on the network response.&lt;/p&gt;

&lt;p&gt;This function involves multiple UI updates. Reading through this function’s code makes the behavior abundantly clear. Using the same concept, we can encapsulate other actions into distinct intent functions like &lt;code&gt;submit&lt;/code&gt;, &lt;code&gt;onTapListItem&lt;/code&gt;, &lt;code&gt;onDeleteItem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In essence, the function of an &lt;strong&gt;intent&lt;/strong&gt; is to bundle &lt;strong&gt;state changes&lt;/strong&gt; into various actions, thereby simplifying the understanding and testing of these logical processes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code example
&lt;/h1&gt;

&lt;p&gt;From the preceding discussion, we’ve underscored that the crux of the MVI architecture lies in managing &lt;strong&gt;state changes&lt;/strong&gt;. Understanding this principle enables us to apply this architecture universally.&lt;/p&gt;

&lt;p&gt;In this section, we’ll demonstrate how to implement the MVI architecture in iOS development using Swift.&lt;/p&gt;

&lt;p&gt;To begin with, we’ll construct the &lt;em&gt;model&lt;/em&gt; for our sample app. The model’s role is to mange the data and state, providing various helper functions for easier using.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;ExmapleModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ObservableObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;@Published&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;contentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ContentState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loading&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// MARK: - Helper function&lt;/span&gt;
&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;ExampleModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;contentState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;displayLoading&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;contentState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loading&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;displayError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;contentState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;localizedDescription&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// MARK: - Helper enum&lt;/span&gt;
&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;ExampleModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;loading&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this example model, we have a singular state: &lt;code&gt;contentState&lt;/code&gt;. Leveraging the functionality of SwiftUI, any updates to &lt;code&gt;contentState&lt;/code&gt; will trigger a UI re-render. In the first extension, we’ve introduced several helper functions, all of which manage intricate state manipulation logic, ensuring consistent and predictable state changes. These functions are purely functional and do not induce any side effects.&lt;/p&gt;

&lt;p&gt;Having completed the model code, it’s now time to create an intent class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;ExampleIntent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ExampleModelProtocol&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;networkService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NetworkServiceProtocol&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;

    &lt;span class="c1"&gt;// This is a series of Publishers&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;routerSubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Subjects&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// MARK: - Intents&lt;/span&gt;
&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;ExampleIntent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewOnAppear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;displayLoading&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;networkService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://example.com/api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;weak&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
            &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;displayError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;onTapItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// This code will go to another page&lt;/span&gt;
        &lt;span class="n"&gt;routerSubject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tapFollow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above code, we’ve re-implemented the &lt;code&gt;viewOnAppear&lt;/code&gt; function. As can be observed, we’re updating several states and issuing a network request within this intent. Our state changing code is no longer dispersed but encapsulated within intent functions.&lt;/p&gt;

&lt;p&gt;At this point, we can proceed to implement the view.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;

&lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ExampleView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ExampleModelProtocol&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ExampleIntentProtocol&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;VStack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contentState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="kt"&gt;LoadingContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"loading..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;items&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="kt"&gt;ListContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="kt"&gt;ErrorContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onAppear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;viewOnappear&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// MARK: - Views&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;ExampleView&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;LoadingContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ErrorContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="kt"&gt;ListContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ExampleIntentProtocol&lt;/span&gt;

        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;some&lt;/span&gt; &lt;span class="kt"&gt;View&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// render the items&lt;/span&gt;
                &lt;span class="kt"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;onTapGesture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onTapItem&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="c1"&gt;// ...&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Using the MVI architecture to structure our code makes state changes and view updates predictable. The view will transition between &lt;code&gt;loading&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;list&lt;/code&gt; based on the &lt;code&gt;contentState&lt;/code&gt;. All actions potentially altering the state are enclosed within the intent functions, making them easier to comprehend.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;In this article, we’ve explored the MVI architecture.&lt;/p&gt;

&lt;p&gt;Before diving into any new architecture, it’s essential to identify the problems we’re facing and the crux of those issues.&lt;/p&gt;

&lt;p&gt;In UI development, the framework ensures synchronization between the state and view, which shifts our focus to managing state changes. In a large system, these state changes can become quite complex. Thus, we employ the MVI architecture to reduce system complexity. The linchpin of this architecture is the &lt;strong&gt;Intent&lt;/strong&gt;, a discrete level solely focused on altering states through clear, identifiable actions.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Reliable, Scalable, and Maintainable Applications</title>
      <dc:creator>Atri</dc:creator>
      <pubDate>Mon, 09 Jan 2023 12:38:04 +0000</pubDate>
      <link>https://dev.to/atriiy/reliable-scalable-and-maintainable-applications-1fim</link>
      <guid>https://dev.to/atriiy/reliable-scalable-and-maintainable-applications-1fim</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a reading note for &lt;a href="https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/" rel="noopener noreferrer"&gt;Designing Data-Intensive Applications&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;For a developer working in a commercial company, the most frequently encountered systems are &lt;strong&gt;data-intensive systems&lt;/strong&gt;. Different companies have different businesses, but behind the different business models is a set of general abilities. For example, application code, in-memory cache, primary database, message queue, e.g., The commercial company doesn't have enough resources to allow developers to implement all of them; therefore, we make architecture decisions according to the problem scales. A website with only 2,000 visits per day doesn't need to consider caching, but things become entirely different for a website with 2,000 visits per second.&lt;/p&gt;

&lt;p&gt;Before jumping into the details of data-intensive systems, we need to know how to evaluate a system. Or in other words, when we say a &lt;em&gt;good&lt;/em&gt; system, what exactly are we talking about? Generally, we will evaluate a system from three aspects: reliability, scalability, and maintainability. We will discuss some techniques, architectures, or algorithms to achieve these goals. But before it, we need to understand these terms clearly. Consistent and clear terms understanding is the first step in discussing system design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability
&lt;/h2&gt;

&lt;p&gt;We often refer to this term when discussing system architecture, but people often misunderstand it. It's worth noticing that &lt;em&gt;reliability&lt;/em&gt; is not describing the system returning the right value that the user expected or tolerating mistakes made by users; it means &lt;strong&gt;continuing to work correctly, even when things go wrong&lt;/strong&gt;. Therefore, when we talk about reliability, we are actually talking about &lt;strong&gt;fault-tolerant&lt;/strong&gt;. A good paper called &lt;em&gt;&lt;a href="https://resources.sei.cmu.edu/library/asset-view.cfm?assetid=11747" rel="noopener noreferrer"&gt;A Conceptual Framework for System Fault Tolerance&lt;/a&gt;&lt;/em&gt; expounds on this topic. Thus, we will focus on this paper in this section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Faults and failures
&lt;/h3&gt;

&lt;p&gt;A precise understanding of these two terms is the first step in understanding system reliability.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;fault&lt;/strong&gt; is usually defined as one component of the system deviating from its specification, whereas a &lt;strong&gt;failure&lt;/strong&gt; is when the system as a whole stops providing the required service to the user. A system may continue to provide its service even when encountering a fault. Such a system is called &lt;strong&gt;fault tolerant&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's impossible to reduce the probability of a fault to zero. Therefore it is usually best to design fault-tolerance mechanisms that prevent faults from causing failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies and failure regions
&lt;/h3&gt;

&lt;p&gt;If a component's behavior's correctness requires the second component's correct behavior, we say the first component depends on the second component. An actual system may have a set of possible dependencies forming a graph. The graph is &lt;em&gt;acyclic&lt;/em&gt; if it forms part of a tree, while it is &lt;em&gt;cyclic&lt;/em&gt; if part of the dependencies connects to themselves. It is better to describe the second situation as a directed cyclic graph.&lt;/p&gt;

&lt;p&gt;When we design a fault-tolerant system, it is essential to identify the dependencies between components of the system. Dependencies may be static, or they may change. &lt;/p&gt;

&lt;p&gt;A fault that occurs on a component may transmit in the dependencies graph. Thus it is essential to understand the failure regions. We define the failure region as a limitation of considering faults and failures to a portion of a system and its environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fault tolerance mechanisms
&lt;/h3&gt;

&lt;p&gt;Based on the discussion above, we introduce three fault tolerance mechanisms.&lt;/p&gt;

&lt;p&gt;The first is &lt;strong&gt;redundancy management&lt;/strong&gt;. It provides redundant resources for the system and automatically replaces a component when it fails so that it can continue providing service for the users. The second is &lt;strong&gt;acceptance test techniques&lt;/strong&gt;. The components of the system execute the testing for the information from other components before using it. This mechanism can work in the non-redundant system. The third is &lt;strong&gt;comparison techniques&lt;/strong&gt;. Multiple processors are used to execute the same program and compare the results across processors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Achieve reliability
&lt;/h3&gt;

&lt;p&gt;Based on the discussion of reliability and fault-tolerant system, it's easy to understand the first step in implementing a reliable system is to understand your system precisely. You need to know the system's requirements so that you will have enough information to identify the portions that may go wrong. Determine the appropriate fault containment regions to deal with fault and make the time/space trade-offs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scalability
&lt;/h2&gt;

&lt;p&gt;Reliability describes if a system can work reliably at that moment, but it does not mean a reliable system can still provide reliable service in the future. The number of users may increase, which puts the system under more pressure. Therefore, we use &lt;strong&gt;scalability&lt;/strong&gt; to describe a system's ability to cope with increased load.&lt;/p&gt;

&lt;p&gt;We will discuss the load and performance first. A good understanding of these two concepts can give us enough information to make trade-offs when developing the system's solution. After that, we will briefly talk about some approaches. It's hard to talk about all details of these approaches in an article; thus, we only talk about some conceptual stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  Describing load
&lt;/h3&gt;

&lt;p&gt;Succinctly describing the load is the first step in improving the performance of our system. We always use a few numbers called &lt;strong&gt;load parameters&lt;/strong&gt; for this requirement.&lt;/p&gt;

&lt;p&gt;The choice of load parameters depends on the architecture of your system. If the core function requires intensive reading and writing to the database, the ratio of that behavior is a good candidate. There is no universal parameter measure of system load; you need to understand your system or the function you're interested in before choosing them. The book takes Twitter as an example; you can read it for inspiration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Describing performance
&lt;/h3&gt;

&lt;p&gt;Generally, we want the best performance with the least amount of resources. Therefore, we have two ways to investigate the performance of our system when loading increases.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep the resource unchanged when you increase the load parameter and observe how the performance is affected.&lt;/li&gt;
&lt;li&gt;Increase the resource to keep the performance unchanged. Observe how many resources you need to increase.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Like the load, we need to use a few numbers to describe the performance of our system. We always use response time for the online system to describe the performance. It describes the time between a client sending a request and receiving a response.&lt;/p&gt;

&lt;p&gt;It is vital to recognize that response time is not a single number but a &lt;em&gt;distribution&lt;/em&gt; of values. Therefore, looking at the average becomes meaningless from a statistical point of view. A system with an unstable response time may have the same average value as a stable system. But the resulting user experience is completely different.&lt;/p&gt;

&lt;p&gt;We always use &lt;strong&gt;percentiles&lt;/strong&gt; to bypass the fundamental issue with averages. The idea is to take the data during a period of time and sort it, then discard the worst 1% and observe the remaining value. For example, we can find the largest value that occurs at 99% of the response time. In practice, we often choose the 99.9%, 99%, 95%, and 90%.&lt;/p&gt;

&lt;p&gt;Why can't we use the 99%? Let's suppose that the largest value that occurs at 99% of the response is 400ms. It means 99% response time during this time is better than 400ms, but we don't know the distribution of these &lt;em&gt;better values&lt;/em&gt;. Maybe we have 100 response time records; 80 of them are 398ms. Therefore we need to review the percentiles of the response time to recognize the distribution.&lt;/p&gt;

&lt;p&gt;At the same time, it is necessary to know what we talked about above is only researching a single request. In modern websites, a web page may need to send hundreds of requests. Therefore, although you may have put a lot of effort into improving the performance data, the users still experience the worst situation with a high probability.&lt;/p&gt;

&lt;p&gt;If you want more information about this topic, I suggest you read &lt;a href="https://orangematter.solarwinds.com/2016/11/18/why-percentiles-dont-work-the-way-you-think/" rel="noopener noreferrer"&gt;Why Percentiles Don’t Work the Way You Think&lt;/a&gt; and &lt;a href="https://bravenewgeek.com/everything-you-know-about-latency-is-wrong/" rel="noopener noreferrer"&gt;Everything You Know About Latency Is Wrong&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Approaches for coping with load
&lt;/h3&gt;

&lt;p&gt;Based on the discussion of load and performance, we can say when we talk about the scalability of a system, we are talking about how to maintain good performance under increasing load parameters.&lt;/p&gt;

&lt;p&gt;We already have some common methods for addressing this requirement in modern software development. Like auto-scaling, load balancing, caching (including CDN), and distributed systems. We will talk about them in the future because each topic needs much discussion and has tons of details.&lt;/p&gt;

&lt;p&gt;Another thing is the trade-off during the architectural design. Although we have many ways to improve the performance, we can't implement all of them because of the limited resources. Therefore. a smart way is to use the simplest way and refactor it until the current strategy or high-performance requirements force you to change it. But with the improvement of cloud service infrastructure, some approaches like distributed databases may be the default in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintainability
&lt;/h2&gt;

&lt;p&gt;The majority cost of software development is in its ongoing maintenance instead of the initial development. Although we can not eliminate the pain of maintaining an old project, we should use some ways to reduce it. To achieve this, we should pay attention to three design principles: operability, simplicity, and evolvability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operability
&lt;/h3&gt;

&lt;p&gt;Developing software is not only include writing code; it also includes running it smoothly. &lt;/p&gt;

&lt;p&gt;For example, we need to monitor the system's health by collecting logs and data; we need to use CI/CD to release the new version smoothly; we need to keep the software up to date; we need to share knowledge about the software with team members who doesn't participate in; we need to establish the good practices for development. Most of these requirements can be addressed by using some automatic tools.&lt;/p&gt;

&lt;p&gt;Good operability makes the team's life easier. The team can focus on more valuable things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplicity
&lt;/h3&gt;

&lt;p&gt;Managing the complexity of the software is the core topic of development. As time goes by, more and more functions are added to the system, and the system may also accumulate a lot of technical debt. These factors make the system becoming complex and difficult to understand.&lt;/p&gt;

&lt;p&gt;Two effective methods are abstraction and delamination. It can hide the complexity behind a clean facade. This book will introduce some approaches to dividing the huge system into well-defined, reusable components. If you want to know how to do the same thing for the code, a book worth reading is &lt;a href="https://mitp-content-server.mit.edu/books/content/sectbyfn/books_pres_0/6515/sicp.zip/index.html" rel="noopener noreferrer"&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evolvability
&lt;/h3&gt;

&lt;p&gt;As we mentioned before, the system is not static stuff. We don't only refactor the code and architecture to support more users but also add new features and change the existing functions. Therefore, evolvability is an important measuring aspect of the system.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;agile&lt;/strong&gt; working patterns provide a good framework to deal with this problem. Some technical tools and patterns from the agile community are useful for the system. Test-driving development and refactoring are probably the most well-known methodologies. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This article talked about some fundamental principles of measuring data-intensive applications. A good understanding of these principles is the first step to jumping into deep technical details. Although we will introduce more technologies to make the applications reliable, scalable, and maintainable, we will never have a one-size-fits-all solution. Succinctly understanding your system is always the first step to addressing the problems and making the application better.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>softwaredevelopment</category>
      <category>api</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
