<?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[Nanosoft Code Foundation]]></title><description><![CDATA[Programming mentorship, node, ios, android, web, react, swift, swiftui, kotlin, jetpack compose]]></description><link>https://codefoundation.co.za</link><generator>RSS for Node</generator><lastBuildDate>Sat, 16 May 2026 10:50:34 GMT</lastBuildDate><atom:link href="https://codefoundation.co.za/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Login / Logout Flow: SwiftUI and EnvironmentObject]]></title><description><![CDATA[EnvironmentObject is useful when you want to create a dependency in a higher component of the layout tree and use it on a lower component without having to pass it down the tree through every child component.
We will now use EnvironmentObject to moni...]]></description><link>https://codefoundation.co.za/login-logout-flow-swiftui-and-environmentobject</link><guid isPermaLink="true">https://codefoundation.co.za/login-logout-flow-swiftui-and-environmentobject</guid><category><![CDATA[iOS]]></category><category><![CDATA[ios app development]]></category><category><![CDATA[Swift]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Mon, 08 Nov 2021 08:33:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636359923041/99Q-Dcv3w.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>EnvironmentObject is useful when you want to create a dependency in a higher component of the layout tree and use it on a lower component without having to pass it down the tree through every child component.</p>
<p>We will now use EnvironmentObject to monitor when a user logs in and out.</p>
<ol>
<li>When the user is successfully logged in (isLoggedIn = true), they are directed to the rest of the application views.</li>
<li>When a user is logged out (isLoggedIn = false) at any point within the app, they are directed to the login page.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636360017555/VIb0LbEjr.png" alt="Login Logout Flow: SwiftUI" /></p>
<p>We need the following components:</p>
<ol>
<li>User State View Model</li>
<li>Application Switcher</li>
<li>Login Screen</li>
<li>Home Screen (Our Application Views)</li>
</ol>
<h3 id="user-state-view-model">User State View Model</h3>
<p>The user state view model tracks and broadcasts the user status. We store this view model in an EnvironmentObject.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">UserStateError</span>: <span class="hljs-title">Error</span></span>{
    <span class="hljs-keyword">case</span> signInError, signOutError
}

@<span class="hljs-type">MainActor</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserStateViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> isLoggedIn = <span class="hljs-literal">false</span>
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> isBusy = <span class="hljs-literal">false</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">signIn</span><span class="hljs-params">(email: String, password: String)</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">UserStateError</span>&gt;  {
        isBusy = <span class="hljs-literal">true</span>
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">try</span> await <span class="hljs-type">Task</span>.sleep(nanoseconds:  <span class="hljs-number">1_000_000_000</span>)
            isLoggedIn = <span class="hljs-literal">true</span>
            isBusy = <span class="hljs-literal">false</span>
            <span class="hljs-keyword">return</span> .success(<span class="hljs-literal">true</span>)
        }<span class="hljs-keyword">catch</span>{
            isBusy = <span class="hljs-literal">false</span>
            <span class="hljs-keyword">return</span> .failure(.signInError)
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">signOut</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">UserStateError</span>&gt;  {
        isBusy = <span class="hljs-literal">true</span>
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">try</span> await <span class="hljs-type">Task</span>.sleep(nanoseconds: <span class="hljs-number">1_000_000_000</span>)
            isLoggedIn = <span class="hljs-literal">false</span>
            isBusy = <span class="hljs-literal">false</span>
            <span class="hljs-keyword">return</span> .success(<span class="hljs-literal">true</span>)
        }<span class="hljs-keyword">catch</span>{
            isBusy = <span class="hljs-literal">false</span>
            <span class="hljs-keyword">return</span> .failure(.signOutError)
        }
    }
}
</code></pre>
<p>We make our view model instance available to all child views, starting from the ApplicationSwitcher view</p>
<h3 id="application-switcher">Application Switcher</h3>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI

@main
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">LoginFlowApp</span>: <span class="hljs-title">App</span> </span>{

    @<span class="hljs-type">StateObject</span> <span class="hljs-keyword">var</span> userStateViewModel = <span class="hljs-type">UserStateViewModel</span>()

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">Scene</span> {
        <span class="hljs-type">WindowGroup</span> {
            <span class="hljs-type">NavigationView</span>{
                <span class="hljs-type">ApplicationSwitcher</span>()
            }
            .navigationViewStyle(.stack)
            .environmentObject(userStateViewModel)
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ApplicationSwitcher</span>: <span class="hljs-title">View</span> </span>{

    @<span class="hljs-type">EnvironmentObject</span> <span class="hljs-keyword">var</span> vm: <span class="hljs-type">UserStateViewModel</span>

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-keyword">if</span> (vm.isLoggedIn) {
                <span class="hljs-type">HomeScreen</span>()
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-type">LoginScreen</span>()
        }

    }
}
</code></pre>
<h3 id="login-screen">Login Screen</h3>
<p>The Login screen uses the UserStateViewModel to invoke signIn</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">LoginScreen</span>: <span class="hljs-title">View</span> </span>{

    @<span class="hljs-type">EnvironmentObject</span> <span class="hljs-keyword">var</span> vm: <span class="hljs-type">UserStateViewModel</span>
    @<span class="hljs-type">State</span> <span class="hljs-keyword">var</span> email = <span class="hljs-string">""</span>
    @<span class="hljs-type">State</span> <span class="hljs-keyword">var</span> password = <span class="hljs-string">""</span>

    <span class="hljs-keyword">fileprivate</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">EmailInput</span><span class="hljs-params">()</span></span> -&gt; some <span class="hljs-type">View</span> {
        <span class="hljs-type">TextField</span>(<span class="hljs-string">"Email"</span>, text: $email)
            .keyboardType(.emailAddress)
            .disableAutocorrection(<span class="hljs-literal">true</span>)
            .autocapitalization(.<span class="hljs-keyword">none</span>)
            .textFieldStyle(.roundedBorder)
    }

    <span class="hljs-keyword">fileprivate</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">PasswordInput</span><span class="hljs-params">()</span></span> -&gt; some <span class="hljs-type">View</span> {
        <span class="hljs-type">SecureField</span>(<span class="hljs-string">"Password"</span>, text: $password)
            .textFieldStyle(.roundedBorder)
    }

    <span class="hljs-keyword">fileprivate</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">LoginButton</span><span class="hljs-params">()</span></span> -&gt; some <span class="hljs-type">View</span> {
        <span class="hljs-type">Button</span>(action: {
            <span class="hljs-type">Task</span> {
                await vm.signIn(
                    email: email,
                    password:password
                )
            }
        }) {
            <span class="hljs-type">Text</span>(<span class="hljs-string">"Sign In"</span>)
        }
    }

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {

        <span class="hljs-type">VStack</span>{
            <span class="hljs-keyword">if</span>(vm.isBusy){
                <span class="hljs-type">ProgressView</span>()
            }<span class="hljs-keyword">else</span>{
                <span class="hljs-type">Text</span>(<span class="hljs-string">"Login Screen"</span>).font(.title)
                <span class="hljs-type">EmailInput</span>()
                <span class="hljs-type">PasswordInput</span>()
                <span class="hljs-type">LoginButton</span>()
            }
        }.padding()

    }
}
</code></pre>
<h3 id="home-screen-with-logout-button">Home Screen with Logout Button</h3>
<p>The Home screen uses the UserStateViewModel to invoke signOut</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">HomeScreen</span>: <span class="hljs-title">View</span> </span>{

    @<span class="hljs-type">EnvironmentObject</span> <span class="hljs-keyword">var</span> vm: <span class="hljs-type">UserStateViewModel</span>

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {

        <span class="hljs-keyword">if</span>(vm.isBusy){
            <span class="hljs-type">ProgressView</span>()
        }<span class="hljs-keyword">else</span>{
            <span class="hljs-type">Text</span>(<span class="hljs-string">"Home Screen"</span>)
                .navigationTitle(<span class="hljs-string">"Home"</span>)
                .toolbar {

                        <span class="hljs-type">Button</span> {
                            <span class="hljs-type">Task</span>{
                                await vm.signOut()
                            }
                        } label: {
                            <span class="hljs-type">Image</span>(systemName:  <span class="hljs-string">"rectangle.portrait.and.arrow.right"</span>)
                        }


                }
        }
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636360203295/xU0_gTE5X.gif" alt="1_FjHwFObdKFT5PNCqd_zW3A.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Login / Logout Flow: Android Jetpack Compose and CompositionLocal]]></title><description><![CDATA[CompositionLocal is useful when you want to create a dependency in a higher node of the layout tree and use it on a lower node without having to pass it down the tree through every child Composable.
Here we will use it to direct our application when ...]]></description><link>https://codefoundation.co.za/login-logout-flow-android-jetpack-compose-and-compositionlocal</link><guid isPermaLink="true">https://codefoundation.co.za/login-logout-flow-android-jetpack-compose-and-compositionlocal</guid><category><![CDATA[Android]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[login]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Fri, 05 Nov 2021 12:12:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636113874284/voOq9X7qI.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>CompositionLocal is useful when you want to create a dependency in a higher node of the layout tree and use it on a lower node without having to pass it down the tree through every child Composable.</p>
<p>Here we will use it to direct our application when a user logs in and out.</p>
<ol>
<li>When the user is successfully logged in (isLoggedIn = true), they are directed to the rest of the application views.</li>
<li>When a user is logged out (isLoggedIn = false) at any point within the app, they are directed to the login page.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636113922972/k0Pvl2Z95.png" alt="1_6VAswSMtIhBP6zBwzvPShg.png" /></p>
<p>We need the following components:</p>
<ol>
<li>User State View Model</li>
<li>Application Switcher</li>
<li>Login Screen</li>
<li>Home Screen</li>
</ol>
<h3 id="user-state-view-model">User State View Model</h3>
<p>The UserStateViewModel keeps track of and broadcasts our user status. We are going to store this view model to a CompositionLocal.</p>
<pre><code class="lang-kt"><span class="hljs-keyword">import</span> androidx.compose.runtime.compositionLocalOf
<span class="hljs-keyword">import</span> androidx.compose.runtime.getValue
<span class="hljs-keyword">import</span> androidx.compose.runtime.mutableStateOf
<span class="hljs-keyword">import</span> androidx.compose.runtime.setValue
<span class="hljs-keyword">import</span> androidx.lifecycle.ViewModel
<span class="hljs-keyword">import</span> kotlinx.coroutines.delay


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserStateViewModel</span> : <span class="hljs-type">ViewModel</span></span>() {
    <span class="hljs-keyword">var</span> isLoggedIn <span class="hljs-keyword">by</span> mutableStateOf(<span class="hljs-literal">false</span>)
    <span class="hljs-keyword">var</span> isBusy <span class="hljs-keyword">by</span> mutableStateOf(<span class="hljs-literal">false</span>)

    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">signIn</span><span class="hljs-params">(email: <span class="hljs-type">String</span>, password: <span class="hljs-type">String</span>)</span></span> {
        isBusy = <span class="hljs-literal">true</span>
        delay(<span class="hljs-number">2000</span>)
        isLoggedIn = <span class="hljs-literal">true</span>
        isBusy = <span class="hljs-literal">false</span>
    }

    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">signOut</span><span class="hljs-params">()</span></span> {
        isBusy = <span class="hljs-literal">true</span>
        delay(<span class="hljs-number">2000</span>)
        isLoggedIn = <span class="hljs-literal">false</span>
        isBusy = <span class="hljs-literal">false</span>
    }
}

<span class="hljs-keyword">val</span> UserState = compositionLocalOf&lt;UserStateViewModel&gt; { error(<span class="hljs-string">"User State Context Not Found!"</span>) }
</code></pre>
<p>We make our view model instance available to all child composables, starting from the ApplicationSwitcher composable</p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> userState <span class="hljs-keyword">by</span> viewModels&lt;UserStateViewModel&gt;()
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent {
            CompositionLocalProvider(UserState provides userState) {
                ApplicationSwitcher()
            }
        }
    }
}
</code></pre>
<h3 id="application-switcher">Application Switcher</h3>
<pre><code class="lang-kt"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">ApplicationSwitcher</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> vm = UserState.current
    <span class="hljs-keyword">if</span> (vm.isLoggedIn) {
        HomeScreen()
    } <span class="hljs-keyword">else</span> {
        LoginScreen()
    }
}
</code></pre>
<h3 id="login-screen">Login Screen</h3>
<p>The Login screen can now use the <strong>UserStateViewModel</strong> to invoke <em>signIn</em></p>
<pre><code class="lang-kt"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">LoginScreen</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> email <span class="hljs-keyword">by</span> remember { mutableStateOf(<span class="hljs-string">""</span>) }
    <span class="hljs-keyword">var</span> password <span class="hljs-keyword">by</span> remember { mutableStateOf(<span class="hljs-string">""</span>) }
    <span class="hljs-keyword">val</span> coroutineScope = rememberCoroutineScope()
    <span class="hljs-keyword">val</span> vm = UserState.current
    Column(
        Modifier
            .fillMaxSize()
            .padding(<span class="hljs-number">32</span>.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        <span class="hljs-keyword">if</span> (vm.isBusy) {
            CircularProgressIndicator()
        } <span class="hljs-keyword">else</span> {
            Text(<span class="hljs-string">"Login Screen"</span>, fontSize = <span class="hljs-number">32</span>.sp)
            Spacer(modifier = Modifier.height(<span class="hljs-number">16</span>.dp))
            Email(email, onChange = {
                email = it
            })
            Spacer(modifier = Modifier.height(<span class="hljs-number">16</span>.dp))
            Password(password, onChange = {
                password = it
            })
            Spacer(modifier = Modifier.height(<span class="hljs-number">16</span>.dp))
            LoginButton(onClick = {
                coroutineScope.launch {
                    vm.signIn(email, password)
                }
            })
        }


    }
}
</code></pre>
<h3 id="home-screen-with-logout-button">Home Screen with Logout Button</h3>
<p>The Home screen also uses the <strong>UserStateViewModel</strong> to invoke the <em>signOut</em></p>
<pre><code class="lang-kt"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">HomeScreen</span><span class="hljs-params">(navController: <span class="hljs-type">NavHostController</span>)</span></span> {
    <span class="hljs-keyword">val</span> vm = UserState.current
    <span class="hljs-keyword">val</span> coroutineScope = rememberCoroutineScope()
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(<span class="hljs-string">"Home"</span>) },
                actions = {
                    IconButton(onClick = {
                        coroutineScope.launch {
                            vm.signOut()
                        }
                    }) {
                        Icon(Icons.Filled.ExitToApp, <span class="hljs-literal">null</span>)
                    }
                }
            )
        },
        ) {
        Column(
            Modifier
                .fillMaxSize()
                .padding(<span class="hljs-number">16</span>.dp),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            <span class="hljs-keyword">if</span> (vm.isBusy) {
                CircularProgressIndicator()
            } <span class="hljs-keyword">else</span> {
                Text(<span class="hljs-string">"Home"</span>)
            }
        }
    }
}
</code></pre>
<p>At all times the Application Switcher is monitoring the isLoggedIn status:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636114119440/L0eM-7xsj.gif" alt="1_8eRY-tsLv8eDl2JkzSmybw.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Getting Started with TDD: SwiftUI]]></title><description><![CDATA[The  TDD (Test Driven Development)  approach is important when it comes to testing small portions of business logic code in isolation.
In this blog, I'll cover how I would use TDD to build a clean architecture To-do SwiftUI application
I'll cover imp...]]></description><link>https://codefoundation.co.za/getting-started-with-tdd-swiftui</link><guid isPermaLink="true">https://codefoundation.co.za/getting-started-with-tdd-swiftui</guid><category><![CDATA[iOS]]></category><category><![CDATA[ios app development]]></category><category><![CDATA[Swift]]></category><category><![CDATA[TDD (Test-driven development)]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Wed, 27 Oct 2021 13:53:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635331994383/FWMBworTf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The  <a target="_blank" href="https://en.wikipedia.org/wiki/Test-driven_development">TDD (Test Driven Development)</a>  approach is important when it comes to testing small portions of business logic code in isolation.</p>
<p>In this blog, I'll cover how I would use TDD to build a clean architecture To-do SwiftUI application</p>
<p>I'll cover implementing the "Get To-dos" use case.</p>
<p><a target="_blank" href="https://mermaid.live/edit/#eyJjb2RlIjoiZ3JhcGggVERcbiAgICAxW1RvZG9WaWV3XSAtLT58T2JzZXJ2ZXMgLyBVc2VzfCAyW1RvZG9WaWV3TW9kZWxdXG4gICAgMiAtLT4gfEludm9rZXN8IDNbR2V0VG9kb3NVc2VDYXNlOiBHZXRUb2Rvc11cbiAgICAzIC0tPiB8VXNlc3wgNltUb2RvUmVwb3NpdG9yeUltcGw6IFRvZG9SZXBvc2l0b3J5XVxuICAgIDYgLS0-IHxVc2VzfCA3W1RvZG9EYXRhU291cmNlSW1wbDogVG9kb0RhdGFTb3VyY2VdXG4gICBcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9"><img src="https://mermaid.ink/img/eyJjb2RlIjoiZ3JhcGggVERcbiAgICAxW1RvZG9WaWV3XSAtLT58T2JzZXJ2ZXMgLyBVc2VzfCAyW1RvZG9WaWV3TW9kZWxdXG4gICAgMiAtLT4gfEludm9rZXN8IDNbR2V0VG9kb3NVc2VDYXNlOiBHZXRUb2Rvc11cbiAgICAzIC0tPiB8VXNlc3wgNltUb2RvUmVwb3NpdG9yeUltcGw6IFRvZG9SZXBvc2l0b3J5XVxuICAgIDYgLS0-IHxVc2VzfCA3W1RvZG9EYXRhU291cmNlSW1wbDogVG9kb0RhdGFTb3VyY2VdXG4gICBcbiAgICAiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9LCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" alt /></a></p>
<p>For this type of application, we need 2 types for application testing; UI Testing and Unit Testing. We'll be concentrating on the business logic, so we'll only be covering TDD unit testing. Before we write any production code, we'll write the test first.</p>
<p>The application will be structured in the following file and folder structure:</p>
<pre><code>.
├── <span class="hljs-selector-tag">MyApp</span>
    ├── <span class="hljs-selector-tag">Data</span>
    │   ├── <span class="hljs-selector-tag">DataSource</span>
    │   │   ├── <span class="hljs-selector-tag">TodoDataSource</span><span class="hljs-selector-class">.swift</span>
    │   │   └── <span class="hljs-selector-tag">DB</span>
    │   │       ├── <span class="hljs-selector-tag">Entity</span>
    │   │       │    └── <span class="hljs-selector-tag">TodoDBEntity</span><span class="hljs-selector-class">.swift</span>
    │   │       └── <span class="hljs-selector-tag">TodoDBDataSourceImpl</span><span class="hljs-selector-class">.swift</span>
    │   └── <span class="hljs-selector-tag">Repository</span>
    │       └── <span class="hljs-selector-tag">TodoRepositoryImpl</span><span class="hljs-selector-class">.swift</span>
    ├── <span class="hljs-selector-tag">Domain</span>
    │    ├── <span class="hljs-selector-tag">Model</span>
    │    │   └── <span class="hljs-selector-tag">Todo</span><span class="hljs-selector-class">.swift</span>
    │    ├── <span class="hljs-selector-tag">Repository</span>
    │    │   └── <span class="hljs-selector-tag">TodoRepository</span><span class="hljs-selector-class">.swift</span>
    │    └── <span class="hljs-selector-tag">UseCase</span>
    │        └── <span class="hljs-selector-tag">GetTodos</span><span class="hljs-selector-class">.swift</span>
    └── <span class="hljs-selector-tag">Presentation</span>
        ├── <span class="hljs-selector-tag">TodoViewModel</span><span class="hljs-selector-class">.swift</span>
        └── <span class="hljs-selector-tag">TodoListView</span><span class="hljs-selector-class">.swift</span>
└── <span class="hljs-selector-tag">MyAppTests</span>
    ├── <span class="hljs-selector-tag">Data</span>
    │   ├── <span class="hljs-selector-tag">DataSource</span>
    │   │   └── <span class="hljs-selector-tag">DB</span>
    │   │       └── <span class="hljs-selector-tag">TodoDBDataSourceImplTest</span><span class="hljs-selector-class">.swift</span>
    │   └── <span class="hljs-selector-tag">Repository</span>
    │       └── <span class="hljs-selector-tag">TodoRepositoryImplTest</span><span class="hljs-selector-class">.swift</span>
    ├── <span class="hljs-selector-tag">Domain</span>
    │    └── <span class="hljs-selector-tag">UseCase</span>
    │        └── <span class="hljs-selector-tag">GetTodosTest</span><span class="hljs-selector-class">.swift</span>
    └── <span class="hljs-selector-tag">Presentation</span>
        └── <span class="hljs-selector-tag">TodoViewModelTest</span><span class="hljs-selector-class">.swift</span>
</code></pre><p>We'd like to develop the "TodoViewModel" through the practice of TDD</p>
<h4 id="a-note-on-tdd">A note on TDD</h4>
<p>TDD is a software development process in which the unit test will be written first and after that the original code. In TDD, the design and development of the code are through unit tests.</p>
<p>In the traditional unit tests, the unit test is written after the original code is written. This is only for long-term maintainability. But in TDD the unit test is written first and code evolved through it.</p>
<h4 id="red-green-refactor">Red Green Refactor</h4>
<p>Red Green Refactor is an interesting concept in TDD. The stages are given below:</p>
<p><strong>Red</strong> - First a failing unit test is created, and it results in red status</p>
<p><strong>Green</strong> - We will modify the associated code to just make the unit test pass - resulting in green status</p>
<p><strong>Refactor</strong> - Once the test is passing we can refactor the code so that the original implementation is done.</p>
<p>To get started with testing in your iOS SwiftUI project, we need to add a test target:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635332909190/6ST1cZ0nT.png" alt="Screenshot 2021-10-27 at 13.08.10.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635332809283/r74Tf26DD.png" alt="Screenshot 2021-10-27 at 13.04.56.png" /></p>
<p>This now creates a test template:
To run the entire test suite click on the run button next to the class name or to run individual tests click the diamond button next to each test. Also note that each test needs to begin with the word "test"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635333144374/Nopqur21a.png" alt="Screenshot 2021-10-27 at 13.12.19.png" /></p>
<p>Let's create the test and application file and folder structure. We'll just create the file without any production code.  All development code will be driven by test code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635334559509/J67taId-3.png" alt="Screenshot 2021-10-27 at 13.35.43.png" /></p>
<p>Let's start with our first test:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635335043055/7WZuRByXz.png" alt="Screenshot 2021-10-27 at 13.43.39.png" /></p>
<p><em>MyAppTests/Presentation/TodoViewModelTest.swift</em></p>
<p>Of course, this test doesn't build and therefore fails because the file doesn't exist. 
We're in the RED Stage.</p>
<p>Let's write the minimum code to make the test pass. </p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

}
</code></pre>
<p>If we run the test again, it passes - GREEN Stage</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635335517862/S-LoqOLCA.png" alt="Screenshot 2021-10-27 at 13.51.52.png" /></p>
<p>We also notice that the View Model takes a dependency so we'll have to change the test to include the getTodosUseCase</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635337383119/LliTXBGHn.png" alt="Screenshot 2021-10-27 at 14.22.48.png" /></p>
<p>We're back in RED stage</p>
<p>Let's update the view model</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> getTodosUseCase : <span class="hljs-type">GetTodos</span>

    <span class="hljs-keyword">init</span>(getTodosUseCase: <span class="hljs-type">GetTodos</span>){
        <span class="hljs-keyword">self</span>.getTodosUseCase = getTodosUseCase
    }

}
</code></pre>
<p>We need to create the protocol and mock implementation for GetTodosUseCase. While we are at it let's create the Todo Model</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">UseCaseError</span>: <span class="hljs-title">Error</span></span>{
    <span class="hljs-keyword">case</span> dataSourceError, decodingError
}

