Joining an Android Project
As an Android developer in a 2-people studio, it's common for me to join an existing development team, often as the most senior team member. Most developers prefer starting a new project. But, in real life, it’s more likely that you are going to join an already existing project.
That’s an experience rarely talked about in the industry, but a lot of developers struggle with it. They struggle fitting in, knowing how to improve the state of the project, keep adding new features without introducing new bugs, etc..
That's why talking about this subject is important. It's not about what makes code great, but how you can blend in, interact with the team, and keep productive. And while seasoned developers learn it by instinct, beginners have a lot of questions about it.
So, someone asks you to join an existing project. You need to maintain and build new features on an existing app. And you will have new team members to work with. Let's talk about project auditing, creating work plans, collaborating with team mates and getting things done. The examples will be Android related, but the insights apply to development in general.
An audit is the first thing we do when we have access to an existing project. It can be a formal audit (someone asked you to assess its current state) or informal (you’re just curious). The goal is to get a sense of how complex the project is, and whether it’s taking advantage of the industry best practices.
Here’s a list of things I usually check:
- Development Process
- Version control
- Code reviews
- Quality assurance
- Release process
- Crash monitoring
- Android SDK version
- Versions of major libraries
- Unusual dependencies
- Build tasks
- Package organization
- Styles & themes
- (Vector) Drawables
- Values (strings, dimens…)
- Design Patterns
- Dependency injection
- UI: fragments, custom views…
- Custom Complexity
- External APIs
- Push notifications
- Manual testing plan
- Unit testing
- Instrumentation testing
- Integration testing
- Continuous integration
After an audit, it’s common feel tempted to throw everything to the trash and start over. It’s easy to feel superior to an existing codebase. To be the guy telling everyone how things should be done. But it’s important to be humble at this stage. You don’t have the full picture, what were the original requirements and constraints, in what conditions was the project developed.
Most of the times the team already wanted to improve things, and now they can use you as an excuse. More often than not, they already know the best practices. They just didn't have the experience of how to implement them effectively. And now they can use you, the new guy, as an opportunity to change this.
Discuss, discuss, discuss
The first step to plan anything should be to discuss it with the team. Learn about the challenges they face. What do they fell needs improvement. Gain trust first, then start suggesting changes. Discuss patterns, share examples. Bring every team member to the conversation.
Avoid a big rewrite. Most companies don’t have the budget for it. And they need features implemented and bugs fixed in the meantime. And you still don’t have the full picture, so there’s no guarantee the new version would be any better.
What projects need is continuous improvement.
Regular improvements happen when everyone in the team feels empowered to question how things are being done. And they’re not afraid to change them.
Code reviews are good opportunities to discuss matters with the team. You can discuss on concrete scenarios and suggest alternatives. Be thorough but humble in them. Don't force anything. It's all subjective, so always be willing to compromise on your suggestions. And always be the example to follow on your code submissions.
Everyone should agree on the best practices. New components should follow them. Old components should migrate towards them. It doesn't need to be something complex, there’s no need to go full clean architecture from the start.
Here’s some common low-hanging fruit:
- Group features into packages
- Extract and group external calls:
- API, database, storage, preferences
- Move code out of Android classes:
- Activities, fragments, views, services...
- Break things down
- Prefer small and specific, not big and general
- Abstract use cases
- Prefer ErrorDisplayer instead of SnackbarHelper
- Extract duplicated code (3 times or more)
Let Android Studio help and abuse the refactor. Remember the boy scouts rule: “always leave the campground cleaner than you found it”. Take every chance to improve the code you’re working with. Trying to work around bad code leads to worse decisions. On the other hand, improvements accumulate and help the team feel good about the project.
Automated testing is something still lacking on most Android projects. Writing automated tests on an existing project is big effort short term. And most of the rewards are only felt long term. It’s also more crucial for some business than others. But they are always worth doing, so be persistent about it.
You can write functional tests no matter of how bad the code is. You might need deal with state, API calls, etc.., but you can always do it for any app. Unit tests depend on good code practices, so they’re harder to write on legacy code. Do it’s better to start doing it on new or refactored code.
Some tips: Start testing the more valuable and complex parts; Need to fix a bug? Reproduce it with a test first; Make sure the rest of the team runs the tests as well; Aim to have Continuous Integration to help you out with this
If you run into trouble convincing your colleagues about the importance of automated testing, we wrote a blog post about it.
When all else fails… Get out of there!
Just kidding 😁
Keep working on it. Be persistent. The best decisions shine in the long run.
This blog post comes out of a talk presented at GDG Devfest Lisbon 2017. Here are the slides for reference: