Skip to content

☎️ This is a complete Kotlin application built to demonstrate the use of Modern development tools with best practices implementation using multi-module architecture developed using SOLID principles

License

Notifications You must be signed in to change notification settings

devrath/droid-pure-kotlin-application

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

droid-pure-kotlin-application 🧞‍

Android Best practices Kotlin Coroutines DaggerHilt Moshi Firebase Datastore Timber Orhanobut Jetpack compose Coil Google Material Compose Navigation Hilt navigation compose Activity compose Ui tooling preview Compose ui Kt lint Crashlytics

𝙸𝚗𝚝𝚛𝚘𝚍𝚞𝚌𝚝𝚒𝚘𝚗 💡

🏷️ This repository serves as template and demo for building android applications for scale. It is suited for large teams where individuals can work independently on feature wise and layer wise reducing the dependency on each other. It is built with pure kotlin in the project namely compose for the presentation-layer, kotlin for writing the business-logic, kotlin-dsl for handeling the dependencies.
🏷️ Single activity architecture where compose-navigation is used for navigating between the screens. Also care is taken so that dependencies used in presentation layer is not available for domain layer and data layer. Multimodule architecture used with reusability by adhering SOLID-principles, also unit-testing, integration-testing in mind. Coding for abstraction rather than implementation is followed in the project that enables testing and so that fakes can be easily provided for abstractions for testing individual components.

🧱🧱 Application is under constant improvement 🧱🧱


𝙿𝚞𝚛𝚎 𝚔𝚘𝚝𝚕𝚒𝚗 🗂️

dev_logo

🏷️ Programming language: ➖ By migrating away from Java and towards kotlin, we can leverage the features like better readability, null saftey, less code, benifits of improved syntax and others.
🏷️ Kotlin DSL: ➖ Earlier we used to use gradle for organizing dependencies. Gradle is written in a groovy programming language. Using the kotlin-DSL, we can organize the dependencies in our project cleaner and in an efficient way. Type safety. This allows better autocompletion which was missing from grovey till now. Code navigation between files becomes easy in Kotlin DSL. Refactoring is much easier.
🏷️ Compose: ➖ Earlier we had xml for building the UI and thus there was one more language hooked to android project. But with the addition of jetpack compose, Even the UI will be built in kotlin language.


𝚆𝚑𝚢 𝚌𝚕𝚎𝚊𝚗 𝚊𝚛𝚌𝚑𝚒𝚝𝚎𝚌𝚝𝚞𝚛𝚎 𝚒𝚜 𝚗𝚎𝚎𝚍𝚎𝚍 🗂️

dev_logo

🏷️ Scalability: ➖ When new features are added, using the clean architecture we can easily add the new features and maintain old existing features without breaking them.
🏷️ Testability: ➖ For the new features, its essential we write a code that can be tested for all possible inputs so that once in production we can forecast all possible scenarios and handle them.
🏷️ Understandable: ➖ Scaling a product with keeping the code testable is good but its also should be in such a way that everyone should understand it and also should easily be modify it.

𝚆𝚑𝚢 𝚖𝚞𝚕𝚝𝚒 𝚖𝚘𝚍𝚞𝚕𝚎 𝚒𝚜 𝚞𝚜𝚎𝚍 𝚒𝚗 𝚙𝚛𝚘𝚓𝚎𝚌𝚝 🗂️

🏷️ A multi module project helps us to segrigate between the layers of code in the project and enforcing strict seperation of concerns.
🏷️ When working on a large project this will keep the team to work in layer wise and also feature wise.
🏷️ A change in one feature will not affect other features in the project.


𝙳𝚎𝚙𝚎𝚗𝚍𝚎𝚗𝚌𝚢 𝙸𝚗𝚓𝚎𝚌𝚝𝚒𝚘𝚗 🗂️

dev_logo

🏷️ A Depencency Injection results in a loosely coupled programs. It helps to achieve inversion of control. Inversion of control means a object or function recieves another object or function as a dependency.
🏷️ We use hilt that is built on top of dagger tool that generates code on behalf of user and helps to attain the inversion control easily. This is very essential because all the extra code that we need to generate, hilt will do it for us.
🏷️ The inversion control becomes even more crucial part of the structure in case of multi module project.
🏷️ This also helps in unit testing thte code because, since object is not created and instead provided to a function, we can easily mock it during unit testing.

𝙲𝚘𝚖𝚖𝚞𝚗𝚒𝚌𝚊𝚝𝚒𝚘𝚗 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚝𝚑𝚎 𝚕𝚊𝚢𝚎𝚛𝚜 🗂️

dev_logo

🏷️ Presentation Layer: ➖ This layer is the UI layer of the application, It contains composables and view-models. The presentation layer communicates with the domain layer, But the presentation layer is not aware of the data layer.
🏷️ Domain Layer: ➖ This layer contains use cases that contain business logic that perform one functionality each. It also contains the interfaces that communicates with repository which is present in the data layer.
🏷️ Data Layer: ➖ The data layer contains the repositries, The repository can be a preference repository, remote API, local-filesystem etc. The data layer communicates back with the domain layer after fetching the data.

𝙸𝚖𝚙𝚕𝚎𝚖𝚎𝚗𝚝𝚊𝚝𝚒𝚘𝚗 𝚘𝚏 𝚂𝙾𝙻𝙸𝙳 𝚙𝚛𝚒𝚗𝚌𝚒𝚙𝚕𝚎𝚜 🗂️

This applicaion is developed keeping in mind of clean architecture principles

SINGLE RESPONSIBILITY OPEN CLOSED PRINCIPLE LISKOV SUBSTITUTION PRINCIPLE INTERFACE SEGREGATION PRINCIPLE DEPENDENCY INVERSION PRINCIPLE
Each class having one responsibility. If there is a change in it, it must be because of only one reason only. If there are two reasons for a class to change, then it violates single responsibility principle. This indicates that the class is open for extension but closed for modification When we have a class that is inheriting the parent, the parent class functionality must be replaceable using the child class without modifying the functionality of parent class Here we should not force a class to do something that it does not want to do, Say a class is implementing interface then it overrides all the functions in it. Now if we don’t want a function of interface to be implemented then we give the default behaviour for the interface and so that it will not force the child class to override that method This indicates that, a class must depend on abstraction instead of concrete implementation. Say we want a implementation to be used for a class thence need to inject a abstraction for it instead of concrete implementation so that if its implementation changes in future , it must not affect where the abstract version of it is implemented

𝙰𝚍𝚟𝚊𝚗𝚝𝚊𝚐𝚎𝚜 𝚊𝚗𝚍 𝙳𝚒𝚜𝚊𝚍𝚟𝚊𝚗𝚝𝚊𝚐𝚎𝚜 𝚘𝚏 𝚖𝚞𝚕𝚝𝚒 𝚖𝚘𝚍𝚞𝚕𝚎 𝚊𝚛𝚌𝚑𝚒𝚝𝚎𝚌𝚝𝚞𝚛𝚎 🗂️

𝙰𝚍𝚟𝚊𝚗𝚝𝚊𝚐𝚎𝚜

Clear separation Faster build time
• Each of the modules is a library and it can depend on each other
• If there is a scenario where one library is not dependent on another, Then they can't access each other
• Thus, instead of adding terms of separate packages in the app module, we can enforce strict modularity by modularising it
• In a large project and big team we can enforce, who works on which project. Thus one person working on one won't affect other modules
• Using the multi-module we can decrease the build time. When in multi-module each module will use separate threads so build time will decrease since all modules will build independently
• Since Gradle needs to build the module that has been changed, it doesn't need to make the modules that have not been changed
• Point to note here is that, say there is a root module with few child modules, if the root module changes, all the child modules also need to rebuild
• Support for instant apps and dynamic feature module
• Using this we can make parts of our app reusable

𝙳𝚒𝚜𝚊𝚍𝚟𝚊𝚗𝚝𝚊𝚐𝚎𝚜

• Lot of initial code
• Not knowing what problem it will cause


𝙼𝚅𝚅𝙼 𝚜𝚝𝚛𝚞𝚌𝚝𝚞𝚛𝚎 𝚞𝚜𝚎𝚍 𝚒𝚗 𝚖𝚞𝚕𝚝𝚒-𝚖𝚘𝚍𝚞𝚕𝚎 𝚏𝚘𝚛 𝚌𝚕𝚎𝚊𝚗 𝚊𝚛𝚌𝚑𝚒𝚝𝚎𝚌𝚝𝚞𝚛𝚎

mvvm mvvm-improved