<span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">GetTodos</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">Todo</span>], <span class="hljs-type">UseCaseError</span>&gt;
}
</code></pre>
<center><sub><em>MyApp/Domain/UseCase/GetTodos.swift</em></sub></center>


<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Todo</span>: <span class="hljs-title">Identifiable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> title: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> isCompleted: <span class="hljs-type">Bool</span>
}
</code></pre>
<center><sub><em>MyApp/Domain/Model/Todo.swift</em></sub></center>

<p>Because we're testing and developing the view model, we don't need a GetTodos use case implementation at this stage, we will need to create a mock use case that implements the protocol</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation
<span class="hljs-meta">@testable</span> <span class="hljs-keyword">import</span> MyApp

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockGetTodosUseCase</span>: <span class="hljs-title">GetTodos</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">Todo</span>], <span class="hljs-type">UseCaseError</span>&gt; {
        <span class="hljs-type">Result</span>.success([
            <span class="hljs-type">Todo</span>(id: <span class="hljs-number">1</span>, title: <span class="hljs-string">"Mock Title One"</span>, isCompleted: <span class="hljs-literal">true</span>),
            <span class="hljs-type">Todo</span>(id: <span class="hljs-number">2</span>, title: <span class="hljs-string">"Mock Title Two"</span>, isCompleted: <span class="hljs-literal">false</span>)
        ])
    }
}
</code></pre>
<center><sub><em>MyAppTests/Domain/UseCase/MockGetTodosUseCase.swift</em></sub></center>

<p>The test passes - GREEN stage</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635338905220/A_s3dTWVR.png" alt="Screenshot 2021-10-27 at 14.48.19.png" /></p>
<p>Let's add a few more tests to drive the development of the view model</p>
<hr />
<h4 id="testtodoviewmodelshouldreturnanemptytodoslist">testTodoViewModel_Should_Return_An_Empty_Todos_List</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635339245571/FCGeZCJ8K.png" alt="Screenshot 2021-10-27 at 14.53.59.png" /></p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> getTodosUseCase : <span class="hljs-type">GetTodos</span>

    <span class="hljs-keyword">init</span>(getTodosUseCase: <span class="hljs-type">GetTodos</span>){
        <span class="hljs-keyword">self</span>.getTodosUseCase = getTodosUseCase
    }

    @<span class="hljs-type">Published</span>
    <span class="hljs-keyword">var</span> todos: [<span class="hljs-type">Todo</span>] = []

}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635339497097/SgRO_NaML.png" alt="Screenshot 2021-10-27 at 14.58.13.png" /></p>
<hr />
<h4 id="testtodoviewmodelshouldreturn2todoswhengettodosisinvoked">testTodoViewModel_Should_Return_2_Todos_When_getTodos_Is_Invoked</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635340121789/7YodqHfSJ.png" alt="Screenshot 2021-10-27 at 15.08.25.png" /></p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> getTodosUseCase : <span class="hljs-type">GetTodos</span>

    <span class="hljs-keyword">init</span>(getTodosUseCase: <span class="hljs-type">GetTodos</span>){
        <span class="hljs-keyword">self</span>.getTodosUseCase = getTodosUseCase
    }

    @<span class="hljs-type">Published</span>
    <span class="hljs-keyword">var</span> todos: [<span class="hljs-type">Todo</span>] = []

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async {

        <span class="hljs-keyword">let</span> result = await <span class="hljs-keyword">self</span>.getTodosUseCase.execute()
        <span class="hljs-keyword">switch</span> result{
        <span class="hljs-keyword">case</span> .success(<span class="hljs-keyword">let</span> todos):
            <span class="hljs-keyword">self</span>.todos = todos
        <span class="hljs-keyword">case</span> .failure(<span class="hljs-number">_</span>):
            <span class="hljs-keyword">self</span>.todos = []

        }
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635340197034/_QmRt8lEx.png" alt="Screenshot 2021-10-27 at 15.09.41.png" /></p>
<hr />
<h4 id="testtodoviewmodelshoulddisplayerrormessagewhengettodosresultsinerror">testTodoViewModel_Should_Display_Error_Message_When_getTodos_Results_In_Error</h4>
<p>let's create a use case that results in an error</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation
<span class="hljs-meta">@testable</span> <span class="hljs-keyword">import</span> MyApp

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockGetTodosErrorUseCase</span>: <span class="hljs-title">GetTodos</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">Todo</span>], <span class="hljs-type">UseCaseError</span>&gt; {
        <span class="hljs-type">Result</span>.failure(.dataSourceError)
    }
}
</code></pre>
<center><sub><em>MyAppTests/Domain/UseCase/MockGetTodosErrorUseCase.swift</em></sub></center>




<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635342258714/QDTx78vPz.png" alt="Screenshot 2021-10-27 at 15.34.31.png" /></p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> getTodosUseCase : <span class="hljs-type">GetTodos</span>

    <span class="hljs-keyword">init</span>(getTodosUseCase: <span class="hljs-type">GetTodos</span>){
        <span class="hljs-keyword">self</span>.getTodosUseCase = getTodosUseCase
    }

    @<span class="hljs-type">Published</span>
    <span class="hljs-keyword">var</span> todos: [<span class="hljs-type">Todo</span>] = []


    @<span class="hljs-type">Published</span>
    <span class="hljs-keyword">var</span> errorMessage = <span class="hljs-string">""</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async {

        <span class="hljs-keyword">let</span> result = await <span class="hljs-keyword">self</span>.getTodosUseCase.execute()
        <span class="hljs-keyword">switch</span> result{
        <span class="hljs-keyword">case</span> .success(<span class="hljs-keyword">let</span> todos):
            <span class="hljs-keyword">self</span>.todos = todos
        <span class="hljs-keyword">case</span> .failure(<span class="hljs-keyword">let</span> error):
            <span class="hljs-keyword">self</span>.todos = []

            <span class="hljs-keyword">if</span>(error == <span class="hljs-type">UseCaseError</span>.dataSourceError){
                errorMessage = <span class="hljs-string">"Error"</span>
            }

            <span class="hljs-keyword">if</span>(error == <span class="hljs-type">UseCaseError</span>.decodingError){
                errorMessage = <span class="hljs-string">"Data Decoding Error"</span>
            }
        }
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635342327426/l69hG9JHWd.png" alt="Screenshot 2021-10-27 at 15.45.13.png" /></p>
<p>Our test is finally picking up that the error message is incorrect. We need to rename it from "Error" to "Data Source Error" and all the tests finally pass</p>
<pre><code class="lang-swift">     <span class="hljs-keyword">if</span>(error == <span class="hljs-type">UseCaseError</span>.dataSourceError){
                errorMessage = <span class="hljs-string">"Data Source Error"</span>
            }
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635342457190/C86CEo8TN.png" alt="Screenshot 2021-10-27 at 15.47.31.png" /></p>
<p>Our code for the todo view model is finally done. We can use the same process for all other business logic in other layers.</p>
]]></content:encoded></item><item><title><![CDATA[Getting Started with TDD: Kotlin and Jetpack Compose]]></title><description><![CDATA[The TDD (Test Driven Development) approach is important when it comes to testing small portions of business logic code in isolation.
In this blog, I'll cover how I would use TDD to build a clean architecture To-do Jetpack Compose Android application
...]]></description><link>https://codefoundation.co.za/getting-started-with-tdd-kotlin-and-jetpack-compose</link><guid isPermaLink="true">https://codefoundation.co.za/getting-started-with-tdd-kotlin-and-jetpack-compose</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[TDD (Test-driven development)]]></category><category><![CDATA[Testing]]></category><category><![CDATA[Kotlin]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Wed, 27 Oct 2021 09:30:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635327100497/fFtu9zsiU.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Test-driven_development">TDD (Test Driven Development)</a> approach is important when it comes to testing small portions of business logic code in isolation.</p>
<p>In this blog, I'll cover how I would use TDD to build a <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">clean architecture</a> To-do Jetpack Compose Android application</p>
<p>I'll cover implementing the "Get To-dos" use case.</p>
<p><a target="_blank" href="https://mermaid.live/edit/#eyJjb2RlIjoiZ3JhcGggVERcbiAgICAxW1RvZG9MaXN0Vmlld10gLS0-fE9ic2VydmVzIC8gVXNlc3wgMltUb2RvTGlzdFZpZXdNb2RlbF1cbiAgICAyIC0tPiB8SW52b2tlc3wgM1tHZXRUb2Rvc1VzZUNhc2U6IEdldFRvZG9zXVxuICAgIDMgLS0-IHxVc2VzfCA2W1RvZG9SZXBvc2l0b3J5SW1wbDogVG9kb1JlcG9zaXRvcnldXG4gICAgNiAtLT4gfFVzZXN8IDdbVG9kb0RhdGFTb3VyY2VJbXBsOiBUb2RvRGF0YVNvdXJjZV1cbiAgIFxuICAgICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9"><img src="https://mermaid.ink/img/eyJjb2RlIjoiZ3JhcGggVERcbiAgICAxW1RvZG9MaXN0Vmlld10gLS0-fE9ic2VydmVzIC8gVXNlc3wgMltUb2RvTGlzdFZpZXdNb2RlbF1cbiAgICAyIC0tPiB8SW52b2tlc3wgM1tHZXRUb2Rvc1VzZUNhc2U6IEdldFRvZG9zXVxuICAgIDMgLS0-IHxVc2VzfCA2W1RvZG9SZXBvc2l0b3J5SW1wbDogVG9kb1JlcG9zaXRvcnldXG4gICAgNiAtLT4gfFVzZXN8IDdbVG9kb0RhdGFTb3VyY2VJbXBsOiBUb2RvRGF0YVNvdXJjZV1cbiAgIFxuICAgICIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In0sInVwZGF0ZUVkaXRvciI6ZmFsc2UsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjpmYWxzZX0" alt /></a></p>
<p>For this type of application, we need 2 types for application testing; UI Testing and <strong>Unit Testing</strong>. We'll be concentrating on the business logic, so we'll only be covering TDD <strong>unit testing</strong>. Before we write any production code, we'll write the test first. </p>
<p>The application will be structured in the following file and folder structure:</p>
<pre><code>.
.
├── <span class="hljs-selector-tag">src</span>
    ├── <span class="hljs-selector-tag">Data</span>
    │   ├── <span class="hljs-selector-tag">DataSource</span>
    │   │   ├── <span class="hljs-selector-tag">TodoDataSource</span><span class="hljs-selector-class">.kt</span>
    │   │   └── <span class="hljs-selector-tag">DB</span>
    │   │       ├── <span class="hljs-selector-tag">Entity</span>
    │   │       │    └── <span class="hljs-selector-tag">TodoDBEntity</span><span class="hljs-selector-class">.kt</span>
    │   │       └── <span class="hljs-selector-tag">TodoDBDataSourceImpl</span><span class="hljs-selector-class">.kt</span>
    │   └── <span class="hljs-selector-tag">Repository</span>
    │       └── <span class="hljs-selector-tag">TodoRepositoryImpl</span><span class="hljs-selector-class">.kt</span>
    ├── <span class="hljs-selector-tag">Domain</span>
    │    ├── <span class="hljs-selector-tag">Model</span>
    │    │   └── <span class="hljs-selector-tag">Todo</span><span class="hljs-selector-class">.kt</span>
    │    ├── <span class="hljs-selector-tag">Repository</span>
    │    │   └── <span class="hljs-selector-tag">TodoRepository</span><span class="hljs-selector-class">.kt</span>
    │    └── <span class="hljs-selector-tag">UseCase</span>
    │        └── <span class="hljs-selector-tag">GetTodos</span><span class="hljs-selector-class">.kt</span>
    └── <span class="hljs-selector-tag">Presentation</span>
        ├── <span class="hljs-selector-tag">TodoViewModel</span><span class="hljs-selector-class">.kt</span>
        └── <span class="hljs-selector-tag">TodoListView</span><span class="hljs-selector-class">.kt</span>
└── <span class="hljs-selector-tag">test</span>
    ├── <span class="hljs-selector-tag">Data</span>
    │   ├── <span class="hljs-selector-tag">DataSource</span>
    │   │   └── <span class="hljs-selector-tag">DB</span>
    │   │       └── <span class="hljs-selector-tag">TodoDBDataSourceImplTest</span><span class="hljs-selector-class">.kt</span>
    │   └── <span class="hljs-selector-tag">Repository</span>
    │       └── <span class="hljs-selector-tag">TodoRepositoryImplTest</span><span class="hljs-selector-class">.kt</span>
    ├── <span class="hljs-selector-tag">Domain</span>
    │    └── <span class="hljs-selector-tag">UseCase</span>
    │        └── <span class="hljs-selector-tag">GetTodosTest</span><span class="hljs-selector-class">.kt</span>
    └── <span class="hljs-selector-tag">Presentation</span>
        └── <span class="hljs-selector-tag">TodoViewModelTest</span><span class="hljs-selector-class">.kt</span>
</code></pre><p>We'd like to put the "TodoViewModel" under test.</p>
<h3 id="a-note-on-tdd">A note on TDD</h3>
<p><strong>TDD (Test Driven Development)</strong> is a software development process in which the unit test will be written first and after that the original code. In TDD, the design and development of the code are through unit tests.</p>
<p>In the traditional unit tests, the unit test is written after the original code is written. This is only for long-term maintainability. But in TDD the unit test is written first and code evolved through it.</p>
<p><strong>Red Green Refactor</strong></p>
<p>Red Green Refactor is an interesting concept in TDD. The stages are given below:</p>
<p>Red - First a failing unit test is created, and it results in red status</p>
<p>Green - We will modify the associated code to just make the unit test pass - resulting in green status</p>
<p>Refactor - Once the test is passing we can refactor the code so that the original implementation is done.</p>
<p>When you create an android project, Android Studio automatically creates a UI Test (androidTest) Package and Unit Test (test) Package. </p>
<p>Let's start by writing a test for our View Model.</p>
<hr />
<h4 id="testtodolistviewmodelshouldexist">test_TodoListViewModel_Should_Exist</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635325832598/eMNDfDkEu.png" alt="Screenshot 2021-10-27 at 11.09.59.png" /></p>
<p>Obviously the test doesn't build and therefore fails because these file don't exist. We're in <span>Red Stage</span>. </p>
<p>Let's write the minimum code to make the test pass. We need a view model and its mock dependency. </p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span> <span class="hljs-keyword">constructor</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> GetTodos: GetTodos) : ViewModel() {

}
</code></pre>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">GetTodos</span> </span>{
    <span class="hljs-keyword">suspend</span> <span class="hljs-keyword">operator</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt;
}
</code></pre>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockGetTodosUseCase</span> : <span class="hljs-type">GetTodos {</span></span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-keyword">operator</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt; {
        <span class="hljs-keyword">var</span> list = listOf(
            Todo(id = <span class="hljs-number">1</span>, title = <span class="hljs-string">"One"</span>, isComplete = <span class="hljs-literal">true</span>),
            Todo(id = <span class="hljs-number">2</span>, title = <span class="hljs-string">"Two"</span>, isComplete = <span class="hljs-literal">false</span>),
            Todo(id = <span class="hljs-number">3</span>, title = <span class="hljs-string">"Three"</span>, isComplete = <span class="hljs-literal">true</span>),
            Todo(id = <span class="hljs-number">4</span>, title = <span class="hljs-string">"Four"</span>, isComplete = <span class="hljs-literal">false</span>),
        )

        <span class="hljs-keyword">return</span> list
    }
}
</code></pre>
<p>The test will now pass - <span>Green Stage</span></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635325925322/PStvS1Qgr.png" alt="Screenshot 2021-10-27 at 11.11.40.png" /></p>
<p>Let's add a few more tests to drive the development of the view model</p>
<hr />
<h4 id="testtodolistviewmodelshouldreturnanemptytodoslist">test_TodoListViewModel_Should_Return_An_Empty_Todos_List</h4>
<div>


<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635326042657/VoQ7YBQ3W.png" alt="Screenshot 2021-10-27 at 11.13.26.png" />

</div>


<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span> <span class="hljs-keyword">constructor</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> GetTodos: GetTodos) : ViewModel() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _todos = mutableStateListOf&lt;Todo&gt;()
    <span class="hljs-keyword">val</span> todos: List&lt;Todo&gt;
        <span class="hljs-keyword">get</span>() = _todos
}
</code></pre>
<div>


<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635326147481/dA192X59X.png" alt="Screenshot 2021-10-27 at 11.15.17.png" />
</div>

<hr />
<h4 id="testtodolistviewmodelshouldreturn4todoswhengettodosisinvoked">test_TodoListViewModel_Should_Return_4_Todos_When_getTodos_Is_Invoked</h4>
<div>


<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635326426819/Tmgg_yhhl.png" alt="Screenshot 2021-10-27 at 11.18.46.png" />
</div>


<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span> <span class="hljs-keyword">constructor</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> GetTodos: GetTodos) : ViewModel() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _todos = mutableStateListOf&lt;Todo&gt;()
    <span class="hljs-keyword">val</span> todos: List&lt;Todo&gt;
        <span class="hljs-keyword">get</span>() = _todos

    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> {
        _todos.clear()
        <span class="hljs-keyword">val</span> result = GetTodos()
        _todos.addAll(result)
    }

}
</code></pre>
<div>


<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635326440837/o3Fuu_kaF.png" alt="Screenshot 2021-10-27 at 11.20.08.png" />

</div>

<hr />
<h4 id="testtodolistviewmodelshoulddisplayerrormessagewhengettodosthrowsexception">test_TodoListViewModel_Should_Display_Error_Message_When_getTodos_Throws_Exception</h4>
<div>


<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635326624595/zGz1sIBY9.png" alt="Screenshot 2021-10-27 at 11.22.30.png" />


</div>


<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MockGetTodosThrowingUseCase</span> : <span class="hljs-type">GetTodos {</span></span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-keyword">operator</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt; {
        <span class="hljs-keyword">throw</span> Exception(<span class="hljs-string">"Use Case Error"</span>)
    }
}
</code></pre>
<pre><code class="lang-kt">
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span> <span class="hljs-keyword">constructor</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> GetTodos: GetTodos) : ViewModel() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _todos = mutableStateListOf&lt;Todo&gt;()
    <span class="hljs-keyword">val</span> todos: List&lt;Todo&gt;
        <span class="hljs-keyword">get</span>() = _todos

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _errorMessage = mutableStateOf(<span class="hljs-string">""</span>)
    <span class="hljs-keyword">val</span> errorMessage: String
        <span class="hljs-keyword">get</span>() = _errorMessage.value

    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">try</span> {
            _todos.clear()
            <span class="hljs-keyword">val</span> result = GetTodos()
            _todos.addAll(result)
        } <span class="hljs-keyword">catch</span> (err: Exception) {
            _errorMessage.value = err.message.toString()
        }
    }
}
</code></pre>
<div>


<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635326615634/3hweEVRj2.png" alt="Screenshot 2021-10-27 at 11.23.21.png" />
</div>

<p>We can now continue down the flow dependency chain, unit testing and mocking until we complete the "get todos" use case.</p>
]]></content:encoded></item><item><title><![CDATA[Room(SQLite) and Kotlin]]></title><description><![CDATA[The Room persistence library provides an abstraction layer over SQLite.
To use Room in your app, add the following dependencies to your app’s build.gradle file:
dependencies {
    ....
    kapt "org.xerial:sqlite-jdbc:3.34.0"

    // Room
    def roo...]]></description><link>https://codefoundation.co.za/clean-architecture-typescript-and-react-1</link><guid isPermaLink="true">https://codefoundation.co.za/clean-architecture-typescript-and-react-1</guid><category><![CDATA[clean code]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[SQLite]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Mon, 25 Oct 2021 10:04:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635155350908/v442aUZUD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Room persistence library provides an abstraction layer over SQLite.
To use Room in your app, add the following dependencies to your app’s build.gradle file:</p>
<pre><code>dependencies {
    ....
    kapt <span class="hljs-string">"org.xerial:sqlite-jdbc:3.34.0"</span>

    <span class="hljs-comment">// Room</span>
    def room_version = <span class="hljs-string">"2.3.0"</span>
    implementation <span class="hljs-string">"androidx.room:room-runtime:<span class="hljs-variable">$room_version</span>"</span>
    annotationProcessor <span class="hljs-string">"androidx.room:room-compiler:<span class="hljs-variable">$room_version</span>"</span>
    kapt <span class="hljs-string">"androidx.room:room-compiler:<span class="hljs-variable">$room_version</span>"</span>
    implementation <span class="hljs-string">"androidx.room:room-ktx:<span class="hljs-variable">$room_version</span>"</span>
}
</code></pre><p><strong>Note</strong>: the “sqlite-jdbc” needed at the time of this blog if you’re running an arm processor as you’ll get this without it: “No native library is found for os.name=Mac and os.arch=aarch64”</p>
<p>After adding those dependencies, let’s once again continue with a clean architectured project by creating the following structure. We’ll only cover the files on display</p>
<pre><code>├─<span class="hljs-selector-tag">Core</span>
├─<span class="hljs-selector-tag">Presentation</span>
├─<span class="hljs-selector-tag">Domain</span>
│ ├─<span class="hljs-selector-tag">Model</span>
│ │ └─ <span class="hljs-selector-tag">Todo</span><span class="hljs-selector-class">.kt</span>
│ └─<span class="hljs-selector-tag">Repository</span>
│   └─ <span class="hljs-selector-tag">TodoRepository</span><span class="hljs-selector-class">.kt</span>
└─<span class="hljs-selector-tag">Data</span>
  ├─<span class="hljs-selector-tag">DataSource</span> 
  │ ├─ <span class="hljs-selector-tag">TodoDataSource</span><span class="hljs-selector-class">.kt</span>
  │ └─<span class="hljs-selector-tag">Room</span>
  │   ├─ <span class="hljs-selector-tag">TodoDao</span><span class="hljs-selector-class">.kt</span>
  │   ├─ <span class="hljs-selector-tag">TodoDatabase</span><span class="hljs-selector-class">.kt</span>
  │   ├─ <span class="hljs-selector-tag">TodoRoomDataSourceImpl</span><span class="hljs-selector-class">.kt</span>
  │   └─<span class="hljs-selector-tag">Entity</span>
  │     └─<span class="hljs-selector-tag">TodoRoomEntity</span><span class="hljs-selector-class">.kt</span>
  └─<span class="hljs-selector-tag">Repository</span>
    └─<span class="hljs-selector-tag">TodoRepositoryImpl</span><span class="hljs-selector-class">.kt</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635156049920/gjdes1mGG.png" alt="1_gu0Jz4YWQwyl4M_y6sM8kQ.png" /></p>
<pre><code class="lang-kt"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Todo</span></span>(
    <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Int</span>?,
    <span class="hljs-keyword">val</span> title: String,
    <span class="hljs-keyword">val</span> isComplete: <span class="hljs-built_in">Boolean</span>,
)
</code></pre>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TodoRepository</span> </span>{
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>: Result&lt;List&lt;Todo&gt;&gt;
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodo</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>: Result&lt;Todo&gt;
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">deleteTodo</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>: Result&lt;<span class="hljs-built_in">Boolean</span>&gt;
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createTodo</span><span class="hljs-params">(todo: <span class="hljs-type">Todo</span>)</span></span>: Result&lt;<span class="hljs-built_in">Boolean</span>&gt;
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">updateTodo</span><span class="hljs-params">(todo: <span class="hljs-type">Todo</span>)</span></span>: Result&lt;<span class="hljs-built_in">Boolean</span>&gt;
}
</code></pre>
<p>Next, we’ll specify what our Datasource must do by creating the TodoDataSource interface</p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TodoDataSource</span> </span>{
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getAll</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt;
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getById</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">delete</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">create</span><span class="hljs-params">(todo: <span class="hljs-type">Todo</span>)</span></span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">update</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>, todo: <span class="hljs-type">Todo</span>)</span></span>
}
</code></pre>
<p>Ok now let’s implement these project details:</p>
<p>We need three things to allow our Kotlin code to talk to our SQLite DB:</p>
<ol>
<li>Data entities: data classes that represent database tables</li>
<li>Data access objects (DAO): container of methods that map to SQL queries</li>
<li>Database class: the main access point for persisting data</li>
</ol>
<p>Let’s start with our data entity. We’ll name this TodoRoomEntity as this represents a room-specific entity. Note how the extra mapping code from TodoRoomEntity to Todo data class in the Domain layer.</p>
<pre><code class="lang-kt">
<span class="hljs-meta">@Entity(tableName = <span class="hljs-meta-string">"tb_todo"</span>)</span>
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoRoomEntity</span></span>(
    <span class="hljs-meta">@PrimaryKey(autoGenerate = true)</span>
    <span class="hljs-meta">@ColumnInfo(name = <span class="hljs-meta-string">"id"</span>)</span>
    <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Int</span>?,
    <span class="hljs-keyword">val</span> title: String,
    <span class="hljs-keyword">val</span> is_complete: <span class="hljs-built_in">Boolean</span>
)

<span class="hljs-function"><span class="hljs-keyword">fun</span> TodoRoomEntity.<span class="hljs-title">toTodo</span><span class="hljs-params">()</span></span>: Todo {
    <span class="hljs-keyword">return</span> Todo(
        id = id,
        isComplete = is_complete,
        title = title
    )
}
</code></pre>
<p>Now let’s create the DAO and the database</p>
<pre><code class="lang-kt"><span class="hljs-meta">@Dao</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TodoDao</span> </span>{
    <span class="hljs-meta">@Query(<span class="hljs-meta-string">"SELECT * FROM tb_todo"</span>)</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getAll</span><span class="hljs-params">()</span></span>: List&lt;TodoRoomEntity&gt;

    <span class="hljs-meta">@Insert(onConflict = OnConflictStrategy.REPLACE)</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">insert</span><span class="hljs-params">(todo: <span class="hljs-type">TodoRoomEntity</span>)</span></span>

    <span class="hljs-meta">@Update</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">update</span><span class="hljs-params">(<span class="hljs-keyword">vararg</span> todos: <span class="hljs-type">TodoRoomEntity</span>)</span></span>

    <span class="hljs-meta">@Query(<span class="hljs-meta-string">"SELECT * FROM tb_todo WHERE id = :id"</span>)</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getById</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>: TodoRoomEntity?

    <span class="hljs-meta">@Query(<span class="hljs-meta-string">"DELETE FROM tb_todo WHERE id = :id"</span>)</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">deleteById</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>

}
</code></pre>
<pre><code class="lang-kt"><span class="hljs-meta">@Database(entities = [TodoRoomEntity::class], version = 1)</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoDatabase</span> : <span class="hljs-type">RoomDatabase</span></span>() {
    <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">val</span> todoDao: TodoDao

    <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> {
        <span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> DATABASE_NAME = <span class="hljs-string">"todo_db"</span>
    }
}
</code></pre>
<p>To use the Dao we can create a data source that conforms to the TodoDataSource. We inject the DAO as a dependency.</p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoRoomDataSourceImpl</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> dao: TodoDao) : TodoDataSource {

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getAll</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt; {
        <span class="hljs-keyword">return</span> dao.getAll().map { it.toTodo() }
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getById</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>: Todo? {
        <span class="hljs-keyword">val</span> todoRoomEntity = dao.getById(id)
        <span class="hljs-keyword">if</span> (todoRoomEntity != <span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">return</span> todoRoomEntity.toTodo()
        }
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">delete</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span> {
        dao.deleteById(id)
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">create</span><span class="hljs-params">(todo: <span class="hljs-type">Todo</span>)</span></span> {
        dao.insert(
            TodoRoomEntity(
                id = <span class="hljs-literal">null</span>,
                title = todo.title,
                is_complete = todo.isComplete
            )
        )
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">update</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>, todo: <span class="hljs-type">Todo</span>)</span></span> {
        dao.update(
            TodoRoomEntity(
                id = id,
                title = todo.title,
                is_complete = todo.isComplete
            )
        )
    }
}
</code></pre>
<p>and then lastly, our TodoRepositoryImpl would implement our TodoRepository:</p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoRepositoryImpl</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> datasource: TodoDataSource) : TodoRepository {
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>: Result&lt;List&lt;Todo&gt;&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> {
            Result.success(datasource.getAll())
        } <span class="hljs-keyword">catch</span> (e: Exception) {
            Result.failure(Exception(<span class="hljs-string">"Error Getting Data"</span>))
        }
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodo</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>: Result&lt;Todo?&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">val</span> todo = datasource.getById(id)
            Result.success(todo)
        } <span class="hljs-keyword">catch</span> (e: Exception) {
            Result.failure(Exception(<span class="hljs-string">"Error Getting Todo"</span>))
        }
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">deleteTodo</span><span class="hljs-params">(id: <span class="hljs-type">Int</span>)</span></span>: Result&lt;<span class="hljs-built_in">Boolean</span>&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> {
            Result.success(<span class="hljs-literal">true</span>)
        } <span class="hljs-keyword">catch</span> (e: Exception) {
            Result.failure(Exception(<span class="hljs-string">"Error Deleting Data"</span>))
        }
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createTodo</span><span class="hljs-params">(todo: <span class="hljs-type">Todo</span>)</span></span>: Result&lt;<span class="hljs-built_in">Boolean</span>&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> {
            Result.success(<span class="hljs-literal">true</span>)
        } <span class="hljs-keyword">catch</span> (e: Exception) {
            Result.failure(Exception(<span class="hljs-string">"Error Creating Todo"</span>))
        }
    }

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">updateTodo</span><span class="hljs-params">(todo: <span class="hljs-type">Todo</span>)</span></span>: Result&lt;<span class="hljs-built_in">Boolean</span>&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> {
            datasource.update(todo.id!!, todo)
            Result.success(<span class="hljs-literal">true</span>)
        } <span class="hljs-keyword">catch</span> (e: Exception) {
            Result.failure(Exception(<span class="hljs-string">"Error Updating Todo"</span>))
        }
    }
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Kotlin Dependency Injection with Hilt]]></title><description><![CDATA[It is encouraged that you divide your code into classes to benefit from separation of concerns, a principle where each class of the hierarchy has a single defined responsibility. This leads to more, smaller classes that need to be connected together ...]]></description><link>https://codefoundation.co.za/kotlin-dependency-injection-with-hilt</link><guid isPermaLink="true">https://codefoundation.co.za/kotlin-dependency-injection-with-hilt</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[dependency injection]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Mon, 25 Oct 2021 08:57:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635152005007/vyWg_NEUL.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is encouraged that you divide your code into classes to benefit from separation of concerns, a principle where each class of the hierarchy has a single defined responsibility. This leads to more, smaller classes that need to be connected together to fulfil each other’s dependencies.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635151963405/UC3SrCQ3h.png" alt="1_g4faqaRC1dGwzkp-byC3qg.png" /></p>
<p>Of course, we can use good old manual dependency injection as follows:</p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {

        <span class="hljs-keyword">val</span> viewModel = TodoViewModel(
            GetTodos = GetTodosUseCase(
                todoRepository = TodoRepositoryImpl(
                    datasource = TodoDataSourceImpl()
                )
            ),
            CreateTodo = CreateTodoUseCase(
                todoRepository = TodoRepositoryImpl(
                    datasource = TodoDataSourceImpl()
                )
            ),
            DeleteTodo =  DeleteTodoUseCase(
                todoRepository = TodoRepositoryImpl(
                    datasource = TodoDataSourceImpl()
                )
            )
        )

        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent {
            TodoView(viewModel)
        }
    }
}
</code></pre>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span>  <span class="hljs-keyword">constructor</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> GetTodos: GetTodos,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> CreateTodo: CreateTodo,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> DeleteTodo: DeleteTodo
) : ViewModel() {

...

}
</code></pre>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GetTodosUseCase</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> todoRepository: TodoRepository) : GetTodos {
    ...
}
</code></pre>
<pre><code class="lang-kt">
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoRepositoryImpl</span></span>(<span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> datasource: TodoDataSource) : TodoRepository {
    ...
}
</code></pre>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoDataSourceImpl</span></span>() : TodoDataSource {
    ...
}
</code></pre>
<p>To ease the pain of dependency injection, we are going to use  <a target="_blank" href="https://dagger.dev/hilt/">Hilt</a>  to manage and resolve our dependencies.</p>
<p>To use Hilt, add the following build dependencies to the Android Gradle module’s build.gradle file:</p>
<pre><code>plugins {
    <span class="hljs-keyword">...</span>
    id <span class="hljs-string">'dagger.hilt.android.plugin'</span>
}
dependencies {
    <span class="hljs-keyword">...</span>
    implementation <span class="hljs-string">'com.google.dagger:hilt-android:2.39.1'</span>
    implementation <span class="hljs-string">'androidx.hilt:hilt-navigation-compose:1.0.0-alpha03'</span>
    kapt <span class="hljs-string">"com.google.dagger:hilt-compiler:2.39.1"</span>
    kapt <span class="hljs-string">"androidx.hilt:hilt-compiler:1.0.0"</span>
}
</code></pre><p>Note: you only need “hilt-navigation-compose” if you intend to inject view models</p>
<p>Let’s start.</p>
<ol>
<li>Make your project aware of Hilt and that's it’s going to do DI for you</li>
<li>Mark the android activity that is going to be the root or starting point of all DI</li>
<li>Tell Hilt how to provide instances of a ViewModel.</li>
<li>Mark class constructors with @Inject to tell Hilt how to create instances of a class.</li>
<li>Create your IOC container</li>
</ol>
<h3 id="create-hilt-android-app">Create Hilt Android App</h3>
<p>All apps that use Hilt must contain an application class that is annotated with @HiltAndroidApp.</p>
<p>Create a file in the root package:</p>
<pre><code class="lang-kt"><span class="hljs-keyword">import</span> android.app.Application
<span class="hljs-keyword">import</span> dagger.hilt.android.HiltAndroidApp

<span class="hljs-meta">@HiltAndroidApp</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoApp</span> : <span class="hljs-type">Application</span></span>()
</code></pre>
<p>Update your application name in your AndroidManifest.xml file</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">manifest</span> <span class="hljs-attr">xmlns:android</span>=<span class="hljs-string">"http://schemas.android.com/apk/res/android"</span>
    <span class="hljs-attr">package</span>=<span class="hljs-string">"com.diexample"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">application</span>
        <span class="hljs-attr">android:name</span>=<span class="hljs-string">".TodoApp"</span>
        <span class="hljs-attr">...</span>
    &gt;</span>
        ...                 
    <span class="hljs-tag">&lt;/<span class="hljs-name">application</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">manifest</span>&gt;</span>
