|
| 1 | +# Welcome to My Architecture Design! |
| 2 | + |
| 3 | +Untuk mengukur seberapa baik sebuah arsitektur, kita membutuhkan base line (Standar minimum) dan sebuah alat untuk mengukur. |
| 4 | +Base tersebut adalah **Alur Dependensi dan Alur Kerja** dan alat ukur tersebut adalah **Prinsib-prinsib pembuatan software** |
| 5 | +Arsitektur software adalah tentang Flow Dependensi dan Flow Runtime. Hal-hal selain itu adalah preferensi saja. |
| 6 | + |
| 7 | +Disini kita akan "**Back to Basic**" dengan konsern sepenuhnya pada **Flow dependensi** dan **Flow runtime**. |
| 8 | + |
| 9 | +Saya memiliki prinsib sederhana; "Jika rumit berarti salah". Jadi kita akan membuatnya sedikit lebih mudah dengan menghadirkan sebuah module baru pada gradle project , |
| 10 | +yaitu : **Provider** dan **Igniter** |
| 11 | + |
| 12 | +Ide utama dari proyek ini adalah: |
| 13 | +1. Menghilangkan Horizontal dependency sepenuhnya, dengan memunculkan module baru yakni **Provider** dan **Igniter**. |
| 14 | +2. Menghilangkan state dari data layer, dengan memaksimalkan functional pattern pada data layer. |
| 15 | +3. Me-lokalisasi side effect. Kita harus membatasi module yang bisa melakukan side effect dan sebisa mungkin menghilangkannya. |
| 16 | + |
| 17 | +# Project Arsitektur |
| 18 | + |
| 19 | +Projek arsitektur mencakup keseluruhan arsitektur dari gradle project kita. Tidak segala hal bisa |
| 20 | +kita lakukan dengan gradle project akan tetapi **Pengecualian adalah hal yang buruk** jika kita |
| 21 | +tidak membatasinya. Jadi kita akan membatasi pengecualian tersebut hanya 2 hal. |
| 22 | + |
| 23 | +1. App Module adalah bagian dari Igniter. Sehingga App Module dapat berperilaku seperti Igniter |
| 24 | + module, akan tetapi tidak boleh memprovide Module apapun sebagaimana module Igniter. |
| 25 | +2. Straight dependensi ke Core Module. |
| 26 | + |
| 27 | +**Circular dependensi** terjadi dikarenakan kita mengizinkan "**Horizontal Dependency**". Jadi kita tidak akan mengijinkan adanya Horizontal dependensi pada module ini. |
| 28 | + |
| 29 | +1. Sebuah module tidak boleh depend ke module lain kecuali Provider. |
| 30 | +2. Sebuah module, tidak perlu mengetahui keberadaan Module Lain, selain keberadaan module Provider. |
| 31 | + |
| 32 | +## Provider |
| 33 | + |
| 34 | +Sebagai mana namanya, Provider bertugas untuk memprovide module berdasarkan kontrak module pada |
| 35 | +Provider. Sebagai contoh, module tersebut bisa sebuah **API**, **Aktivitas**, **Widget** dan lain |
| 36 | +sebagainya. |
| 37 | + |
| 38 | +### Runtime Flow |
| 39 | + |
| 40 | +```mermaid |
| 41 | +graph LR |
| 42 | +A[Module 1] -- payload --> B((Provider)) -- payload --> C[Module 2] |
| 43 | +``` |
| 44 | + |
| 45 | +Setiap module bisa memanggil module lain melalui kontrak yang sudah dideklarasikan di dalam |
| 46 | +Provider. Selanjutnya, **Igniter** akan memprovide module berdasarkan kontrak yang di inginkan, |
| 47 | +dan **Module 1** tidak perlu tau dari mana dia mendapatkan **Module 2** tersebut. Tentusaja sebuah |
| 48 | +module harus memprovide atau meng-injeksikan module tersebut ke **Igniter** sebelumnya, untuk |
| 49 | +kemudian module tersebut dapat ditemukan oleh **Provider**. |
| 50 | + |
| 51 | +### Dependency Flow |
| 52 | + |
| 53 | +```mermaid |
| 54 | +graph LR |
| 55 | +A[Module 1] --> B((Provider)) |
| 56 | +C[Module 2] --> B |
| 57 | +D[Module 3] --> B |
| 58 | +B --> E{{Core}} |
| 59 | +``` |
| 60 | + |
| 61 | +Seluruh module (yang masuk dalam kategori runtime module) hanya depend ke 1 Module, yakni Provider |
| 62 | +Module. Sementara Provider Module depend ke **Core Module**. Dalam arsitektur ini **Core Module** |
| 63 | +adalah sebuah pengecualian, dikarenakan Core Module memiliki sangat banyak komponent dan kebanyakan |
| 64 | +berukuran sangat kecil. Oleh Karena itu, akan jauh lebih mudah jika semua module yang membutuhkan |
| 65 | +core **"Straight Depend" ke Module Core**, dan semua module tetap harus **mengakses Core Module |
| 66 | +melalui Provider**. |
| 67 | + |
| 68 | +## Igniter |
| 69 | + |
| 70 | +Sebagaimana namanya, Igniter adalah sebuah module yang bertugas untuk menjadi sumbu api. Igniter |
| 71 | +perlu depend ke semua module, dan **meng-interaksikan** Module-module, API, Widget dll, yang diprovide |
| 72 | +setiap Module. |
| 73 | + |
| 74 | +**Application** perlu **diprovide oleh Igniter**. Dan Igniter perlu menghubungkan seluruh Module ke satu sumbu api pada |
| 75 | +Application class. |
| 76 | + |
| 77 | +## Overview arsitektur |
| 78 | + |
| 79 | +Anda bisa melihat overview arsitektur pada file arsitektur-overview.pdf |
| 80 | + |
| 81 | +# Internal Module Arsitektur |
| 82 | + |
| 83 | +Kita mengenal MVVM , Clean Architectur, tapi apakah aplikasi front-end perlu se rumit itu? Menurut |
| 84 | +saya, Tidak. |
| 85 | + |
| 86 | +Sebagai front-end developer, saya tidak pernah menemukan kemungkinan yang begitu rumit. |
| 87 | + |
| 88 | +Aplikasi front-end hanya terdiri dari 2 hal yakni **UI** dan **Data**. Seberapa rumitkah itu. |
| 89 | + |
| 90 | +## UI |
| 91 | + |
| 92 | +UI adalah module level tinggi, penuh dengan side-effect, lifecycle, configuration changes dan lain |
| 93 | +sebagainya. Module ini memang cukup rumit, oleh karena itu, prinsib SOLID dan Dependency injection |
| 94 | +akan sangat membantu kita. Tidak ada hal yang istimewa yang perlu saya sampaikan, gunakan ViewModel |
| 95 | +dan Injector seperti Koin atau Dagger. |
| 96 | + |
| 97 | +**Note**: Sekalipun UI penuh dengan side effect, kita tidak boleh hanya memakluminya. Melainkan kita harus sebisa mungkin menghilangkannya. |
| 98 | +Dalam pemrograman android imperativ, saya biasanya hanya mengijinkan side effect terjadi di Controller (Fragment atau Activity class). |
| 99 | + |
| 100 | +1. Tidak boleh ada side effect dimanapun selain pada controller module (Fragment Activity, Service dll). Misalnya saja sekalipun viewmodel dan adapter termasuk di dalam presentation module, mereka tidak boleh melakukan side effect karena tidak termasuk ke dalam kategori Controller Class. |
| 101 | +2. Class dengan side effect tidak boleh melakukan "**Cross Responsibility Side Effect**"; Misal, Fragment mengimplementasikan kontrak A dan B, implementasi interface kontrak A melakukan side effect dengan menyimpan data di variable, dan implementasi interface kontrak B menggunakan data yang tersimpan tersebut, ini termasuk dalam **Cross Responsibility Side Effect**. Sangat di sarankan untuk module B, harus memiliki interface untuk menerima data tersebut secara langsung. dan Kontrak A boleh mengirimkan data ke Kontrak B dengan dependensi ke Kontrak B. Atau lebih baik lagi, Kontrak A menyediakan getter untuk data tersebut dan Kontrak B depend ke getter tersebut sesuai dengan **Dependency Inversion** principle. |
| 102 | + |
| 103 | +## Data |
| 104 | + |
| 105 | +Disini bagian menariknya. Data layer tidak memerlukan side-effect, tidak perlu memperdulikan |
| 106 | +lifecycle dan configuration changes (rotasi, dark mode, dll). Module ini sangat sederhana, jadi |
| 107 | +kenapa kita tidak membuatnya menjadi sederhana? |
| 108 | + |
| 109 | +Dalam contoh dalam project ini. Data module tidak perlu mematuhi SOLID principle. Akan tetapi kita |
| 110 | +akan memaksimalkan **Functional Pattern** sebisa mungkin. Saya masih menemukan beberapa kesulitan |
| 111 | +dalam hal support teknologi, dan dokumentasi, akan tetapi, lihat seberapa sederhana itu. |
| 112 | + |
| 113 | +1. Data module, tidak boleh memiliki state, dia hanya peduli dengan apa data yang diminta, dan |
| 114 | + memberikannya atau memberikan Error / Exception / Either.left apapun yang kalian gunakan. |
| 115 | +2. Data module hanya memprovide data dari Source, memberikan data atau Error jika data tidak |
| 116 | + ditemukan. Sedangkan bagaimana source berperilaku bukanlah konsern dari Data module. |
| 117 | +3. Repository API -> Source. Tidak rumit bukan. Dengan monoid chain hal ini dapat menjadi sangat |
| 118 | + sederhana, hanya memerlukan 2 step saja. |
0 commit comments