🏷️ Implementations of repositories sits in the data layer.
🏷️ The Data layer has reference to domain layer, So it can access all the classes from the data layer.
🏷️ Presentation layer has reference to the domain layer, so it can access all the classes from the domain layer and not data layer.
🏷️ We alwaays inject abstractions to any class instead of concrete implementation.
🏷️ Data flows from presentation layer to data layer if data is saved locally or sent to server. In other case the data is retrieved from data layer to presentation layer in case when data is retrieved from server to UI displayed or from data saved locally to UI displayed

𝙿𝚊𝚝𝚝𝚎𝚛𝚗𝚜

  • 𝚁𝚎𝚙𝚘𝚜𝚒𝚝𝚘𝚛𝚢 𝙿𝚊𝚝𝚝𝚎𝚛𝚗 - The Repository Pattern is one of the most popular patterns to create an enterprise level application. It restricts us to work directly with the data in the application and creates new layers for database operations, business logic, and the application's UI.
  • 𝙾𝚋𝚜𝚎𝚛𝚟𝚎𝚛 𝙿𝚊𝚝𝚝𝚎𝚛𝚗 - The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
  • 𝚄𝚜𝚎𝙲𝚊𝚜𝚎 𝙿𝚊𝚝𝚝𝚎𝚛𝚗 - This pattern means to convert and pass user actions to inner layers of the application.
  • 𝚃𝙳𝙳 - Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases, then the software is improved so that the tests pass.

𝚃𝚎𝚜𝚝𝚒𝚗𝚐 𝚝𝚑𝚎 𝚌𝚘𝚍𝚎 🧪

🏷️ We test the features of the code, Each of the features contain three layers namely data, domain, presentation.
🏷️ In the core layer we can write tests for the implementation and repository for each of modules.
🏷️ UI tests - Development in progress

𝙿𝚊𝚌𝚔𝚊𝚐𝚎 𝚂𝚝𝚛𝚞𝚌𝚝𝚞𝚛𝚎 𝚒𝚗 𝚝𝚑𝚎 𝚙𝚛𝚘𝚓𝚎𝚌𝚝 📦

Project Folder                                    # Root Package
.
├── app                                           # It is the starting point for the application
│   ├── activity                                  # Entire application has just one activity
│   ├── view-model                                # This will be the view-model for the single activity     
|   ├── navigation                                # It contains the navigation compose and the routes used in the application
│   └── application                               # Singleton used at application level
|
├── buildSrc                                      # It contains all project dependencies & its version references that can be modified from one place
|
├── core                                          # Module with code that can be re-used in all the modules. This also helps us to manage them easily
│   ├── res                                       # String resources used in the project
│   └── java
│       ├── data                                  # data layer of the core module
│       │    ├── implementation                   # contains implementations of the features hosted in core module
│       │    └── repository                       # contains repository for the features
│       │  
│       ├── di                                    # Hilt dependency injection
│       ├── domain                                # Domain layer for all the reusable third party features in project
│       │   ├── features                          # Contains interface for all the reusable third party features in project
│       │   └── models                            # data modules used thorught the project
│       │
│       └── platform                              # Can old other miscellaneous things needed in project, some are listed below
│           ├── base                              # Can hold base classes that are used in different features in project
│           ├── extensions                        # kotlin extensions that can be kept in one place and handeled
│           └── functional                        # Other util functional elements in teh project
│      
│ 
├── core-ui                                       # Module contains all the UI related things in the project
│   ├── res                                       
│   │   ├── drawable                              # Contains all the drawables needed for the project
│   │   └── font                                  # Place we can store the font files in the project
│   │
│   └── java
│       ├── composables                           # Here we store the reusable composables used for the project 
│       └── theme                                 # Contains the theme file used in project
│ 
└── features                                      # The module contains all the features used in project
    │
    ├── common                                    # sub-module that holds the logic that is re-used in multiple features
    │   │
    │   │
    │   ├── common_data                           # sub-module for data
    │   │   ├── di                                # di for current module
    │   │   ├── repository                        # repository used for injection
    │   │   └── service                           # service used in repository
    │   │   
    │   │
    │   └── common_domain                         # sub-module for domain
    │       ├── di                                # di used for having use-case data object instance
    │       ├── repository                        # interface of the repository
    │       └── usecases                          # individual logic for domain data
    │         
    └── login                                     # sub-module that contains one feature
        │
        │
        ├── login_data                            # sub-module for data
        │   ├── di                                # di used to build the module and create instances of service and repository of current module
        │   ├── repository                        # implementation of the repository
        │   └── service                           # service used in repository
        │   
        │
        ├── login_domain                          # sub-module for domain
        │   ├── di                                # di used for having use-case data object instance
        │   ├── repository                        # interface of the repository
        │   └── usecases                          # individual logic for domain data
        │   
        │
        └── login_presentation                    # sub-module for presentation
            ├── states                            # states of the data displayed and view-model
            ├── view-composable                   # composable representing a screen
            └── viewmodel                         # view model for the composable