</code></pre>
<h3 id="mark-mainactivity-as-androidentrypoint">Mark MainActivity as AndroidEntryPoint</h3>
<p>For Hilt to be able to inject dependencies into an activity, the activity needs to be annotated with @AndroidEntryPoint. Let’s change our MainActivity from before to:</p>
<pre><code class="lang-kt"><span class="hljs-meta">@AndroidEntryPoint</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent {
            TodoView()
        }
    }
}
</code></pre>
<pre><code class="lang-kt"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">TodoView</span><span class="hljs-params">(vm: <span class="hljs-type">TodoViewModel</span> = hiltViewModel()</span></span>) {
   ... 
}
</code></pre>
<h3 id="create-ioc-container">Create IOC Container</h3>
<p>Next, we create our container to list and resolve our dependencies.</p>
<pre><code class="lang-kt"><span class="hljs-meta">@Module</span>
<span class="hljs-meta">@InstallIn(SingletonComponent::class)</span>
<span class="hljs-keyword">object</span> AppModule {

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">providesTodoDatasource</span><span class="hljs-params">(db: <span class="hljs-type">TodoDatabase</span>)</span></span>: TodoDataSource {
        <span class="hljs-keyword">return</span> TodoRoomDataSourceImpl()
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">providesTodoRepository</span><span class="hljs-params">(dataSource: <span class="hljs-type">TodoDataSource</span>)</span></span>: TodoRepository {
        <span class="hljs-keyword">return</span> TodoRepositoryImpl(datasource = dataSource)
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">providesGetTodosUseCase</span><span class="hljs-params">(repository: <span class="hljs-type">TodoRepository</span>)</span></span>: GetTodos {
        <span class="hljs-keyword">return</span> GetTodosUseCase(todoRepository = repository)
    }


    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">providesCreateTodoUseCase</span><span class="hljs-params">(repository: <span class="hljs-type">TodoRepository</span>)</span></span>: CreateTodo {
        <span class="hljs-keyword">return</span> CreateTodoUseCase(todoRepository = repository)
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">providesDeleteTodoUseCase</span><span class="hljs-params">(repository: <span class="hljs-type">TodoRepository</span>)</span></span>: DeleteTodo {
        <span class="hljs-keyword">return</span> DeleteTodoUseCase(todoRepository = repository)
    }


}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Core Data and Swift]]></title><description><![CDATA[Continuing with our clean architecture, let’s write a simple Todo CoreData Datasource in swift. Our applications repository method would use the DataSource, in this case, the TodoCoreDataSource. Here is the proposed files and their locations:
├─Core
...]]></description><link>https://codefoundation.co.za/core-data-and-swift</link><guid isPermaLink="true">https://codefoundation.co.za/core-data-and-swift</guid><category><![CDATA[clean code]]></category><category><![CDATA[Swift]]></category><category><![CDATA[Databases]]></category><category><![CDATA[iOS]]></category><category><![CDATA[ios app development]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Mon, 25 Oct 2021 07:41:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635147318845/wSoCsnCDI.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Continuing with our clean architecture, let’s write a simple Todo CoreData Datasource in swift. Our applications repository method would use the DataSource, in this case, the TodoCoreDataSource. Here is the proposed files and their locations:</p>
<pre><code>├─<span class="hljs-selector-tag">Core</span>
└─<span class="hljs-selector-tag">Data</span>
    ├─<span class="hljs-selector-tag">DataSource</span>
    │   ├── <span class="hljs-selector-tag">TodoDataSource</span><span class="hljs-selector-class">.swift</span>
    │   └─<span class="hljs-selector-tag">CoreData</span>
    │       ├── <span class="hljs-selector-tag">Main</span><span class="hljs-selector-class">.xcdatamodeld</span>
    │       └── <span class="hljs-selector-tag">TodoCoreDataSourceImpl</span><span class="hljs-selector-class">.swift</span>
    └─<span class="hljs-selector-tag">Repository</span>
        └── <span class="hljs-selector-tag">TodoRepositoryImpl</span><span class="hljs-selector-class">.swift</span>

├─<span class="hljs-selector-tag">Presentation</span>
└─<span class="hljs-selector-tag">Domain</span>
    ├─<span class="hljs-selector-tag">Model</span>
    │ └── <span class="hljs-selector-tag">Todo</span><span class="hljs-selector-class">.swift</span>
    ├─<span class="hljs-selector-tag">Error</span>
    │ └── <span class="hljs-selector-tag">TodoError</span><span class="hljs-selector-class">.swift</span>
    └─<span class="hljs-selector-tag">Repository</span>
      └── <span class="hljs-selector-tag">TodoRepository</span><span class="hljs-selector-class">.swift</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635147362037/hg9IMT1lP.png" alt="1_8s522ULc1qqqD6o5dtzu4Q.png" /></p>
<p>Let’s first specify our Domain Model and Repository. We need a domain model because we can’t always control what our data source model looks and operates like.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Todo</span>: <span class="hljs-title">Identifiable</span></span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">UUID</span>
    <span class="hljs-keyword">let</span> title: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> isCompleted: <span class="hljs-type">Bool</span>
}
</code></pre>
<p>Mapping between these two models would need to take place in our data source.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">TodoDataSource</span></span>{
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getAll</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">Todo</span>]
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getById</span><span class="hljs-params">(<span class="hljs-number">_</span> id: UUID)</span></span> async <span class="hljs-keyword">throws</span> -&gt; <span class="hljs-type">Todo?</span>
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">delete</span><span class="hljs-params">(<span class="hljs-number">_</span> id: UUID)</span></span> async <span class="hljs-keyword">throws</span> -&gt; ()
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">create</span><span class="hljs-params">(todo: Todo)</span></span> async <span class="hljs-keyword">throws</span> -&gt; ()
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">update</span><span class="hljs-params">(id: UUID, todo: Todo)</span></span> async <span class="hljs-keyword">throws</span> -&gt; ()
}
</code></pre>
<p>This time around we need a persistence framework for our data source. Here we’re going to use  <a target="_blank" href="https://developer.apple.com/documentation/coredata">Core Data</a>  to save your application’s permanent data for offline use.</p>
<p>Create a CoreData Model by adding a new file and choosing Core Data -&gt; Data Model and creating at TodoCoreDataEntity:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635147456135/o_8b-EHuJ.png" alt="1_hlk14ihTrCzRXqpfnkifgQ.png" /></p>
<p>To use the CoreData Main Model we can create a data source that conforms to the TodoDataSource and uses the NSPersitanceContainer.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation
<span class="hljs-keyword">import</span> CoreData

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoCoreDataSourceImpl</span>: <span class="hljs-title">TodoDataSource</span> </span>{

    <span class="hljs-keyword">let</span> container: <span class="hljs-type">NSPersistentContainer</span>

    <span class="hljs-keyword">init</span>(){
        container = <span class="hljs-type">NSPersistentContainer</span>(name: <span class="hljs-string">"Main"</span>)
        container.loadPersistentStores { description, error <span class="hljs-keyword">in</span>
            <span class="hljs-keyword">if</span> error != <span class="hljs-literal">nil</span> {
                <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"Cannot Load Core Data Model"</span>)
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getAll</span><span class="hljs-params">()</span></span> <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">Todo</span>]{
        <span class="hljs-keyword">let</span> request = <span class="hljs-type">TodoCoreDataEntity</span>.fetchRequest()
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">try</span> container.viewContext.fetch(request).<span class="hljs-built_in">map</span>({ todoCoreDataEntity <span class="hljs-keyword">in</span>
            <span class="hljs-type">Todo</span>(
                id: todoCoreDataEntity.id!,
                 title: todoCoreDataEntity.title!,
                isCompleted: todoCoreDataEntity.is_completed
            )
        })

    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getById</span><span class="hljs-params">(<span class="hljs-number">_</span> id: UUID)</span></span>  <span class="hljs-keyword">throws</span>  -&gt; <span class="hljs-type">Todo?</span>{
        <span class="hljs-keyword">let</span> todoCoreDataEntity = <span class="hljs-keyword">try</span> getEntityById(id)!
        <span class="hljs-keyword">return</span> <span class="hljs-type">Todo</span>(
            id: todoCoreDataEntity.id!,
            title: todoCoreDataEntity.title!,
            isCompleted: todoCoreDataEntity.is_completed
        )

    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">delete</span><span class="hljs-params">(<span class="hljs-number">_</span> id: UUID)</span></span> <span class="hljs-keyword">throws</span> -&gt; (){
        <span class="hljs-keyword">let</span> todoCoreDataEntity = <span class="hljs-keyword">try</span> getEntityById(id)!
        <span class="hljs-keyword">let</span> context = container.viewContext;
        context.delete(todoCoreDataEntity)
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">try</span> context.save()
        }<span class="hljs-keyword">catch</span>{
            context.rollback()
            <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"Error: \(error.localizedDescription)"</span>)
        }

    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">update</span><span class="hljs-params">(id: UUID, todo: Todo)</span></span> <span class="hljs-keyword">throws</span> -&gt; (){
        <span class="hljs-keyword">let</span> todoCoreDataEntity = <span class="hljs-keyword">try</span> getEntityById(id)!
        todoCoreDataEntity.is_completed = todo.isCompleted
        todoCoreDataEntity.title = todo.title
        saveContext()
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">create</span><span class="hljs-params">(todo: Todo)</span></span> <span class="hljs-keyword">throws</span> -&gt; (){
        <span class="hljs-keyword">let</span> todoCoreDataEntity = <span class="hljs-type">TodoCoreDataEntity</span>(context: container.viewContext)
        todoCoreDataEntity.is_completed = todo.isCompleted
        todoCoreDataEntity.title = todo.title
        todoCoreDataEntity.id = todo.id
        saveContext()
    }


    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getEntityById</span><span class="hljs-params">(<span class="hljs-number">_</span> id: UUID)</span></span>  <span class="hljs-keyword">throws</span>  -&gt; <span class="hljs-type">TodoCoreDataEntity?</span>{
        <span class="hljs-keyword">let</span> request = <span class="hljs-type">TodoCoreDataEntity</span>.fetchRequest()
        request.fetchLimit = <span class="hljs-number">1</span>
        request.predicate = <span class="hljs-type">NSPredicate</span>(
            format: <span class="hljs-string">"id = %@"</span>, id.uuidString)
        <span class="hljs-keyword">let</span> context =  container.viewContext
        <span class="hljs-keyword">let</span> todoCoreDataEntity = <span class="hljs-keyword">try</span> context.fetch(request)[<span class="hljs-number">0</span>]
        <span class="hljs-keyword">return</span> todoCoreDataEntity

    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">saveContext</span><span class="hljs-params">()</span></span>{
        <span class="hljs-keyword">let</span> context = container.viewContext
        <span class="hljs-keyword">if</span> context.hasChanges {
            <span class="hljs-keyword">do</span>{
                <span class="hljs-keyword">try</span> context.save()
            }<span class="hljs-keyword">catch</span>{
                <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"Error: \(error.localizedDescription)"</span>)
            }
        }
    }

}
</code></pre>
<p>and then lastly, our TodoRepositoryImpl would implement our TodoRepository and call our Datasource:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">TodoRepository</span> </span>{
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">Todo</span>], <span class="hljs-type">TodoError</span>&gt;
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodo</span><span class="hljs-params">(id: UUID)</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Todo?</span> , <span class="hljs-type">TodoError</span>&gt;
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">deleteTodo</span><span class="hljs-params">(<span class="hljs-number">_</span> id: UUID)</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">TodoError</span>&gt;
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">createTodo</span><span class="hljs-params">(<span class="hljs-number">_</span> todo: Todo)</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">TodoError</span>&gt;
 <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateTodo</span><span class="hljs-params">(<span class="hljs-number">_</span> todo: Todo)</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">TodoError</span>&gt;
}
</code></pre>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">TodoError</span>: <span class="hljs-title">Error</span></span>{
 <span class="hljs-keyword">case</span> <span class="hljs-type">DataSourceError</span>, <span class="hljs-type">CreateError</span>, <span class="hljs-type">DeleteError</span>, <span class="hljs-type">UpdateError</span>, <span class="hljs-type">FetchError</span>
}
</code></pre>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoRepositoryImpl</span>: <span class="hljs-title">TodoRepository</span></span>{

    <span class="hljs-keyword">var</span> dataSource: <span class="hljs-type">TodoDataSource</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodo</span><span class="hljs-params">(id: UUID)</span></span> async  -&gt; <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Todo?</span>, <span class="hljs-type">TodoError</span>&gt; {
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">let</span> _todo =  <span class="hljs-keyword">try</span> await dataSource.getById(id)
            <span class="hljs-keyword">return</span> .success(_todo)
        }<span class="hljs-keyword">catch</span>{
            <span class="hljs-keyword">return</span> .failure(.<span class="hljs-type">FetchError</span>)
        }

    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">deleteTodo</span><span class="hljs-params">(<span class="hljs-number">_</span> id: UUID)</span></span> async -&gt;  <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">TodoError</span>&gt;  {
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">try</span> await dataSource.delete(id)
            <span class="hljs-keyword">return</span> .success(<span class="hljs-literal">true</span>)
        }<span class="hljs-keyword">catch</span>{
            <span class="hljs-keyword">return</span> .failure(.<span class="hljs-type">DeleteError</span>)
        }

    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">createTodo</span><span class="hljs-params">(<span class="hljs-number">_</span> todo: Todo)</span></span> async -&gt;  <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">TodoError</span>&gt;   {
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">try</span> await dataSource.create(todo: todo)
            <span class="hljs-keyword">return</span> .success(<span class="hljs-literal">true</span>)
        }<span class="hljs-keyword">catch</span>{
            <span class="hljs-keyword">return</span> .failure(.<span class="hljs-type">CreateError</span>)
        }

    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">updateTodo</span><span class="hljs-params">(<span class="hljs-number">_</span> todo: Todo)</span></span> async -&gt;  <span class="hljs-type">Result</span>&lt;<span class="hljs-type">Bool</span>, <span class="hljs-type">TodoError</span>&gt;   {
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">try</span> await dataSource.update(id: todo.id, todo:todo)
            <span class="hljs-keyword">return</span> .success(<span class="hljs-literal">true</span>)
        }<span class="hljs-keyword">catch</span>{
            <span class="hljs-keyword">return</span> .failure(.<span class="hljs-type">UpdateError</span>)
        }

    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async -&gt; <span class="hljs-type">Result</span>&lt;[<span class="hljs-type">Todo</span>], <span class="hljs-type">TodoError</span>&gt; {
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">let</span> _todos =  <span class="hljs-keyword">try</span> await dataSource.getAll()
            <span class="hljs-keyword">return</span> .success(_todos)
        }<span class="hljs-keyword">catch</span>{
            <span class="hljs-keyword">return</span> .failure(.<span class="hljs-type">FetchError</span>)
        }
    }
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Clean Architecture: TypeScript and React]]></title><description><![CDATA[By employing  clean architecture, you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It ...]]></description><link>https://codefoundation.co.za/clean-architecture-typescript-and-react</link><guid isPermaLink="true">https://codefoundation.co.za/clean-architecture-typescript-and-react</guid><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Sun, 24 Oct 2021 18:43:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635100819702/u_Xt8ZLrd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>By employing  <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">clean architecture</a>, you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It also becomes intrinsically testable. Here I’ll show how I structure my clean architecture projects. This time we are going to build a React todo application using Typescript.</p>
<p>The folder/group structure of the project takes on the following form:</p>
<pre><code>├── Core
├── Data
├── <span class="hljs-keyword">Domain</span>
└── Presentation
</code></pre><p>Let’s start with the Domain Layer.</p>
<p>This layer describes <strong>WHAT</strong> your project/application does. Let me explain, Many applications are built and structured in a way that you cannot understand what the application does by merely looking at the folder structure. Using a building of a house analogy, you can quickly identify what a building would look like and its functionality by viewing the floor plan and elevation of the building</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635064158057/IjnmnmSgo.png" alt="1_GfMGNsEj814uSiYw1Vq23w.png" /></p>
<p>In the same way, the domain layer of our project should specify and describe <strong>WHAT</strong> our application does. In this folder, we would use models, repository interfaces, and use cases.</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Data</span>
├── <span class="hljs-selector-tag">Presentation</span>
└── <span class="hljs-selector-tag">Domain</span>
    ├── <span class="hljs-selector-tag">Model</span>
    │   ├── <span class="hljs-selector-tag">Todo</span><span class="hljs-selector-class">.ts</span>
    │   └── <span class="hljs-selector-tag">User</span><span class="hljs-selector-class">.ts</span>
    ├── <span class="hljs-selector-tag">Repository</span>
    │   ├── <span class="hljs-selector-tag">TodoRepository</span><span class="hljs-selector-class">.ts</span>
    │   └── <span class="hljs-selector-tag">UserRepository</span><span class="hljs-selector-class">.ts</span>
    └── <span class="hljs-selector-tag">UseCase</span>
        ├── <span class="hljs-selector-tag">Todo</span>
        │   ├── <span class="hljs-selector-tag">GetTodos</span><span class="hljs-selector-class">.ts</span>
        │   ├── <span class="hljs-selector-tag">GetTodo</span><span class="hljs-selector-class">.ts</span>
        │   ├── <span class="hljs-selector-tag">DeleteTodo</span><span class="hljs-selector-class">.ts</span>
        │   ├── <span class="hljs-selector-tag">UpdateTodo</span><span class="hljs-selector-class">.ts</span>
        │   └── <span class="hljs-selector-tag">CreateTodo</span><span class="hljs-selector-class">.ts</span>
        └── <span class="hljs-selector-tag">User</span>
            ├── <span class="hljs-selector-tag">GetUsers</span><span class="hljs-selector-class">.ts</span>
            ├── <span class="hljs-selector-tag">GetUser</span><span class="hljs-selector-class">.ts</span>
            ├── <span class="hljs-selector-tag">DeleteUser</span><span class="hljs-selector-class">.ts</span>
            ├── <span class="hljs-selector-tag">UpdateUser</span><span class="hljs-selector-class">.ts</span>
            └── <span class="hljs-selector-tag">CreateUser</span><span class="hljs-selector-class">.ts</span>
</code></pre><ol>
<li><strong>Model</strong>: A model typically represents a real-world object that is related to the problem. In this folder, we would typically keep classes to represent objects. e.g. Todo, User, Product, etc</li>
<li><strong>Repository</strong>: Container for all repository interfaces. The repository is a central place to keep all model-specific operations. In this case, the Todo repository interface would describe repository methods. The actual repository implementation will be kept in the Data layer.</li>
<li><strong>UseCases</strong>: Container to list all functionality of our application. e.g Get Todos, Delete Todo, Create Todo, Update Todo</li>
</ol>
<p>The <strong>PRESENTATION</strong> layer will keep all of the consumer-related code as to <strong>HOW</strong> the application will interact with the outside world. The presentation layer can be WebForms, Command Line Interface, API Endpoints, etc. In this case, it would be the screens for a List of Todos and its accompanying view model.</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Data</span>
├── <span class="hljs-selector-tag">Domain</span>
└── <span class="hljs-selector-tag">Presentation</span>
    └── <span class="hljs-selector-tag">Todo</span>
        └── <span class="hljs-selector-tag">TodoList</span>
            ├── <span class="hljs-selector-tag">TodoListViewModel</span><span class="hljs-selector-class">.tsx</span>
            └── <span class="hljs-selector-tag">TodoListView</span><span class="hljs-selector-class">.tsx</span>
</code></pre><p>The <strong>DATA</strong> layer will keep all the external dependency-related code as to HOW they are implemented:</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Domain</span>
├── <span class="hljs-selector-tag">Presentation</span>
└── <span class="hljs-selector-tag">Data</span>
    ├── <span class="hljs-selector-tag">Repository</span>
    │   ├── <span class="hljs-selector-tag">TodoRepositoryImpl</span><span class="hljs-selector-class">.ts</span>
    └── <span class="hljs-selector-tag">DataSource</span>
        ├── <span class="hljs-selector-tag">TodoDataSource</span><span class="hljs-selector-class">.ts</span>
        ├── <span class="hljs-selector-tag">API</span>
        │   ├── <span class="hljs-selector-tag">TodoAPIDataSourceImpl</span><span class="hljs-selector-class">.ts</span>
        │   └── <span class="hljs-selector-tag">Entity</span>
        │       ├── <span class="hljs-selector-tag">TodoAPIEntity</span><span class="hljs-selector-class">.ts</span>
        │       └── <span class="hljs-selector-tag">UserAPIEntity</span><span class="hljs-selector-class">.ts</span>
        └── <span class="hljs-selector-tag">DB</span>
            ├── <span class="hljs-selector-tag">TodoDBDataSourceImpl</span><span class="hljs-selector-class">.ts</span>
            └── <span class="hljs-selector-tag">Entity</span>
                ├── <span class="hljs-selector-tag">TodoDBEntity</span><span class="hljs-selector-class">.ts</span>
                └── <span class="hljs-selector-tag">UserDBEntity</span><span class="hljs-selector-class">.ts</span>
</code></pre><ol>
<li><strong>Repository</strong>: Repository implementations</li>
<li><strong>DataSource</strong>: All data source interfaces and entities. An entity represents a single instance of your domain object saved into the database as a record. It has some attributes that we represent as columns in our DB tables or API endpoints. We can’t control how data is modeled on the external data source, so these entities are required to be mapped from entities to domain models in the implementations</li>
</ol>
<p>and lastly, the <strong>CORE</strong> layer keep all the components that are common across all layers like constants or configs or dependency injection (which we won’t cover)
Our first task would be always to start with the domain models and data entities. Let’s start with the model</p>
<pre><code class="lang-ts"><span class="hljs-comment">//Domain/Model/Todo.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Todo {
  id: <span class="hljs-built_in">number</span>;
  title: <span class="hljs-built_in">string</span>;
  isComplete: <span class="hljs-built_in">boolean</span>;
}
</code></pre>
<p>We need it to conform to Identifiable as we’re going to display these items in a list view.</p>
<p>Next, let’s do the todo entity</p>
<pre><code class="lang-ts"><span class="hljs-comment">//Data/DataSource/API/Entity/TodoAPIEntity.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> TodoAPIEntity {
  id: <span class="hljs-built_in">number</span>;
  title: <span class="hljs-built_in">string</span>;
  completed: <span class="hljs-built_in">boolean</span>;
}
</code></pre>
<p>Let’s now write an interface for the TodoDatasource</p>
<pre><code class="lang-ts"><span class="hljs-comment">//Data/DataSource/TodoDataSource.ts</span>
<span class="hljs-keyword">import</span> { Todo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Domain/Model/Todo"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">interface</span> TodoDataSource {
  getTodos(): <span class="hljs-built_in">Promise</span>&lt;Todo[]&gt;;
}
</code></pre>
<p>We have enough to write an implementation of this interface and we’ll call it TodoAPIImpl:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { Todo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../../Domain/Model/Todo"</span>;
<span class="hljs-keyword">import</span> TodoDataSource <span class="hljs-keyword">from</span> <span class="hljs-string">"../TodoDataSource"</span>;
<span class="hljs-keyword">import</span> { TodoAPIEntity } <span class="hljs-keyword">from</span> <span class="hljs-string">"./Entity/TodoAPIEntity"</span>;

<span class="hljs-keyword">const</span> BASE_URL = <span class="hljs-string">"https://jsonplaceholder.typicode.com"</span>;

<span class="hljs-keyword">interface</span> TypedResponse&lt;T = any&gt; <span class="hljs-keyword">extends</span> Response {
  json&lt;P = T&gt;(): <span class="hljs-built_in">Promise</span>&lt;P&gt;;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myFetch</span>&lt;<span class="hljs-title">T</span>&gt;(<span class="hljs-params">...args: <span class="hljs-built_in">any</span></span>): <span class="hljs-title">Promise</span>&lt;<span class="hljs-title">TypedResponse</span>&lt;<span class="hljs-title">T</span>&gt;&gt; </span>{
  <span class="hljs-keyword">return</span> fetch.apply(<span class="hljs-built_in">window</span>, args);
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> TodoAPIDataSourceImpl <span class="hljs-keyword">implements</span> TodoDataSource {
  <span class="hljs-keyword">async</span> getTodos(): <span class="hljs-built_in">Promise</span>&lt;Todo[]&gt; {
    <span class="hljs-keyword">let</span> response = <span class="hljs-keyword">await</span> myFetch&lt;TodoAPIEntity[]&gt;(<span class="hljs-string">`<span class="hljs-subst">${BASE_URL}</span>/todos`</span>);
    <span class="hljs-keyword">let</span> data = <span class="hljs-keyword">await</span> response.json();
    <span class="hljs-keyword">return</span> data.map(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> ({
      id: item.id,
      title: item.title,
      isComplete: item.completed,
    }));
  }
}
</code></pre>
<p><strong>Note</strong>: this data source's getTodos function returns a list of Todo. So, we have to map TodoEntity -&gt; Todo:
Before we write our TodoRepositoryImpl let’s write the interface for that in the Domain layer</p>
<pre><code class="lang-ts"><span class="hljs-comment">//Domain/Repository/TodoRepository.ts</span>
<span class="hljs-keyword">import</span> { Todo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../Model/Todo"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> TodoRepository {
  getTodos(): <span class="hljs-built_in">Promise</span>&lt;Todo[]&gt;;
}
</code></pre>
<pre><code class="lang-ts"><span class="hljs-comment">//Data/Repository/TodoRepositoryImpl.ts</span>
<span class="hljs-keyword">import</span> { Todo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Domain/Model/Todo"</span>;
<span class="hljs-keyword">import</span> { TodoRepository } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../Domain/Repository/TodoRepository"</span>;
<span class="hljs-keyword">import</span> TodoDataSource <span class="hljs-keyword">from</span> <span class="hljs-string">"../DataSource/TodoDataSource"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> TodoRepositoryImpl <span class="hljs-keyword">implements</span> TodoRepository {
  dataSource: TodoDataSource;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">_datasource: TodoDataSource</span>) {
    <span class="hljs-built_in">this</span>.dataSource = _datasource;
  }

  <span class="hljs-keyword">async</span> getTodos(): <span class="hljs-built_in">Promise</span>&lt;Todo[]&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.dataSource.getTodos();
  }
}
</code></pre>
<p>Now that we have our todo repository, we can code up the GetTodos use case</p>
<pre><code class="lang-ts"><span class="hljs-comment">//Domain/UseCase/GetTodos.ts</span>
<span class="hljs-keyword">import</span> { Todo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../Model/Todo"</span>;
<span class="hljs-keyword">import</span> { TodoRepository } <span class="hljs-keyword">from</span> <span class="hljs-string">"../Repository/TodoRepository"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> GetTodos {
  invoke(): <span class="hljs-built_in">Promise</span>&lt;Todo[]&gt;;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> GetTodosUseCase <span class="hljs-keyword">implements</span> GetTodos {
  <span class="hljs-keyword">private</span> todoRepo: TodoRepository;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">_todoRepo: TodoRepository</span>) {
    <span class="hljs-built_in">this</span>.todoRepo = _todoRepo;
  }
  <span class="hljs-keyword">async</span> invoke(): <span class="hljs-built_in">Promise</span>&lt;Todo[]&gt; {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.todoRepo.getTodos();
  }
}
</code></pre>
<p>and then in turn we can write our presentation’s view model and view</p>
<pre><code class="lang-ts"><span class="hljs-comment">//Presentation/View/Todo/TodoListViewModel.ts</span>
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> TodoAPIDataSourceImpl <span class="hljs-keyword">from</span> <span class="hljs-string">"../../../Data/DataSource/API/TodoAPIDataSourceImpl"</span>;
<span class="hljs-keyword">import</span> { TodoRepositoryImpl } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../../Data/Repository/TodoRepositoryImpl"</span>;
<span class="hljs-keyword">import</span> { Todo } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../../Domain/Model/Todo"</span>;
<span class="hljs-keyword">import</span> { GetTodosUseCase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../../Domain/UseCase/GetTodos"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoViewModel</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [todos, setTodos] = useState&lt;Todo[]&gt;([]);

  <span class="hljs-keyword">const</span> UseCase = <span class="hljs-keyword">new</span> GetTodosUseCase(
    <span class="hljs-keyword">new</span> TodoRepositoryImpl(<span class="hljs-keyword">new</span> TodoAPIDataSourceImpl())
  );

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getTodos</span>(<span class="hljs-params"></span>) </span>{
    setTodos(<span class="hljs-keyword">await</span> UseCase.invoke());
  }

  <span class="hljs-keyword">return</span> {
    getTodos,
    todos,
  };
}
</code></pre>
<pre><code class="lang-ts"><span class="hljs-comment">//Presentation/Views/Todo/TodoListView.ts</span>
<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> useViewModel <span class="hljs-keyword">from</span> <span class="hljs-string">"./TodoListViewModel"</span>;
<span class="hljs-keyword">import</span> {
  List,
  ListItem,
  ListItemIcon,
  Checkbox,
  ListItemText,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@mui/material"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TodoView</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { getTodos, todos } = useViewModel();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    getTodos();
  }, []);

  <span class="hljs-keyword">return</span> (
    &lt;List&gt;
      {todos.map(<span class="hljs-function">(<span class="hljs-params">todo, i</span>) =&gt;</span> {
        <span class="hljs-keyword">return</span> (
          &lt;ListItem key={i}&gt;
            &lt;ListItemIcon&gt;
              &lt;Checkbox checked={todo.isComplete} /&gt;
            &lt;/ListItemIcon&gt;
            &lt;ListItemText primary={todo.title} /&gt;
          &lt;/ListItem&gt;
        );
      })}
    &lt;/List&gt;
  );
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635100111432/3R_P5Kw0U.png" alt="Screenshot 2021-10-24 at 20.27.00.png" /></p>
<p>So to recap:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635100729090/dIigJ7frA.png" alt="mermaid-diagram-20211024203818.png" /></p>
]]></content:encoded></item><item><title><![CDATA[Swift Dependency Injection with Swinject]]></title><description><![CDATA[As in most loosely coupled projects where we have big chains of dependencies.  Swinject  makes it simple and easy to do dependency injection. We’re going to use it in combination with the Swifts new property wrapper
Let’s say we have a 3 layer depend...]]></description><link>https://codefoundation.co.za/swift-dependency-injection-with-swinject</link><guid isPermaLink="true">https://codefoundation.co.za/swift-dependency-injection-with-swinject</guid><category><![CDATA[iOS]]></category><category><![CDATA[ios app development]]></category><category><![CDATA[Swift]]></category><category><![CDATA[dependency injection]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Thu, 21 Oct 2021 18:35:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634840962507/7F9phAjjz.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As in most loosely coupled projects where we have big chains of dependencies.  <a target="_blank" href="https://github.com/Swinject/Swinject">Swinject</a>  makes it simple and easy to do dependency injection. We’re going to use it in combination with the Swifts new property wrapper</p>
<p>Let’s say we have a 3 layer dependency:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634841087978/nY12llx6I.png" alt="1_DtFTj2qdMmgDfeGCyR_jCw.png" /></p>
<p>Of course, we can use good old manual dependency injection as follows:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoListViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{
    <span class="hljs-keyword">var</span> getTodosUseCase = <span class="hljs-type">GetTodosUseCase</span>(
        repo: <span class="hljs-type">TodoRepositoryImpl</span>(
            dataSource: <span class="hljs-type">TodoDataSourceImpl</span>()
        )
    )
....
}
</code></pre>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoListViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{
    @<span class="hljs-type">Inject</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> getTodosUseCase : <span class="hljs-type">GetTodos</span>
....
}
</code></pre>
<p>This would allow us to control the external dependencies by simply decorating the property with the Inject annotation and specifying the interface.</p>
<p>So the first thing is the @Inject annotation. In Swift, we use a property wrapper. Since Swift 5.1, the property wrapper feature enables us to attach logic directly to the property itself. Here we create a property wrapper called “Inject” that will automatically assign something to the prop</p>
<pre><code class="lang-swift"><span class="hljs-meta">@propertyWrapper</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Inject</span>&lt;<span class="hljs-title">I</span>&gt; </span>{
    <span class="hljs-keyword">let</span> wrappedValue: <span class="hljs-type">I</span>
    <span class="hljs-keyword">init</span>() {
        <span class="hljs-comment">//Resolve the interface to an implementation.</span>
        <span class="hljs-keyword">self</span>.wrappedValue = <span class="hljs-type">Resolver</span>.shared.resolve(<span class="hljs-type">I</span>.<span class="hljs-keyword">self</span>)
    }
}
</code></pre>
<p>Let’s build the resolver</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Resolver</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">let</span> shared = <span class="hljs-type">Resolver</span>()

    <span class="hljs-comment">//get the IOC container</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> container = buildContainer() 

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">resolve</span>&lt;T&gt;<span class="hljs-params">(<span class="hljs-number">_</span> type: T.<span class="hljs-keyword">Type</span>)</span></span> -&gt; <span class="hljs-type">T</span> {
        container.resolve(<span class="hljs-type">T</span>.<span class="hljs-keyword">self</span>)!
    }
}
</code></pre>
<p>All we now need is an IOC container. Let’s use Swinject to build one to resolve all interfaces to their respective implementations:</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Swinject
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">buildContainer</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">Container</span> {
    <span class="hljs-keyword">let</span> container = <span class="hljs-type">Container</span>()
    container.register(<span class="hljs-type">GetTodos</span>.<span class="hljs-keyword">self</span>) { <span class="hljs-number">_</span>  <span class="hljs-keyword">in</span>
        <span class="hljs-keyword">return</span> <span class="hljs-type">GetTodosUseCase</span>()
    }.inObjectScope(.container)
    container.register(<span class="hljs-type">TodoDataSource</span>.<span class="hljs-keyword">self</span>) { <span class="hljs-number">_</span>  <span class="hljs-keyword">in</span>
        <span class="hljs-keyword">return</span> <span class="hljs-type">TodoMockDataSourceImpl</span>()
    }.inObjectScope(.container)
    container.register(<span class="hljs-type">TodoRepository</span>.<span class="hljs-keyword">self</span>) { <span class="hljs-number">_</span>  <span class="hljs-keyword">in</span>
        <span class="hljs-keyword">return</span> <span class="hljs-type">TodoRepositoryImpl</span>()
    }.inObjectScope(.container)
    <span class="hljs-keyword">return</span> container
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[SwiftUI 5.5 API Data to List View]]></title><description><![CDATA[Many times we need to make API calls to fetch data to display in a list. Here, I show how to do that with SwiftUI. To illustrate the structure of the application, let’s look at the following diagram:

The Todo APIService
We need to create an API serv...]]></description><link>https://codefoundation.co.za/swiftui-5-5-api-data-to-list-view-776c69a456d3</link><guid isPermaLink="true">https://codefoundation.co.za/swiftui-5-5-api-data-to-list-view-776c69a456d3</guid><category><![CDATA[iOS]]></category><category><![CDATA[Swift]]></category><category><![CDATA[APIs]]></category><category><![CDATA[ios app development]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Wed, 13 Oct 2021 13:47:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162210218/lMwAS6yEZ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Many times we need to make API calls to fetch data to display in a list. Here, I show how to do that with SwiftUI. To illustrate the structure of the application, let’s look at the following diagram:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162205482/SZMMXPeC9.png" alt /></p>
<h2 id="the-todo-apiservice">The Todo APIService</h2>
<p>We need to create an API service to send the network requests. We will use URLSession. Here we have one method to fetch all todo item and deserialise them to [TodoItem]</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoItem</span>: <span class="hljs-title">Identifiable</span>, <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> title: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> completed: <span class="hljs-type">Bool</span>
}

<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">APIError</span>: <span class="hljs-title">Error</span></span>{
    <span class="hljs-keyword">case</span> invalidUrl, requestError, decodingError, statusNotOk
}

<span class="hljs-keyword">let</span> <span class="hljs-type">BASE_URL</span>: <span class="hljs-type">String</span> = <span class="hljs-string">"https://jsonplaceholder.typicode.com"</span>

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

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">TodoItem</span>] {

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string:  <span class="hljs-string">"\(BASE_URL)/todos"</span>) <span class="hljs-keyword">else</span>{
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIError</span>.invalidUrl
        }

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> (data, response) = <span class="hljs-keyword">try</span>? await <span class="hljs-type">URLSession</span>.shared.data(from: url) <span class="hljs-keyword">else</span>{
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIError</span>.requestError
        }

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> response = response <span class="hljs-keyword">as</span>? <span class="hljs-type">HTTPURLResponse</span>, response.statusCode == <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>{
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIError</span>.statusNotOk
        }

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> result = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSONDecoder</span>().decode([<span class="hljs-type">TodoItem</span>].<span class="hljs-keyword">self</span>, from: data) <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIError</span>.decodingError
        }

        <span class="hljs-keyword">return</span> result
    }

}
</code></pre>
<h2 id="the-todo-viewmodel">The Todo ViewModel</h2>
<p>The view model in turn uses the API Service to fetch todos to then publish</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

@<span class="hljs-type">MainActor</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> todos: [<span class="hljs-type">TodoItem</span>] = []
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> errorMessage = <span class="hljs-string">""</span>
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> hasError = <span class="hljs-literal">false</span>


    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async {
        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> data = <span class="hljs-keyword">try</span>?  await  <span class="hljs-type">APIService</span>().getTodos() <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">self</span>.todos = []
            <span class="hljs-keyword">self</span>.hasError = <span class="hljs-literal">true</span>
            <span class="hljs-keyword">self</span>.errorMessage  = <span class="hljs-string">"Server Error"</span>
            <span class="hljs-keyword">return</span>
        }

        <span class="hljs-keyword">self</span>.todos = data

    }
}
</code></pre>
<h2 id="the-todo-view">The Todo View</h2>
<p>Finally we have the view which watches the ViewModel for any todo list state changes. The todo list is display in the view. On list appear the view makes the api call.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoList</span>: <span class="hljs-title">View</span> </span>{
    @<span class="hljs-type">StateObject</span> <span class="hljs-keyword">var</span> vm = <span class="hljs-type">TodoViewModel</span>()

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">List</span>{
            <span class="hljs-type">ForEach</span>(vm.todos){todo <span class="hljs-keyword">in</span>
                <span class="hljs-type">HStack</span>{
                    <span class="hljs-type">Image</span>(systemName: todo.completed ? <span class="hljs-string">"checkmark.circle"</span>: <span class="hljs-string">"circle"</span>)
                        .foregroundColor(todo.completed ? .green : .red)
                    <span class="hljs-type">Text</span>(<span class="hljs-string">"\(todo.title)"</span>)
                }
            }
        }
        .task {
            await vm.getTodos()
        }
        .listStyle(<span class="hljs-type">PlainListStyle</span>())
        .navigationTitle(<span class="hljs-string">"Todos"</span>)

    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162208402/ZWdOiyw6B.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Clean Architecture in Jetpack Compose]]></title><description><![CDATA[By employing clean architecture, you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It a...]]></description><link>https://codefoundation.co.za/clean-architecture-in-the-flavour-of-jetpack-compose-dd4b0016f815</link><guid isPermaLink="true">https://codefoundation.co.za/clean-architecture-in-the-flavour-of-jetpack-compose-dd4b0016f815</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Wed, 13 Oct 2021 11:47:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162202209/zL1ziHdj9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>By employing <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">clean architecture</a>, you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It also becomes intrinsically testable. Here I’ll show how I structure my clean architecture projects. This time we are going to build an Android todo application using Jetpack Compose. We’ll only illustrate one use case of listing todos retrieved from an API. Let’s get started.</p>
