Software is never finished. It is impossible to not have bugs and anyone who denies this probably is either unaware of them or conveniently chose to ignore them. But.. code can be in a good state. An easily understandable and readable state. A state where it can be extended and scaled easily, leaving the developer who reads your code with a smile.
I don’t know any programmer who is not guilty of such mistakes including myself. It took me a long time before I could even tell my code was shit because I wasn’t adhering to certain norms or principles. To know the code is shit you should know what is good code. The trick to avoid all the sufferings that comes with a legacy codebase is to avoid writing bad code in the first place. Secondly, get the code reviewed and cleanup as regularly as possible. Whatever be your excuse for not doing it, it is of paramount importance to start writing clean code. A clean codebase not only takes less maintenance time and efforts to maintain but also saves you from pulling your hair out of frustration when you revisit the it again.
So, let’s first understand some common practices and guidelines developers use in the world of Android App development.
General Principles
- Follow the Standard
- Developer Conventions as a “Rule of Thumb”
- Keep It Simple and Stupid.
- Reduce Complexity by avoiding the temptation to over-engineer the problem
- Boy scout rule. Leave the campground cleaner than you found it.
- Always find root cause.
- Always look for the root cause of a problem and DO NOT hack the solution with quick or easy workarounds.
- Specifically, avoid copy pasting StackOverflow solutions. Make sure to use only updated solutions and that solves the problem for your version of app/lib.
Avoid the temptation to over use - Dependencies/Libraries. Always make sure the dependencies are maintained regularly and by reliable sources/developers. Read the issues, reviews and stars.
- SOLID principles all the way for the rescue.
Adhere to the concepts of Object Oriented Programming Paradigm - Take the “Functional Programming” approach for Data flow
- Take time to understand the problem, brainstorm about possible edge cases and ideate about what is the minimal viable way to achieve this with high quality and performant outcome.
- Use core Kotlin features of Null handling, Multithreading etc effectively
- Always use domain level dependencies using Dependency injection framework like Dagger/Koin which fosters testability
Android Architecture
Android advocated MVVM/MVP/MVI architecture with Architecture components, jetpack. It’s not important WHAT Architecture you use but what’s paramount is HOW you use.
Reference link and image credits: https://github.com/ImangazalievM/CleanArchitectureManifest
Design Principles
- Go with the default Material Design components and guidelines for Android
- Do not customise views until absolutely necessary and you know what you are getting into
- Keep the UX intuitive, easy to use and glitch free by tracking memory leaks as
- Garbage collection triggered regularly causes visible delays in UI in extreme cases
- Stick to a theme and make changes only in the style.xml for each widget which makes the theme consistent and ensures consistency in UI
Testing Principles
- Use following test types
- Unit tests
- Integration Tests/API tests
- Instrumentation Tests
- Acceptance tests
- Always cover all the business logic in the Presenters/ViewModels with meaningful tests.
- Calculate code coverage.
- Use one assert per test.
- Make your tests readable, fast, independent and repeatable.
Code Style
- Comments should only be used to document a class or method as a user manual.
- ToDos should go asap.
- Use IDE Kotlin code style.
Guidelines for Productivity
- Learn IDE Shortcuts
- Profile the app regularly for memory and performance
- Keep your gradle build times at check
- Automate CI and PlaysStore Uploads
- Keep an eye regularly on the Firebase dashboard for crashes
Common Mistakes
- Coupling of dependencies
- Poor handling of threads
- Ignoring Memory Leaks
- Ignoring bounds and null
- Not Profiling the app for network, memory and performance
- Hardcoding Passwords and
- Unencrypted tokens
- Hardcoding strings
- Unformatted and
- Unindented Code
- Typos in variable, class name etc.
- Generic functions or methods with multiple responsibilities
- Not using or bad usage of Dependency Injection
- Everything in One BIG Presenter, Controller or ViewModel
- Needless redundancy and copy pasting instead of overloading or overriding
- Rigidity. The software is difficult to change. A small change causes a cascade of subsequent changes.
- Fragility. The software breaks in many places due to a single change.
- Immobility. You cannot reuse parts of the code in other projects because of involved risks and high effort.
- Needless Complexity.
Opacity. The code is hard to understand. - Not following design principles of Android and trying to custom to make it a iOS or web lookalike.
Learning from Netscape
- Never do a complete rewrite.
Finally, choose clean code as a practice. If not, it is easy to end up down a slippery slope of technical debt that piles up before you know it.
Reference Links
Interested in android development? Contact us!