𝙲𝚘𝚍𝚎 𝚚𝚞𝚊𝚕𝚒𝚝𝚢 📺

Run Kt lint 🔧

🏷️ It is static code analysis tool that is used to analyze the Kotlin code for you. It will check if you have written the code by following the Kotlin code guidelines or not.

// To check the list of errors
./gradlew ktlintCheck  
// Try to auto auto format errors
./gradlew ktlintFormat

𝙷𝚘𝚠 𝚝𝚘 𝚛𝚞𝚗 𝚝𝚑𝚎 𝚜𝚊𝚖𝚙𝚕𝚎 𝚊𝚙𝚙𝚕𝚒𝚌𝚊𝚝𝚒𝚘𝚗 👣

🏷️ Basically You just follow steps to create a firebase account and eanable authentication module, I have summarized some steps below.
1️⃣ Before running the sample application, Please create a account in firebase console.
2️⃣ Now enable the authentication in settings for firebase(This is used during the authentication of login).
3️⃣ Add the google-services.json in the app level of the project that is obtained when creating a project in firebase.
4️⃣ Last but not least add your application SHA in your firebase settings.

𝚃𝚎𝚌𝚑 𝚜𝚝𝚊𝚌𝚔 🏗️️

What How
🎭 𝚄𝚜𝚎𝚛 𝙸𝚗𝚝𝚎𝚛𝚏𝚊𝚌𝚎 (𝙰𝚗𝚍𝚛𝚘𝚒𝚍) 𝙹𝚎𝚝𝚙𝚊𝚌𝚔 𝙲𝚘𝚖𝚙𝚘𝚜𝚎
🏗 𝙰𝚛𝚌𝚑𝚒𝚝𝚎𝚌𝚝𝚞𝚛𝚎 𝙲𝚕𝚎𝚊𝚗 𝙰𝚛𝚌𝚑𝚒𝚝𝚎𝚌𝚝𝚞𝚛𝚎
💉 𝙳𝙸 (𝙰𝚗𝚍𝚛𝚘𝚒𝚍) 𝙷𝚒𝚕𝚝
🌊 𝙰𝚜𝚢𝚗𝚌 𝙲𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 + Flow
🌐 𝙽𝚎𝚝𝚠𝚘𝚛𝚔𝚒𝚗𝚐 𝙵𝚒𝚛𝚎𝚋𝚊𝚜𝚎

𝙲𝚞𝚛𝚛𝚎𝚗𝚝𝚕𝚢 𝚏𝚎𝚊𝚝𝚞𝚛𝚎𝚜 𝚍𝚎𝚟𝚎𝚕𝚘𝚙𝚎𝚍 🧰

Demo contains three screen application namely registration, login, forgot-password and external service used here is firebase. User can create an account using registration. User can login and once login is successful the user details is saved in data-store

Login Registration Forgot Password

𝙼𝙰𝙳 𝚂𝚌𝚘𝚛𝚎 🎈

Banner

𝚂𝚞𝚙𝚙𝚘𝚛𝚝

If you feel like support me a coffee for my efforts, I would greatly appreciate it.
Buy Me A Coffee

𝙲𝚘𝚗𝚝𝚛𝚒𝚋𝚞𝚝𝚎 🙋‍♂️

Read contribution guidelines for more information regarding contribution.

𝙵𝚎𝚎𝚍𝚋𝚊𝚌𝚔 ✍️

Feature requests are always welcome, File an issue here.

𝙵𝚒𝚗𝚍 𝚝𝚑𝚒𝚜 𝚙𝚛𝚘𝚓𝚎𝚌𝚝 𝚞𝚜𝚎𝚏𝚞𝚕 ? ❤️

Support it by clicking the ⭐ button on the upper right of this page. ✌️

𝙻𝚒𝚌𝚎𝚗𝚜𝚎 Licence 💳

This project is licensed under the Apache License 2.0 - see the LICENSE file for details