<p>The package structure of the project takes on the following form:</p>
<pre><code>├── Core
├── Data
├── <span class="hljs-keyword">Domain</span>
└── Presentation
</code></pre><p>Let’s start with the <strong>Domain</strong> Layer.</p>
<p>This layer describes <strong>WHAT</strong> your project/application does. Let me explain, Many applications are built and structured in a way that you cannot understand what the application does just by looking at the folder structure. Using a building of a house analogy, you can quickly identify what a building would look like and its functionality by viewing the floor plan and elevation of the building</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162197103/c6FGyQJJi.png" alt /></p>
<p>In the same way, the domain layer of our project should specify and describe <strong>WHAT</strong> our application does. In this folder, we would keep use models, repository interfaces, and use cases.</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Data</span>
├── <span class="hljs-selector-tag">Presentation</span>
└── <span class="hljs-selector-tag">Domain</span>
    ├── <span class="hljs-selector-tag">Model</span>
    │   ├── <span class="hljs-selector-tag">Todo</span><span class="hljs-selector-class">.kt</span>
    │   └── <span class="hljs-selector-tag">User</span><span class="hljs-selector-class">.kt</span>
    ├── <span class="hljs-selector-tag">Repository</span>
    │   ├── <span class="hljs-selector-tag">TodoRepository</span><span class="hljs-selector-class">.kt</span>
    │   └── <span class="hljs-selector-tag">UserRepository</span><span class="hljs-selector-class">.kt</span>
    └── <span class="hljs-selector-tag">UseCase</span>
        ├── <span class="hljs-selector-tag">Todo</span>
        │   ├── <span class="hljs-selector-tag">GetTodos</span><span class="hljs-selector-class">.kt</span>
        │   ├── <span class="hljs-selector-tag">GetTodo</span><span class="hljs-selector-class">.kt</span>
        │   ├── <span class="hljs-selector-tag">DeleteTodo</span><span class="hljs-selector-class">.kt</span>
        │   ├── <span class="hljs-selector-tag">UpdateTodo</span><span class="hljs-selector-class">.kt</span>
        │   └── <span class="hljs-selector-tag">CreateTodo</span><span class="hljs-selector-class">.kt</span>
        └── <span class="hljs-selector-tag">User</span>
            ├── <span class="hljs-selector-tag">GetUsers</span><span class="hljs-selector-class">.kt</span>
            ├── <span class="hljs-selector-tag">GetUser</span><span class="hljs-selector-class">.kt</span>
            ├── <span class="hljs-selector-tag">DeleteUser</span><span class="hljs-selector-class">.kt</span>
            ├── <span class="hljs-selector-tag">UpdateUser</span><span class="hljs-selector-class">.kt</span>
            └── <span class="hljs-selector-tag">CreateUser</span><span class="hljs-selector-class">.kt</span>
</code></pre><ol>
<li><p><strong>Model</strong>: A model typically represents a real-world object that is related to the problem. In this folder, we would typically keep classes to represent objects. e.g. Todo, User, etc</p>
</li>
<li><p><strong>Repository</strong>: Container for all repository interfaces. The repository is a central place to keep all model-specific operations. In this case, the Todo repository interface would describe repository methods. The actual repository implementation will be kept in the <strong>Data</strong> layer.</p>
</li>
<li><p><strong>UseCases: </strong>Container to list all functionality of our application. e.g <em>Get, Delete, Create , Update</em></p>
</li>
</ol>
<p>The <strong>PRESENTATION</strong> layer will keep all of the consumer-related code as to <strong>HOW</strong> the application will interact with the outside world. The presentation layer can be WebForms, Command Line Interface, API Endpoints, etc. In this case, it would be the screens for a List of Todos and its accompanying view model.</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Data</span>
├── <span class="hljs-selector-tag">Domain</span>
└── <span class="hljs-selector-tag">Presentation</span>
    └── <span class="hljs-selector-tag">Todo</span>
        └── <span class="hljs-selector-tag">TodoList</span>
            ├── <span class="hljs-selector-tag">TodoListViewModel</span><span class="hljs-selector-class">.kt</span>
            └── <span class="hljs-selector-tag">TodoListView</span><span class="hljs-selector-class">.kt</span>
</code></pre><p>The<strong> DATA</strong> layer will keep all the external dependency-related code as to <strong>HOW </strong>they are implemented:</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Domain</span>
├── <span class="hljs-selector-tag">Presentation</span>
├── <span class="hljs-selector-tag">Data</span>
    ├── <span class="hljs-selector-tag">Repository</span>
    │   ├── <span class="hljs-selector-tag">TodoRepositoryImpl</span><span class="hljs-selector-class">.kt</span>
    │   ├── <span class="hljs-selector-tag">TodoAPIDataSourceImpl</span><span class="hljs-selector-class">.kt</span>
    │   └── <span class="hljs-selector-tag">TodoDBDataSourceImpl</span><span class="hljs-selector-class">.kt</span>
    └── <span class="hljs-selector-tag">DataSource</span>
        ├── <span class="hljs-selector-tag">API</span>
        │   ├── <span class="hljs-selector-tag">TodoAPIDataSource</span><span class="hljs-selector-class">.kt</span>.
        │   └── <span class="hljs-selector-tag">Entity</span>
        │       ├── <span class="hljs-selector-tag">TodoAPIEntity</span><span class="hljs-selector-class">.kt</span>
        │       └── <span class="hljs-selector-tag">UserAPIEntity</span><span class="hljs-selector-class">.kt</span>
        └── <span class="hljs-selector-tag">DB</span>
            ├── <span class="hljs-selector-tag">TodoDBDataSource</span><span class="hljs-selector-class">.kt</span>.
            └── <span class="hljs-selector-tag">Entity</span>
                ├── <span class="hljs-selector-tag">TodoDBEntity</span><span class="hljs-selector-class">.kt</span>
                └── <span class="hljs-selector-tag">UserDBEntity</span><span class="hljs-selector-class">.kt</span>
</code></pre><ol>
<li><p><strong>Repository</strong>: Repository implementations</p>
</li>
<li><p><strong>DataSource</strong>: All data source <strong>interfaces</strong> and <strong>entities</strong>. An entity represents a single instance of your domain object saved into the database as a record. It has some attributes that we represent as columns in our DB tables or API endpoints. We can’t control how data is modeled on the external data source, so these entities are required to be mapped from entities to domain models in the implementations</p>
</li>
</ol>
<p>and lastly, the <strong>CORE </strong>layer keep all the components that are common across all layers like constants or configs or dependency injection (which we won’t cover)</p>
<p>Our first task would be always to start with the domain models and data entities</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Todo</span></span>(
    <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Int</span>,
    <span class="hljs-keyword">val</span> isCompleted: <span class="hljs-built_in">Boolean</span>,
    <span class="hljs-keyword">val</span> task: String

)
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoAPIEntity</span></span>(
    <span class="hljs-keyword">val</span> id: <span class="hljs-built_in">Int</span>,
    <span class="hljs-keyword">val</span> completed: <span class="hljs-built_in">Boolean</span>,
    <span class="hljs-keyword">val</span> title: String
)

<span class="hljs-function"><span class="hljs-keyword">fun</span> TodoAPIEntity.<span class="hljs-title">toTodo</span><span class="hljs-params">()</span></span>: Todo {
    <span class="hljs-keyword">return</span> Todo(
        id = id,
        isCompleted = completed,
        task = title
    )
}
</code></pre>
<p>Let’s now write an interface for the TodoDatasource. We need one to enforce how any data source (API, DB, etc) needs to behave.</p>
<pre><code>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TodoDataSource</span> </span>{    
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt;
}
</code></pre><p>We have enough to write an implementation of this interface and we’ll call it TodoAPIImpl:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> toTodo
<span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Data.DataSource.TodoAPI
<span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Data.DataSource.TodoDataSource
<span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Domain.Model.Todo


<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TodoApi</span> </span>{

    <span class="hljs-meta">@GET(<span class="hljs-meta-string">"todos"</span>)</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>: List&lt;TodoAPIEntity&gt;

    <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> {
        <span class="hljs-keyword">var</span> todoApi: TodoApi? = <span class="hljs-literal">null</span>
        <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>: TodoApi {
            <span class="hljs-keyword">if</span> (todoApi == <span class="hljs-literal">null</span>) {
                todoApi = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build().create(TodoApi::<span class="hljs-keyword">class</span>.java)
            }
            <span class="hljs-keyword">return</span> todoApi!!
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoAPIImpl</span> : <span class="hljs-type">TodoDataSource {</span></span>

    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt; {
        <span class="hljs-keyword">return</span> TodoAPI.getInstance().getTodos().map { it.toTodo() }
    }
}
</code></pre>
<p><strong>Note:</strong> this repository’s getTodos function returns a list of Todo. So, we have to map TodoAPIEntity -&gt; Todo:</p>
<p>Before we write our TodoRepositoryImpl let’s write the interface for that in the Domain layer</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Domain.Model.Todo

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">TodoRepository</span> </span>{
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt;

}
</code></pre>
<p>We can now see that the TodoRepositoryImpl can take any datasource as a dependency, great for swapping out datasources.</p>
<p>Now that we have our todo repository, we can code up the GetTodos use case</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Domain.Model.Todo
<span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Domain.Repository.TodoRepository

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GetTodos</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> repository: TodoRepository
) {
    <span class="hljs-keyword">suspend</span> <span class="hljs-keyword">operator</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">invoke</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt; {
        <span class="hljs-keyword">return</span> repository.getTodos()
    }
}
</code></pre>
<p>and then in turn we can write our presentation’s view model and view</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> androidx.compose.runtime.mutableStateListOf
<span class="hljs-keyword">import</span> androidx.lifecycle.ViewModel
<span class="hljs-keyword">import</span> androidx.lifecycle.viewModelScope
<span class="hljs-keyword">import</span> kotlinx.coroutines.launch
<span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Domain.Model.Todo
<span class="hljs-keyword">import</span> za.co.nanosoft.cleantodo.Domain.UseCase.GetTodos

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span> <span class="hljs-keyword">constructor</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> getTodosUseCase: GetTodos
) : ViewModel() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _todos = mutableStateListOf&lt;Todo&gt;()

    <span class="hljs-keyword">val</span> todos: List&lt;Todo&gt;
        <span class="hljs-keyword">get</span>() = _todos


    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> {
        viewModelScope.launch {
            _todos.addAll(getTodosUseCase())
        }
    }
}
</code></pre>
<pre><code class="lang-kotlin">
<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">TodoListView</span><span class="hljs-params">(vm: <span class="hljs-type">TodoViewModel</span>)</span></span> {

    LaunchedEffect(<span class="hljs-built_in">Unit</span>, block = {
        vm.getTodos()
    })

    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text(<span class="hljs-string">"Todos"</span>)
                }
            )
        },
        content = {
            Column(modifier = Modifier.padding(<span class="hljs-number">16</span>.dp)) {
                LazyColumn(modifier = Modifier.fillMaxHeight()) {
                    items(vm.todos) { todo -&gt;
                        Row(modifier = Modifier.padding(<span class="hljs-number">16</span>.dp)) {
                            Checkbox(checked = todo.isCompleted, onCheckedChange = <span class="hljs-literal">null</span>)
                            Spacer(Modifier.width(<span class="hljs-number">5</span>.dp))
                            Text(todo.task)
                        }
                        Divider()
                    }
                }
            }
        }
    )
}
</code></pre>
<p>So to recap:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162198715/9DSCo9-A_.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162200449/Ythc_BSPW.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Clean Architecture in SwiftUI 5.5]]></title><description><![CDATA[By employing  clean architecture , you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It...]]></description><link>https://codefoundation.co.za/clean-architecture-in-swiftui-55</link><guid isPermaLink="true">https://codefoundation.co.za/clean-architecture-in-swiftui-55</guid><category><![CDATA[iOS]]></category><category><![CDATA[ios app development]]></category><category><![CDATA[Swift]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Tue, 12 Oct 2021 21:52:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634074947925/JMJI1WBzf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>By employing  <a target="_blank" href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html">clean architecture</a> , you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It also becomes intrinsically testable. Here I’ll show how I structure my clean architecture projects. This time we are going to build an iOS todo application using SwiftUI. We’ll only illustrate one use case of listing todos retrieved from an API. Let’s get started.</p>
<p>The folder/group structure of the project takes on the following form:</p>
<pre><code>├── Core
├── Data
├── <span class="hljs-keyword">Domain</span>
└── Presentation
</code></pre><p>Let’s start with the <strong>Domain</strong> Layer.
This layer describes <strong>WHAT</strong> your project/application does. Let me explain, Many applications are built and structured in a way that you cannot understand what the application does just by looking at the folder structure. Using a building of a house analogy, you can quickly identify what a building would look like and its functionality by viewing the floor plan and elevation of the building</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634800233899/Ww3pX9pJO.png" alt="1_GfMGNsEj814uSiYw1Vq23w (1).png" /></p>
<p>In the same way, the domain layer of our project should specify and describe WHAT our application does. In this folder, we would keep use models, repository interfaces, and use cases.</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Data</span>
├── <span class="hljs-selector-tag">Presentation</span>
└── <span class="hljs-selector-tag">Domain</span>
    ├── <span class="hljs-selector-tag">Model</span>
    │   ├── <span class="hljs-selector-tag">Todo</span><span class="hljs-selector-class">.swift</span>
    │   └── <span class="hljs-selector-tag">User</span><span class="hljs-selector-class">.swift</span>
    ├── <span class="hljs-selector-tag">Repository</span>
    │   ├── <span class="hljs-selector-tag">TodoRepository</span><span class="hljs-selector-class">.swift</span>
    │   └── <span class="hljs-selector-tag">UserRepository</span><span class="hljs-selector-class">.swift</span>
    └── <span class="hljs-selector-tag">UseCase</span>
        ├── <span class="hljs-selector-tag">Todo</span>
        │   ├── <span class="hljs-selector-tag">GetTodos</span><span class="hljs-selector-class">.swift</span>
        │   ├── <span class="hljs-selector-tag">GetTodo</span><span class="hljs-selector-class">.swift</span>
        │   ├── <span class="hljs-selector-tag">DeleteTodo</span><span class="hljs-selector-class">.swift</span>
        │   ├── <span class="hljs-selector-tag">UpdateTodo</span><span class="hljs-selector-class">.swift</span>
        │   └── <span class="hljs-selector-tag">CreateTodo</span><span class="hljs-selector-class">.swift</span>
        └── <span class="hljs-selector-tag">User</span>
            ├── <span class="hljs-selector-tag">GetUsers</span><span class="hljs-selector-class">.swift</span>
            ├── <span class="hljs-selector-tag">GetUser</span><span class="hljs-selector-class">.swift</span>
            ├── <span class="hljs-selector-tag">DeleteUser</span><span class="hljs-selector-class">.swift</span>
            ├── <span class="hljs-selector-tag">UpdateUser</span><span class="hljs-selector-class">.swift</span>
            └── <span class="hljs-selector-tag">CreateUser</span><span class="hljs-selector-class">.swift</span>
</code></pre><ol>
<li><strong>Model</strong>: A model typically represents a real-world object that is related to the problem. In this folder, we would typically keep classes to represent objects. e.g. Todo, User, Product, etc</li>
<li><strong>Repository</strong>: Container for all repository interfaces. The repository is a central place to keep all model-specific operations. In this case, the Todo repository interface would describe repository methods. The actual repository implementation will be kept in the Data layer.</li>
<li><strong>UseCases</strong>: Container to list all functionality of our application. e.g Get Todos, Delete Todo, Create Todo, Update Todo</li>
</ol>
<p>The <strong>PRESENTATION</strong> layer will keep all of the consumer-related code as to <strong>HOW</strong> the application will interact with the outside world. The presentation layer can be WebForms, Command Line Interface, API Endpoints, etc. In this case, it would be the screens for a List of Todos and its accompanying view model.</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Data</span>
├── <span class="hljs-selector-tag">Domain</span>
└── <span class="hljs-selector-tag">Presentation</span>
    └── <span class="hljs-selector-tag">Todo</span>
        └── <span class="hljs-selector-tag">TodoList</span>
            ├── <span class="hljs-selector-tag">TodoListViewModel</span><span class="hljs-selector-class">.swift</span>
            └── <span class="hljs-selector-tag">TodoListView</span><span class="hljs-selector-class">.swift</span>
</code></pre><p>The <strong>DATA</strong> layer will keep all the external dependency-related code as to HOW they are implemented:</p>
<pre><code>├── <span class="hljs-selector-tag">Core</span>
├── <span class="hljs-selector-tag">Domain</span>
├── <span class="hljs-selector-tag">Presentation</span>
└── <span class="hljs-selector-tag">Data</span>
    ├── <span class="hljs-selector-tag">Repository</span>
    │   ├── <span class="hljs-selector-tag">TodoRepositoryImpl</span><span class="hljs-selector-class">.swift</span>
    └── <span class="hljs-selector-tag">DataSource</span>
        ├── <span class="hljs-selector-tag">TodoDataSource</span><span class="hljs-selector-class">.swift</span>
        ├── <span class="hljs-selector-tag">API</span>
        │   ├── <span class="hljs-selector-tag">TodoAPIDataSourceImpl</span><span class="hljs-selector-class">.swift</span>
        │   └── <span class="hljs-selector-tag">Entity</span>
        │       ├── <span class="hljs-selector-tag">TodoAPIEntity</span><span class="hljs-selector-class">.swift</span>
        │       └── <span class="hljs-selector-tag">UserAPIEntity</span><span class="hljs-selector-class">.swift</span>
        └── <span class="hljs-selector-tag">DB</span>
            ├── <span class="hljs-selector-tag">TodoDBDataSourceImpl</span><span class="hljs-selector-class">.swift</span>
            └── <span class="hljs-selector-tag">Entity</span>
                ├── <span class="hljs-selector-tag">TodoDBEntity</span><span class="hljs-selector-class">.swift</span>
                └── <span class="hljs-selector-tag">UserDBEntity</span><span class="hljs-selector-class">.swift</span>
