nab-challenge
Take home challenge from NAB in partnership with Positive Thinking Company
Software development principles, patterns and practices
Principles
- Program to an interface, not an implementation - Every methods of repository is called through Interface, not their implementation. Because of this, it is easier to add new repositories without changing the implementation
- Seperation of concerns - Seperate the app architecture into layers, each layer has its own responsibility
- Single Responsibility - One method does one thing
- Inversion of Control - Use dependency injection library Hilt to avoid dependencies between components
Patterns
- Observer Pattern - In UI Controllers, observe changes from data in ViewModel to take actions
- Factory Pattern - Use ViewModelFactory to get ViewModel instance based on the type and constructor params
- Builder Pattern - Construct Retrofit, Moshi with builder to avoid calling constructor with so many params
- Singleton Pattern - Make repositories components, API instance as singleton so that there is only one instance of these during the app lifecycle
- MVVM Pattern - Model, View, View-Model for testable code and robust architecture
Practices
- Regex - Used to validate data based on specific format
- Unit test - Make sure that functions run in right way
- Two Way data binding - When the data on the View changes, the binded property in ViewModel will update automatically
- CI/CD with Github Action - Make a build when code in this repository changes. If this fails, notify through email about the result
- DiffUtils - Improve performance of RecyclerView in Android
- Secure app - Use Proguard to minify, obfuscate code, remove unused resource for both
release
anddebug
build
Libraries & frameworks
- Github Action - Create build assembles whenever code is updated
- Timber - Logging
- Retrofit2 - Construct the REST APIs and paging network data
- Moshi - A modern JSON library for Kotlin and Java
- Hilt - A dependency injection library
- AppCompat - Degrade gracefully on older versions of Android
- Test/Junit - An Android testing framework for unit tests
- Data Binding - Declaratively bind observable data to UI elements
- Lifecycles - Create a UI that automatically responds to lifecycle events
- LiveData - Build data objects that notify views when the underlying datasource changes
- Navigation - Handle everything needed for in-app navigation
- Kotlin Coroutine - Handle long running operation outside main thread
Folder structure
data
: Contains mostly code related to acess datanetwork
: Setup code for API service along with its methods to get the datarepository
: Implementation code for the repository in the domain
di
: Dependency Injection modules that are used across the appdomain
: Contains the logic, model accross the app, related to businessdto
: Data Transfer Objects, used to receive data from remote with Json propertiesmodel
: Domain Model Objects, contain data and some logics related to the object in apprepository
: Interface only, define a contract that is needed to access datautils
: Helper methods to handle data
presentation
: Contains the logic, code to display datadailyforecast
: A screen folder, contains its related file such as ViewModel, UI Controller (Fragments, Activities), ViewModelFactoryutils
: Some base or helper methods
Setup
Run by installing APK
- Go to the list of builds created here
- Choose the latest one with green tick (Sucessfully built)
- Download the assemble.zip
- Extract downloaded file and install the APK file
Run in Android Studio
Precondition:
- Android Studio version 4.2.2 and above
- SDK version from 23 to 30
- Emulator from API 23
- Clone this project
- Open in Android Studio
- Click Run
Note for the Average Temperature calculation: Because the Average Temperature is calculated by sum of each measurements, then divided by the times, according to the API, the Average Temperature calculation formula is as below:
Averrage Temperature = SumOf(morning, day, evening, night) / 4
Checklist
- 1. Programming language: Kotlin is required, Java is optional.
- 2. Design app's architecture (suggest MVVM or you can use any architectures that you get familiar)
- 3. Apply LiveData mechanism or any mechanism that you get familiar with
- 4. UI should be looks like in attachment.
- 5. Write UnitTests (nice to have)
- 6. Secure Android app from:
- a. Decompile APK
- b. Rooted device (optional)
- 7. Exception handling (optional)
- 8. Readme file includes:
- a. Brief explanation for the software development principles, patterns & practices being applied
- b. Brief explanation for the code folder structure and the key Java/Kotlin libraries and frameworks being used
- c. All the required steps in order to get the application run on local computer
- d. Checklist of items the candidate has done