</code></pre><ol>
<li><strong>Repository</strong>: Repository implementations</li>
<li><strong>DataSource</strong>: All data source <strong>interfaces</strong> and <strong>entities</strong>. An entity represents a single instance of your domain object saved into the database as a record. It has some attributes that we represent as columns in our DB tables or API endpoints. We can’t control how data is modelled on the external data source, so these entities are required to be mapped from entities to domain models in the implementations</li>
</ol>
<p>and lastly, the <strong>CORE</strong> layer keep all the components that are common across all layers like constants or configs or dependency injection (which we won’t cover)
Our first task would be always to start with the domain models and data entities. Let’s start with the model</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Todo</span>: <span class="hljs-title">Identifiable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> title: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> isCompleted: <span class="hljs-type">Bool</span>
}
</code></pre>
<p>We need it to conform to Identifiable as we’re going to display these items in a list view.
Next let’s do the todo entity</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoAPIEntity</span>: <span class="hljs-title">Codable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">Int</span>
    <span class="hljs-keyword">let</span> title: <span class="hljs-type">String</span>
    <span class="hljs-keyword">let</span> completed: <span class="hljs-type">Bool</span>
}
</code></pre>
<p>Let’s now write an interface (protocol) for the TodoDatasource</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">TodoDataSource</span></span>{   
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">Todo</span>]   
}
</code></pre>
<p>We have enough to write an implementation of this protocol and we’ll call it TodoAPIDataSourceImpl:</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">APIServiceError</span>: <span class="hljs-title">Error</span></span>{
    <span class="hljs-keyword">case</span> badUrl, requestError, decodingError, statusNotOK
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoAPIDataSourceImpl</span>: <span class="hljs-title">TodoDataSource</span></span>{


    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">Todo</span>] {

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> url = <span class="hljs-type">URL</span>(string:  <span class="hljs-string">"\(Constants.BASE_URL)/todos"</span>) <span class="hljs-keyword">else</span>{
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIServiceError</span>.badUrl
        }

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> (data, response) = <span class="hljs-keyword">try</span>? await <span class="hljs-type">URLSession</span>.shared.data(from: url) <span class="hljs-keyword">else</span>{
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIServiceError</span>.requestError
        }

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> response = response <span class="hljs-keyword">as</span>? <span class="hljs-type">HTTPURLResponse</span>, response.statusCode == <span class="hljs-number">200</span> <span class="hljs-keyword">else</span>{
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIServiceError</span>.statusNotOK
        }

        <span class="hljs-keyword">guard</span> <span class="hljs-keyword">let</span> result = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSONDecoder</span>().decode([<span class="hljs-type">TodoAPIEntity</span>].<span class="hljs-keyword">self</span>, from: data) <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">throw</span> <span class="hljs-type">APIServiceError</span>.decodingError
        }

        <span class="hljs-keyword">return</span> result.<span class="hljs-built_in">map</span>({ item <span class="hljs-keyword">in</span>
            <span class="hljs-type">Todo</span>(
                id: item.id,
                title: item.title,
                isCompleted: item.completed
            )
        })
    }
}
</code></pre>
<p><strong>Note</strong>: this repository’s getTodos function returns a list of Todo. So, we have to map TodoEntity -&gt; Todo:
Before we write our TodoRepositoryImpl let’s write the protocol for that in the Domain layer</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">protocol</span> <span class="hljs-title">TodoRepository</span></span>{   
    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">Todo</span>]   
}
</code></pre>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoRepositoryImpl</span>: <span class="hljs-title">TodoRepository</span></span>{

    <span class="hljs-keyword">var</span> dataSource: <span class="hljs-type">TodoDataSource</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async <span class="hljs-keyword">throws</span> -&gt; [<span class="hljs-type">Todo</span>] {
        <span class="hljs-keyword">let</span> _todos =  <span class="hljs-keyword">try</span> await dataSource.getTodos()
        <span class="hljs-keyword">return</span> _todos
    }
}
</code></pre>
<p>Now that we have our todo repository, we can code up the GetTodos use case</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">UseCaseError</span>: <span class="hljs-title">Error</span></span>{
    <span class="hljs-keyword">case</span> networkError, decodingError
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">GetTodosUseCase</span></span>{
    <span class="hljs-keyword">var</span> repo: <span class="hljs-type">TodoRepository</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">Todo</span>], <span class="hljs-type">UseCaseError</span>&gt;{
        <span class="hljs-keyword">do</span>{
            <span class="hljs-keyword">let</span> todos = <span class="hljs-keyword">try</span> await repo.getTodos()
            <span class="hljs-keyword">return</span> .success(todos)
        }<span class="hljs-keyword">catch</span>(<span class="hljs-keyword">let</span> error){
            <span class="hljs-keyword">switch</span>(error){
            <span class="hljs-keyword">case</span> <span class="hljs-type">APIServiceError</span>.decodingError:
                <span class="hljs-keyword">return</span> .failure(.decodingError)
            <span class="hljs-keyword">default</span>:
                <span class="hljs-keyword">return</span> .failure(.networkError)
            }
        }
    }
}
</code></pre>
<p>and then in turn we can write our presentation’s view model and view</p>
<pre><code class="lang-swift">@<span class="hljs-type">MainActor</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoListViewModel</span>: <span class="hljs-title">ObservableObject</span> </span>{

    <span class="hljs-keyword">var</span> getTodosUseCase = <span class="hljs-type">GetTodosUseCase</span>(repo: <span class="hljs-type">TodoRepositoryImpl</span>(dataSource: <span class="hljs-type">TodoAPISourceImpl</span>()))
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> todos: [<span class="hljs-type">Todo</span>] = []
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> errorMessage = <span class="hljs-string">""</span>
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">var</span> hasError = <span class="hljs-literal">false</span>

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span> async {
        errorMessage = <span class="hljs-string">""</span>
        <span class="hljs-keyword">let</span> result = await getTodosUseCase.execute()
        <span class="hljs-keyword">switch</span> result{
        <span class="hljs-keyword">case</span> .success(<span class="hljs-keyword">let</span> todos):
            <span class="hljs-keyword">self</span>.todos = todos
        <span class="hljs-keyword">case</span> .failure(<span class="hljs-keyword">let</span> error):
            <span class="hljs-keyword">self</span>.todos = []
            errorMessage = error.localizedDescription
            hasError = <span class="hljs-literal">true</span>
        }
    }
}
</code></pre>
<p>Note: We use the @MainActor attribute for the view model class because we need to run these functions on the main thread, a singleton actor whose executor is equivalent to the main dispatch queue.</p>
<pre><code class="lang-swift">
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoListView</span>: <span class="hljs-title">View</span> </span>{
    @<span class="hljs-type">StateObject</span> <span class="hljs-keyword">var</span> vm = <span class="hljs-type">TodoListViewModel</span>()


    <span class="hljs-keyword">fileprivate</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">listRow</span><span class="hljs-params">(<span class="hljs-number">_</span> todo: Todo)</span></span> -&gt; some <span class="hljs-type">View</span> {
        <span class="hljs-type">HStack</span>{
            <span class="hljs-type">Image</span>(systemName: todo.isCompleted ? <span class="hljs-string">"checkmark.circle"</span>: <span class="hljs-string">"circle"</span>)
                .foregroundColor(todo.isCompleted ? .green : .red)
            <span class="hljs-type">Text</span>(<span class="hljs-string">"\(todo.title)"</span>)
        }
    }

    <span class="hljs-keyword">fileprivate</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TodoList</span><span class="hljs-params">()</span></span> -&gt; some <span class="hljs-type">View</span> {
        <span class="hljs-type">List</span> {
            <span class="hljs-type">ForEach</span>(vm.todos){ item <span class="hljs-keyword">in</span>
                listRow(item)
            }
        }
        .navigationTitle(<span class="hljs-string">"Todo List"</span>)
        .task {
           await vm.getTodos()
        }
        .alert(<span class="hljs-string">"Error"</span>, isPresented: $vm.hasError) {
        } message: {
            <span class="hljs-type">Text</span>(vm.errorMessage)
        }
    }

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
       <span class="hljs-type">TodoList</span>()
    }
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">TodoListView_Previews</span>: <span class="hljs-title">PreviewProvider</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">var</span> previews: some <span class="hljs-type">View</span> {
        <span class="hljs-type">NavigationView</span>{
        <span class="hljs-type">TodoListView</span>()
        }.navigationViewStyle(<span class="hljs-type">StackNavigationViewStyle</span>())
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634075436448/ywFcnL_Fn.png" alt="1_RPODyu_j2ViIWwGORfWI6g.png" /></p>
<p>So to recap:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1634075461623/W6SErnIQ9.png" alt="1_h1uKBx_PteJ96-aV9Zog1w.png" /></p>
]]></content:encoded></item><item><title><![CDATA[SwiftUI MVVM]]></title><description><![CDATA[Model–View–ViewModel (MVVM) is a software architectural pattern that facilitates the separation of the development of the GUI (the view) from the development of the business logic or back-end logic (the model) so that the view is not dependent on any...]]></description><link>https://codefoundation.co.za/swiftui-mvvm</link><guid isPermaLink="true">https://codefoundation.co.za/swiftui-mvvm</guid><category><![CDATA[iOS]]></category><category><![CDATA[ios app development]]></category><category><![CDATA[Swift]]></category><category><![CDATA[MVVM]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Thu, 07 Oct 2021 11:59:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633607578599/tQEipMG7o.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Model–View–ViewModel (MVVM) is a software architectural pattern that facilitates the separation of the development of the GUI (the view) from the development of the business logic or back-end logic (the model) so that the view is not dependent on any specific model platform. The ViewModel of MVVM is responsible for exposing the data objects from the model in such a way that objects are easily managed and presented. In this respect, the ViewModel is more model than view and handles most if not all of the view’s display logic. The ViewModel may implement a mediator pattern, organizing access to the back-end logic around the set of use cases supported by the view.
I’ve put together a small sample showing these 3 layers and how they relate to each other in SwiftUI. You’ll notice that other than property/method names, none of the objects need to know anything about the others. Each layer can be built completely independent of the others.</p>
<h3 id="sample-model">Sample Model</h3>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">User</span>: <span class="hljs-title">Identifiable</span> </span>{
    <span class="hljs-keyword">let</span> id: <span class="hljs-type">UUID</span>
    <span class="hljs-keyword">let</span> name: <span class="hljs-type">String</span>
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">UserModel</span></span>{
    <span class="hljs-keyword">private</span>(<span class="hljs-keyword">set</span>) <span class="hljs-keyword">var</span> users :[<span class="hljs-type">User</span>] = []

    <span class="hljs-keyword">mutating</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addUser</span><span class="hljs-params">(<span class="hljs-number">_</span> user: User)</span></span>{
        users.append(user)
    }
}
</code></pre>
<p>We define a User model.
The model has 2 members, a privately changeable users list and a mutating function to change the state of the user's collection.
Note the User struct conforms to the Identifiable protocol. SwiftUI needs to know how it can identify each item uniquely otherwise it’s not able to compare view hierarchies to figure out what has changed when a new body is re-built in the view.</p>
<h3 id="sample-viewmodel">Sample ViewModel</h3>
<p>This should contain everything one would need to interact with the view. Right now it contains 2 members: users, and an addUser function.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> Foundation
<span class="hljs-keyword">import</span> UIKit


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserViewModel</span>: <span class="hljs-title">ObservableObject</span></span>{
    @<span class="hljs-type">Published</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> userModel =  <span class="hljs-type">UserModel</span>()

    <span class="hljs-keyword">var</span> users: [<span class="hljs-type">User</span>] {
        <span class="hljs-keyword">return</span> userModel.users
    }

    <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">addUser</span><span class="hljs-params">(<span class="hljs-number">_</span> user: User)</span></span>{
        userModel.addUser(user)
    }
}
</code></pre>
<h3 id="sample-view">Sample View</h3>
<p>And now the View. These are DataTemplates that define how data should be displayed.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">UserView</span>: <span class="hljs-title">View</span> </span>{
   @<span class="hljs-type">ObservedObject</span> <span class="hljs-keyword">var</span> viewModel = <span class="hljs-type">UserViewModel</span>()

    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">NavigationView</span>{
            <span class="hljs-type">List</span>(viewModel.users) { user <span class="hljs-keyword">in</span>
                <span class="hljs-type">VStack</span>(alignment: .leading){
                    <span class="hljs-type">Text</span>(<span class="hljs-string">"\(user.name)"</span>)
                    <span class="hljs-type">Text</span>(<span class="hljs-string">"\(user.id)"</span>)
                }
            }
            .navigationTitle(<span class="hljs-string">"Users"</span>)
            .toolbar {
                <span class="hljs-type">Button</span>(action: {
                    viewModel.addUser(<span class="hljs-type">User</span>(id: <span class="hljs-type">UUID</span>(),name: <span class="hljs-string">"User"</span>))
                }) {
                    <span class="hljs-type">Image</span>(systemName: <span class="hljs-string">"plus"</span>)
                }
            }
            .listStyle(<span class="hljs-type">PlainListStyle</span>())
        }
    }
}
</code></pre>
<p>Anything that conforms to ObservableObject can be used inside SwiftUI, and publish announcements when its values have changed so the View can be updated. Clicking the add button will add User Objects to the collection which will cause the view to be rebuilt as shown here:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633607877603/-daMexLrZ.png" alt="1_vv5xeiS-mDR_PLuHvVDvwQ.png" /></p>
]]></content:encoded></item><item><title><![CDATA[Android Jetpack Compose API Data to List View]]></title><description><![CDATA[Many times we need to make API calls to fetch data and display that data using a List. Here, I show how to do that with Compose. To illustrate the structure of the application let’s look at the following diagram

Firstly, Add Internet Permission to y...]]></description><link>https://codefoundation.co.za/android-jetpack-compose-api-data-to-list-view</link><guid isPermaLink="true">https://codefoundation.co.za/android-jetpack-compose-api-data-to-list-view</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[json]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Thu, 07 Oct 2021 06:42:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633588049126/_KtbEYt1K.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Many times we need to make API calls to fetch data and display that data using a List. Here, I show how to do that with Compose. To illustrate the structure of the application let’s look at the following diagram</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633588117777/ifw1bS2OG.png" alt="1_8z2MyKzSN-npdTQZBr8LJg.png" /></p>
<p>Firstly, Add Internet Permission to your Application in AndroidManifest.xml</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.INTERNET"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">uses-permission</span>&gt;</span>
</code></pre>
<p>Before we start let’s update our build.gradle file with the Retrofit HTTP client and aConverter which uses Gson for serialisation to and from JSON.:</p>
<pre><code class="lang-groovy">dependencies{
...
    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    implementation "com.squareup.retrofit2:converter-gson:2.0.0"
}
</code></pre>
<h3 id="the-todo-apiservice">The Todo APIService</h3>
<p>We need to create the  <a target="_blank" href="https://square.github.io/retrofit/">Retrofit</a>  instance to send the network requests. We need to use the Retrofit Builder class and specify the base URL for the service. Here we have one GET to fetch all Todos and deserialise to List</p>
<pre><code class="lang-kt">
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Todo</span></span>(
    <span class="hljs-keyword">var</span> userId: <span class="hljs-built_in">Int</span>,
    <span class="hljs-keyword">var</span> id: <span class="hljs-built_in">Int</span>,
    <span class="hljs-keyword">var</span> title: String,
    <span class="hljs-keyword">var</span> completed: <span class="hljs-built_in">Boolean</span>
)

<span class="hljs-keyword">const</span> <span class="hljs-keyword">val</span> BASE_URL = <span class="hljs-string">"https://jsonplaceholder.typicode.com/"</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">APIService</span> </span>{
    <span class="hljs-meta">@GET(<span class="hljs-meta-string">"todos"</span>)</span>
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodos</span><span class="hljs-params">()</span></span>: List&lt;Todo&gt;

    <span class="hljs-keyword">companion</span> <span class="hljs-keyword">object</span> {
        <span class="hljs-keyword">var</span> apiService: APIService? = <span class="hljs-literal">null</span>
        <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getInstance</span><span class="hljs-params">()</span></span>: APIService {
            <span class="hljs-keyword">if</span> (apiService == <span class="hljs-literal">null</span>) {
                apiService = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build().create(APIService::<span class="hljs-keyword">class</span>.java)
            }
            <span class="hljs-keyword">return</span> apiService!!
        }
    }
}
</code></pre>
<h3 id="the-todo-viewmodel">The Todo ViewModel</h3>
<p>The View model publishes the todoList and has a getTodoList function to fetch all todos</p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TodoViewModel</span> : <span class="hljs-type">ViewModel</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _todoList = mutableStateListOf&lt;Todo&gt;()
    <span class="hljs-keyword">var</span> errorMessage: String <span class="hljs-keyword">by</span> mutableStateOf(<span class="hljs-string">""</span>)
    <span class="hljs-keyword">val</span> todoList: List&lt;Todo&gt;
        <span class="hljs-keyword">get</span>() = _todoList

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getTodoList</span><span class="hljs-params">()</span></span> {
        viewModelScope.launch {
            <span class="hljs-keyword">val</span> apiService = APIService.getInstance()
            <span class="hljs-keyword">try</span> {
                _todoList.clear()
                _todoList.addAll(apiService.getTodos())

            } <span class="hljs-keyword">catch</span> (e: Exception) {
                errorMessage = e.message.toString()
            }
        }
    }
}
</code></pre>
<h3 id="the-todo-view">The Todo View</h3>
<p>Finally we have the view which observes the ViewModel for any todo list state changes.  When changes are detected the composable rebuilds. The todo list is displayed in the view.</p>
<pre><code class="lang-kt">
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">val</span> vm = TodoViewModel()
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                TodoView(vm)
            }
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">TodoView</span><span class="hljs-params">(vm: <span class="hljs-type">TodoViewModel</span>)</span></span> {

    LaunchedEffect(<span class="hljs-built_in">Unit</span>, block = {
        vm.getTodoList()
    })

    Scaffold(
        topBar = {
            TopBar()
        },
        content = {
            <span class="hljs-keyword">if</span> (vm.errorMessage.isEmpty()) {
                TodoList(vm)
            } <span class="hljs-keyword">else</span> {
                Text(vm.errorMessage)
            }
        }
    )
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">TodoList</span><span class="hljs-params">(vm: <span class="hljs-type">TodoViewModel</span>)</span></span> {
    Column(modifier = Modifier.padding(<span class="hljs-number">16</span>.dp)) {
        LazyColumn(modifier = Modifier.fillMaxHeight()) {
            items(vm.todoList) { todo -&gt;
                Column {
                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(<span class="hljs-number">16</span>.dp),
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Box(
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(<span class="hljs-number">0</span>.dp, <span class="hljs-number">0</span>.dp, <span class="hljs-number">16</span>.dp, <span class="hljs-number">0</span>.dp)
                        ) {
                            Text(
                                todo.title,
                                maxLines = <span class="hljs-number">1</span>,
                                overflow = TextOverflow.Ellipsis
                            )
                        }
                        Spacer(modifier = Modifier.width(<span class="hljs-number">16</span>.dp))
                        Checkbox(checked = todo.completed, onCheckedChange = <span class="hljs-literal">null</span>)
                    }
                    Divider()
                }
            }
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">TopBar</span><span class="hljs-params">()</span></span> {
    TopAppBar(
        title = {
            Row {
                Text(<span class="hljs-string">"Todos"</span>)
            }
        })
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633588516849/RO3vZ42Cm.png" alt="1_AvmLQiF9QC1mTSzM3nu-Kg.png" /></p>
]]></content:encoded></item><item><title><![CDATA[Android Jetpack Compose MVVM]]></title><description><![CDATA[Model–View–ViewModel (MVVM) is a software architectural pattern that facilitates the separation of the development of the GUI (the view) from the development of the business logic or back-end logic (the model) so that the view is not dependent on any...]]></description><link>https://codefoundation.co.za/jetpack-compose-mvvm-6a5033ed54d9</link><guid isPermaLink="true">https://codefoundation.co.za/jetpack-compose-mvvm-6a5033ed54d9</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[MVVM]]></category><category><![CDATA[Kotlin]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Tue, 05 Oct 2021 10:09:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633608118814/owvOg--yV.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Model–View–ViewModel</strong> (<strong>MVVM</strong>) is a software <a target="_blank" href="https://en.wikipedia.org/wiki/Architectural_pattern">architectural pattern</a> that facilitates the <a target="_blank" href="https://en.wikipedia.org/wiki/Separation_of_concerns">separation</a> of the development of the GUI (the <em>view)</em> from the development of the <a target="_blank" href="https://en.wikipedia.org/wiki/Business_logic">business logic</a> or <a target="_blank" href="https://en.wikipedia.org/wiki/Front_and_back_ends">back-end</a> logic (the <em>model</em>) so that the view is not dependent on any specific model platform. The <em>ViewModel</em> of MVVM is responsible for exposing the <a target="_blank" href="https://en.wikipedia.org/wiki/Data_object">data objects</a> from the model in such a way that objects are easily managed and presented. In this respect, the ViewModel is more model than view and handles most if not all of the view’s display logic. The ViewModel may implement a <a target="_blank" href="https://en.wikipedia.org/wiki/Mediator_pattern">mediator pattern</a>, organizing access to the back-end logic around the set of <a target="_blank" href="https://en.wikipedia.org/wiki/Use_case">use cases</a> supported by the view.</p>
<p>I’ve put together a small sample showing these 3 layers and how they relate to each other in JetPack Compose. You’ll notice that other than property/method names, none of the objects need to know anything about the others. Each layer can be built completely independent of the others.</p>
<h2 id="sample-model">Sample Model</h2>
<pre><code class="lang-kt"><span class="hljs-keyword">import</span> java.util.*

<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>(
    <span class="hljs-keyword">var</span> id: UUID,
    <span class="hljs-keyword">var</span> name: String
)
</code></pre>
<h2 id="sample-viewmodel">Sample ViewModel</h2>
<p>This should contain everything one would need to interact with the view. Right now it contains 2 members: users, and an addUser function. Note we’re using mutableStateListOf to maintain state of a collection of users in the view model.</p>
<pre><code class="lang-kt">
<span class="hljs-keyword">import</span> androidx.compose.runtime.*
<span class="hljs-keyword">import</span> androidx.lifecycle.ViewModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserViewModel</span> : <span class="hljs-type">ViewModel</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _users = mutableStateListOf&lt;User&gt;()

    <span class="hljs-keyword">val</span> users: List&lt;User&gt;
        <span class="hljs-keyword">get</span>() = _users

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">addUser</span><span class="hljs-params">(user: <span class="hljs-type">User</span>)</span></span> {
        _users.add(user)
    }
}
</code></pre>
<h2 id="sample-view">Sample View</h2>
<p>And now the View. These are DataTemplates that define how data should be displayed. ViewModels survive configuration changes, so they allow you to encapsulate state and events related to the UI without having to deal with the activity or fragment lifecycle that hosts your Compose code.</p>
<pre><code class="lang-kt"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">UserView</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">val</span> vm <span class="hljs-keyword">by</span> remember { mutableStateOf(UserViewModel()) }
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(<span class="hljs-string">"Users"</span>) },
                actions = {
                    IconButton(onClick = {
                        vm.addUser(User(UUID.randomUUID(), <span class="hljs-string">"User"</span>))
                    }) {
                        Icon(Icons.Filled.Add, <span class="hljs-literal">null</span>)
                    }
                })
        },
        content = {
            Column(modifier = Modifier.padding(<span class="hljs-number">16</span>.dp)) {
                LazyColumn(modifier = Modifier.fillMaxHeight()) {
                    items(vm.users) {
                        Column {
                            Text(it.name)
                            Text(<span class="hljs-string">"<span class="hljs-subst">${it.id}</span>"</span>)
                        }

                    }
                }
            }
        }
    )
}
</code></pre>
<p>We can hoist the ViewModel further up the Compose UI tree to maintain a more global state as follows:</p>
<pre><code class="lang-kt"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        <span class="hljs-keyword">val</span> vm = UserViewModel()
        setContent {
            MaterialTheme {
                UserView(vm)
            }
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">UserView</span><span class="hljs-params">(vm: <span class="hljs-type">UserViewModel</span>)</span></span> {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(<span class="hljs-string">"Users"</span>) },
                actions = {
                    IconButton(onClick = {
                        vm.addUser(User(UUID.randomUUID(), <span class="hljs-string">"User"</span>))
                    }) {
                        Icon(Icons.Filled.Add, <span class="hljs-literal">null</span>)
                    }
                })
        },
        content = {
            Column(modifier = Modifier.padding(<span class="hljs-number">16</span>.dp)) {
                LazyColumn(modifier = Modifier.fillMaxHeight()) {
                    items(vm.users) {
                        Column {
                            Text(it.name)
                            Text(<span class="hljs-string">"<span class="hljs-subst">${it.id}</span>"</span>)
                        }

                    }
                }
            }
        }
    )
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633608116922/Q90jK6B9R.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Jetpack Compose Flat and Hierarchical Navigation]]></title><description><![CDATA[Navigation in your app has to be appropriate: Don’t use non-logical navigation.

Navigation must always be intuitive: Users don’t have time to look for the right section in your app

Don’t steal time from your users: They will delete the app

Navigat...]]></description><link>https://codefoundation.co.za/jetpack-compose-flat-and-hierarchical-navigation-31d61eed148d</link><guid isPermaLink="true">https://codefoundation.co.za/jetpack-compose-flat-and-hierarchical-navigation-31d61eed148d</guid><category><![CDATA[Android]]></category><category><![CDATA[android app development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[navigation]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Fri, 01 Oct 2021 18:39:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162217044/A4iV8gfIe.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ol>
<li><p>Navigation in your app has to be appropriate: Don’t use non-logical navigation.</p>
</li>
<li><p>Navigation must always be intuitive: Users don’t have time to look for the right section in your app</p>
</li>
<li><p>Don’t steal time from your users: They will delete the app</p>
</li>
<li><p>Navigation must be clear: Users have to always know which screen they are on now</p>
</li>
</ol>
<p>When building a business application the 2 main navigation structures are <strong>Hierarchical</strong> and <strong>Flat.</strong></p>
<h2 id="hierarchical">Hierarchical</h2>
<p>Users navigate by making only one choice per screen until they reach their destination. To get to another destination, users must either retrace, or start from the beginning and make other choices.</p>
<p>We use <strong>NavHostController</strong> to implement hierarchical navigation</p>
<p>Add this to your project by updating your app module’s build.gradle dependencies</p>
<pre><code><span class="hljs-selector-tag">dependencies</span> {
    ...
    <span class="hljs-selector-tag">implementation</span>(<span class="hljs-string">"androidx.navigation:navigation-compose:2.4.0-alpha10"</span>)
}
</code></pre><p>Then create a Router component to do all route management. Within this router we map 2 screens to 2 routes: “screen1" and “child1". We keep track of all nav state through a hoisted navController state which is passed down to all routed components.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent {
            <span class="hljs-keyword">val</span> navController = rememberNavController()
            MaterialTheme {
                Router(navController)
            }
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Router</span><span class="hljs-params">(navController: <span class="hljs-type">NavHostController</span>)</span></span> {
    NavHost(
        navController = navController,
        startDestination = <span class="hljs-string">"screen1"</span>
    ) {
        composable(<span class="hljs-string">"screen1"</span>) {
            Screen1(navController)
        }
        composable(<span class="hljs-string">"child1"</span>) {
            Child1(navController)
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Screen1</span><span class="hljs-params">(navController: <span class="hljs-type">NavController</span>)</span></span> {
    Scaffold(
        topBar = { TopAppBar(title = { Text(<span class="hljs-string">"Screen 1"</span>) }) },
        content = {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ){
                Button(onClick = { navController.navigate(<span class="hljs-string">"child1"</span>) }) {
                    Text(text = <span class="hljs-string">"Go to Child of Screen 1"</span>)
                }
            }
        })
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Child1</span><span class="hljs-params">(navController: <span class="hljs-type">NavController</span>)</span></span> {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(<span class="hljs-string">"Screen 1"</span>) },
                navigationIcon = {
                    IconButton(onClick = {
                        navController.popBackStack()
                    }) {
                        Icon(Icons.Filled.ArrowBack, <span class="hljs-literal">null</span>)
                    }
                })
        },
        content = {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ){
                Text(<span class="hljs-string">"This is the Child of Screen 1"</span>)
            }
        })
}
</code></pre>
<p>Clicking on the Button on Screen 1 will push the child screen onto Screen 1</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162213460/F19vJcOZ4.png" alt /></p>
<h2 id="flat">Flat</h2>
<p>Now let’s look at Flat navigation. All the primary screens can be navigated from the main screen. We’ll build and use a BottomNavigation Bar to implement flat navigation.</p>
<p>First Let’s add another screen (screen2) to the Router</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Router</span><span class="hljs-params">(navController: <span class="hljs-type">NavHostController</span>)</span></span> {
    NavHost(
        navController = navController,
        startDestination = <span class="hljs-string">"screen1"</span>
    ) {
        composable(<span class="hljs-string">"screen1"</span>) {
            Screen1(navController)
        }
        composable(<span class="hljs-string">"screen2"</span>) {
            Screen2()
        }
        composable(<span class="hljs-string">"child1"</span>) {
            Child1(navController)
        }
    }
}

<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">Screen2</span><span class="hljs-params">()</span></span> {
    Scaffold(
        topBar = { TopAppBar(title = { Text(<span class="hljs-string">"Screen 2"</span>) }) },
        content = {
            Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                Text(text = <span class="hljs-string">"Screen 2"</span>)
            }
        })
}
</code></pre>
<p>Now let’s create a BottomNavigationBar, a component that takes in a list of nav items, a nav controller, and an item click handler. It then loops through nav items to display them in within a BottomNavigation. Note the BottomNavigation returns a RowScope so all items rendered in this component will automatically be rendered in a row.</p>
<pre><code class="lang-kotlin">
<span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BottomNavItem</span></span>(
    <span class="hljs-keyword">val</span> name: String,
    <span class="hljs-keyword">val</span> route: String,
    <span class="hljs-keyword">val</span> icon: ImageVector
)


<span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">BottomNavigationBar</span><span class="hljs-params">(
    items: <span class="hljs-type">List</span>&lt;<span class="hljs-type">BottomNavItem</span>&gt;,
    navController: <span class="hljs-type">NavHostController</span>,
    modifier: <span class="hljs-type">Modifier</span> = Modifier,
    onItemClick: (<span class="hljs-type">BottomNavItem</span>) -&gt; <span class="hljs-type">Unit</span>
)</span></span> {
    <span class="hljs-keyword">val</span> backStackEntry = navController.currentBackStackEntryAsState();
    BottomNavigation(modifier = modifier) {
        items.forEach { item -&gt;
            <span class="hljs-keyword">var</span> selected = item.route == backStackEntry.value?.destination?.route
            BottomNavigationItem(
                selected = selected,
                onClick = { onItemClick(item) },
                selectedContentColor = Color(<span class="hljs-number">0xFFFFFFFF</span>),
                unselectedContentColor = Color(<span class="hljs-number">0x88FFFFFF</span>),
                icon = {
                    Column(horizontalAlignment = Alignment.CenterHorizontally) {
                        Icon(
                            imageVector = item.icon,
                            contentDescription = item.name
                        )
                        Text(text = item.name, textAlign = TextAlign.Center, fontSize = <span class="hljs-number">10</span>.sp)

                    }
                }
            )
        }
    }
}
</code></pre>
<p>The last step is to change the MainActivity to return a Scaffold with a bottomBar.</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">ComponentActivity</span></span>() {
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                <span class="hljs-keyword">val</span> navController = rememberNavController()
                Scaffold(
                    bottomBar = {
                        BottomNavigationBar(
                            items = listOf(
                                BottomNavItem(
                                    name = <span class="hljs-string">"Screen1"</span>,
                                    route = <span class="hljs-string">"screen1"</span>,
                                    icon = Icons.Filled.Home
                                ),
                                BottomNavItem(
                                    name = <span class="hljs-string">"Screen2"</span>,
                                    route = <span class="hljs-string">"screen2"</span>,
                                    icon = Icons.Filled.Settings
                                )
                            ),
                            navController = navController,
                            onItemClick = {
                                navController.navigate(it.route)
                            }
                        )
                    }
                ) {
                    Router(navController = navController)
                }
            }
        }
    }
}
</code></pre>
<p>Final result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162215224/Mxv9kXT-c.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[SwiftUI 5.5 Flat and Hierarchical Navigation]]></title><description><![CDATA[Navigation in your app has to be appropriate: Don’t use non-logical navigation.

Navigation must always be intuitive: Users don’t have time to look for the right section in your app

Don’t steal time from your users: They will delete the app

Navigat...]]></description><link>https://codefoundation.co.za/swiftui-5-5-flat-and-hierarchical-navigation-feac130e32ac</link><guid isPermaLink="true">https://codefoundation.co.za/swiftui-5-5-flat-and-hierarchical-navigation-feac130e32ac</guid><category><![CDATA[iOS]]></category><category><![CDATA[Swift]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[navigation]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Mon, 27 Sep 2021 10:07:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162193159/re0l-iWiH.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ol>
<li><p>Navigation in your app has to be appropriate: Don’t use non-logical navigation.</p>
</li>
<li><p>Navigation must always be intuitive: Users don’t have time to look for the right section in your app</p>
</li>
<li><p>Don’t steal time from your users: They will delete the app</p>
</li>
<li><p>Navigation must be clear: Users have to always know which screen they are on now</p>
</li>
</ol>
<p>When building a business application the 2 main navigation structures are <strong>Hierarchical</strong> and <strong>Flat.</strong></p>
<h3 id="hierarchical">Hierarchical</h3>
<p>Users navigate by making only one choice per screen until they reach their destination. To get to another destination, users must either retrace, or start from the beginning and make other choices.</p>
<p>We use <strong>NavigationView</strong> to implement hierarchical navigation</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI


<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ChildView</span>: <span class="hljs-title">View</span> </span>{
    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">Text</span>(<span class="hljs-string">"This is the Child of Screen 1"</span>)
    }
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView</span>: <span class="hljs-title">View</span> </span>{
    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">NavigationView</span> {
            <span class="hljs-type">NavigationLink</span>(destination: <span class="hljs-type">ChildView</span>()) {
                <span class="hljs-type">Text</span>(<span class="hljs-string">"Go To Child of Screen 1"</span>)
            }.navigationTitle(<span class="hljs-string">"Screen 1"</span>)
        }.navigationViewStyle(<span class="hljs-type">StackNavigationViewStyle</span>())
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162190056/FyrLr9V9u.png" alt /></p>
<p>Clicking on the Navigation Link will push the child screen onto Screen 1</p>
<h3 id="flat">Flat</h3>
<p>All the primary screens can be navigated from the main screen.</p>
<p>We use <strong>TabViews</strong> to implement flat navigation.</p>
<pre><code class="lang-swift"><span class="hljs-keyword">import</span> SwiftUI


<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ChildView</span>: <span class="hljs-title">View</span> </span>{
    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">Text</span>(<span class="hljs-string">"This is the Child of Screen 1"</span>)
    }
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Screen1View</span>: <span class="hljs-title">View</span> </span>{
    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">NavigationView</span> {
            <span class="hljs-type">NavigationLink</span>(destination: <span class="hljs-type">ChildView</span>()) {
                <span class="hljs-type">Text</span>(<span class="hljs-string">"Go To Child of Screen 1"</span>)

            }.navigationTitle(<span class="hljs-string">"Screen 1"</span>)
        }.navigationViewStyle(<span class="hljs-type">StackNavigationViewStyle</span>())
    }
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Screen2View</span>: <span class="hljs-title">View</span> </span>{
    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">NavigationView</span> {
            <span class="hljs-type">Text</span>(<span class="hljs-string">"Screen 2"</span>).navigationTitle(<span class="hljs-string">"Screen 2"</span>)
        }.navigationViewStyle(<span class="hljs-type">StackNavigationViewStyle</span>())
    }
}

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ContentView</span>: <span class="hljs-title">View</span> </span>{
    <span class="hljs-keyword">var</span> body: some <span class="hljs-type">View</span> {
        <span class="hljs-type">TabView</span>{
            <span class="hljs-type">Screen1View</span>()
                .tabItem({
                    <span class="hljs-type">Label</span>(<span class="hljs-string">"One"</span>, systemImage: <span class="hljs-string">"1.circle"</span>)
                })
            <span class="hljs-type">Screen2View</span>()
                .tabItem({
                    <span class="hljs-type">Label</span>(<span class="hljs-string">"Two"</span>, systemImage: <span class="hljs-string">"2.circle"</span>)
                })
        }
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162191617/QVgml81mH.png" alt /></p>
<p>We’ve now incorporated hierarchical nav inside of flat nav with a TabView and given the tabs labels and icons</p>
]]></content:encoded></item><item><title><![CDATA[Javascript Dependency Injection without Classes]]></title><description><![CDATA[Dependency injection is a programming technique that makes a module independent of its dependencies. This enables you to replace dependencies without changing the module that uses them.
To illustrate Dependency Injection, we’ll build an API with the ...]]></description><link>https://codefoundation.co.za/javascript-dependency-injection-without-classes-7adfa4dacc3d</link><guid isPermaLink="true">https://codefoundation.co.za/javascript-dependency-injection-without-classes-7adfa4dacc3d</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[dependency injection]]></category><dc:creator><![CDATA[Paul Allies]]></dc:creator><pubDate>Sat, 27 Mar 2021 09:50:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162232497/ffHHiPLXp.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Dependency injection is a programming technique that makes a module independent of its dependencies. This enables you to replace dependencies without changing the module that uses them.</p>
<p>To illustrate Dependency Injection, we’ll build an API with the following endpoints</p>
<ol>
<li><p>GET /post: Gets all posts</p>
</li>
<li><p>POST /post: Creates a post</p>
</li>
</ol>
<p>and structure the API in the following way:</p>
<ol>
<li><p>Datasource — persistence implementation using third party modules.</p>
</li>
<li><p>Repository — decouple application from persistence: has a datasource dependency.</p>
</li>
<li><p>UseCase — business logic: has a repository dependency.</p>
</li>
<li><p>Presentation — routes: has a use-case dependency.</p>
</li>
</ol>
<p><strong>1. PostDataSource</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162220385/-u4FkXnCk.png" alt /></p>
<p>The post datasource uses on third a party lib as shown in the require statement. <em>(nedb is an embedded persistent database for Node. API is a subset of MongoDB</em>)</p>
<p><strong>2. PostRepository</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162222197/couVto4Yy.png" alt /></p>
<p>The repository is a way of decoupling our datasource from the rest of our application. The datasource is therefore <strong>property injected</strong> into the repository. Once injected, all the functions within the repository now have access to this external dependency. This is using the closure feature within Javascript</p>
<p><em>A closure is a feature where an inner function has access to the outer (enclosing) function’s variables</em></p>
<p><strong>3. CreatePost UseCase</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162224192/qd5l8VPx5.png" alt /></p>
<p>As we’ve done with the post repository, the post repository is now <strong>property injected</strong> into the use-case.</p>
<p>Let’s now build the post router and see how we chain these dependencies.</p>
<p><strong>4. Post Router</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162226711/b_LQ432Er.png" alt /></p>
<p>With the code above, we manually need to create and chain together the dependencies in order to produce a use-case object on which we run the execute command to produce the result the endpoint responds with.</p>
<p>We can simplify the process of manually managing dependencies by using an IoC container. IoC container (a.k.a. DI Container) is a framework for implementing automatic dependency injection. It manages object creation, and also injects dependencies.</p>
<p>Let us firstly create the container.</p>
<p><strong>IoC Container</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162228836/MILalfjbG.png" alt /></p>
<p>All dependencies are imported and registered here. We use the <a target="_blank" href="https://www.npmjs.com/package/awilix">Awilix</a> third party library to help use create the container</p>
<p>Let’s now revisit our router and replace manually dependency management with the use of the container.</p>
<p><strong>Post Router with Container</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635162230781/EMbPXflzR.png" alt /></p>
<p>And that’s it. We’ve now shown how we can use dependency injection in Javascript and without classes.</p>
]]></content:encoded></item></channel></rss>