It’s hard to add new features to a product when the base code is imperfect. Plus, existing bugs further slow down the product development process.
Just like many other early stage, fast-paced organizations, we were managing a project where the code was dreadfully cluttered due to multiple, rapid changes in the features based on customer feedback and an incomplete understanding of what a good Android architecture should look like.
We had fragments and classes that had codes ranging from 5000 Lines of Code (LOC) to 8000 LOC, violating clean code principles all over. We therefore decided to first clean up the code before the problem got worse.
In this post, we'll discuss:
● How we identified and fixed the issues in our code.
● How we didn't let migration and refactoring get in the way of sprints and deliverables.
● How anyone can adopt our methodology to write amazing Android applications with clean architecture.
Here’s a list of questions that’ll help you decide if your code needs minor cleaning up or if it needs refactoring.
● Does your code follow any coding architecture? Do words like Model-View-ViewModel (MVVM) or Model-View-Presenter (MVP) sound familiar? If the answer is yes, you need to plan for a major refactoring.
● Null pointer, illegal state, or out-of-memory exceptions are common? A few major cleanups might do the trick if you have set up an architecture with not-the-best-implementation.
● Does your code have cyclic dependencies? These are relatively difficult to fix. You need proper planning and an understanding of coding principles to clean up.
● Are the file sizes too big? If your answers to the above questions are no, then just splitting the larger files into smaller files should be a piece of cake.
We, as a rule for all similar projects, identify roadblocks before we begin to migrate or refactor the code to avoid costly surprises later.
● Set reasonable timelines for the project so that the cleanup initiative doesn’t turn messy due to a lack of time.
● We ensure that the refactoring has minimal impact on the current functionality of the product, and provide a team that’ll execute fast.
● Sprint Time — Deliverables will slow down for the next few sprints, and it is advisable to keep all the stakeholders in the loop to avoid any last minute surprises.
● Refactor feature by feature, in small chunks, to avoid any major breakdowns in the rest of the product now, or later.
● Product and code knowledge will speed up the whole process, irrespective of file size. In-depth prior understanding of this is key.
● Refactoring the app when it is already in production increases the overall risk. Make sure that end users are not impacted because of the decisions taken by developers and that they receive timely updates.
● Identify the features — Identify all the features of the app. Ad hoc changes or removals of code can cause unrecoverable damage, thereby increasing the overall time taken to refactor. Though messed up, our code had no or minimal hard coupling, and we could target one class at a time.
● Source control setup — Correct branching strategy in Git helped us track the changes correctly and revert to the stable version in case anything did not work as expected.
● Architecture — After some adequate research, we selected MVVM architecture for our code and decided to migrate the whole code base to MVVM since it was the best fit for our requirements. MVP architecture is equally good for smaller and simpler projects.
● Technology — We made smart decisions, and evaluated and chose our tech stack before starting the process with extensive research.
● Classes or files to target — We created a priority list of which tasks and codes to target first to keep the migration organized.
● Code Quality Setup — We added SonarQube to the project to make sure it keeps reporting all the unnoticed bugs and errors, and then we treated it like a checklist for the code cleanup process.
● Database management — Using Realm or SQLite or Room sounds straightforward, but we created an intelligent design to make it sustainable.
● Profiling — App profiling is one of the key factors that helped us improve the code. We used profiling metrics as proof of concept for the assumptions made during the cleanups. It convinces the stakeholders easily too.
● Test cases — We started simple, and then detailed out our test cases. It helped speed up the cleanup process significantly.
● Documentation — We prepared for the eventuality that other people will be working on this code and documented all our utility codes and business logic.
● Getting rid of the helper class— Helper.java, Utils.java, or Commons.java in almost all projects start as common reusable code and end up being a dumping ground. The size eventually crosses 5000 LOC. So we refactored these into dedicated classes.
● Resource cleanups — Unused or improperly created resources in the resources folder may cause major issues.
● Continuous integration (CI) checklist — This is easier for those who work on CI tools like Bitrise, Github actions, or Jenkins. We created a checklist of items to include in the CI workflow to make the integration smooth across the work of different developers. A simple checklist could include a Gradle test that validates both the code compilation and test cases. Adding SonarQube or SonarCloud to the pipeline is always a plus.
● Distribution of tasks — It is very important to understand that code cleanups are best done with minimal or no overlaps across developers.
● Never start a refactoring process without going through the checklist above, or create your own checklist if required
● Never start refactoring until you know what each part of the application does
● Always make sure that a proper source control environment like Github is set up and branching rules are strictly defined
● Don't mix refactoring and feature updates
● When refactoring, change only the structure of the code, not the functionality. We optimized the code logic only after it was refactored and merged into the stable branch of the code
Once we had all of the above in place, we started the cleanup. Please note that the sequence of these operations plays a crucial role.
● We added some utility libraries like Lombok that eliminated most of the boilerplate code and added SonarQube to identify code quality issues at an early stage.
● We added Kotlin support and migrated the code that we'd need to refactor or break. AndroidStudio converts existing Java code to Kotlin without requiring any major monitoring.
● We added Dagger 2 to introduce dependency injection.
● We used data binding to introduce the MVVM architecture. i.e. Our view was in the XML files which were linked to the reactive model. This reduced the code size, and made it more readable and manageable. It also eliminated if else, setter, and getter.
● We cleaned up the layout files to reduce multiple renderings. We moved to constraint layouts and removed old layouts and nesting.
● We divided the code into multiple independent logical units or modules. We shared and assigned among all the developers to have minimal overlaps and bugs during the process.
● We added Gradle scripts to introduce environments and build scripts that optimize the builds for different environments like dev, stage, and production.
● We optimized the ProGuard to obfuscate the code.
● We added JaCoCo for code coverage along with SonarQube.
● We set up Bitrise as our CI/CD tool to build and test the app on every pull request. It also generated the quality report and we merged the codes only when the minimum requirement set was met.
● We then introduced a repository pattern to the application to make handling Realm more efficient. This eliminated most of our transaction bugs.
● We introduced ViewModels to handle business logic and view manipulations. Our code in activities and fragments were trimmed and distributed to multiple classes. One key thing to remember is to try and maintain single direction dependencies.
● We made sure that the lower order classes had a single responsibility and were reusable.
● We reduced classes that needed the “Android context” to work. This allowed us to write unit tests much faster, without worrying about how the business logic will work based on the underlying operating system, overall future-proofing the app.
● We replaced most of the hard references, especially wherever async operations were involved, with SoftReference or WeakReference. This reduced our memory footprint drastically.
● We kept profiling performance regularly to make sure that our changes are improving performance too and not accidentally increasing memory usage.
● We then cleaned up our resources. We used correct-size images and copy for all different screen densities, reducing overall memory impact. The larger the image, the larger the impact will be while rendering. Using the wrong storage folder may lead to unexpected image scaling and out-of-memory (OOM) issues.
● We also cleaned up colors.xml and strings.xml to remove all the hardcoding from layout files and Java classes, and then externalized all the resources.
It took us six months to refactor the whole code gradually to a cleaner and manageable version. Later we introduced RxJava to further clean up the code, specially in case of asynchronous code and business logic. We were earlier using traditional callbacks, listeners and runOnUi codes, and they soon started becoming unmanageable.
One advantage of planned refactoring is getting results incrementally. It's also easier to verify progress. Here are some of the key outcomes from our overall refactoring effort.
● Reduction in overall app size from 108MB to 37MB
● Improved performance
● Reduced bugs
● Stabilized application with test cases
● More readable and manageable code
● Increased security with improved auth flow and data fetching
● Faster delivery with CI/CD
● Easier tracking with Changelogs and APK
When the app is already in production, the stakes are higher. Here’s how to transition smoother.
● Do not make the whole team work on the refactoring. While a part of the team can work on refactoring old code, other developers can continue working on new features, but with planned and finalized architecture.
● Begin with the architecture setup, like adding dagger, databinding, unit tests, etc. without actually making changes to other files. Test and merge it to a stable branch so that other developers can still continue building new features on top of it.
● Refactor in smaller chunks, test, and deliver. This will take longer to refactor, but will unblock the deliverables and reduce the overall impact on users who are already using the app.
● Plan for a controlled distribution release. Release the refactored app to a small set of users first, and keep tracking the behavior. If it all looks good, then gradually increase the distribution percentage.
● Understanding the front end architecture and memory impact on the underlying device is crucial
● Understanding and applying SOLID principles improves overall code quality
● Don't ignore some basic warnings to prevent long-term fall-out
● Regularly upgrade the libraries, and understanding the change-log to identify any breaking changes
● Always document the code. Maintain a README.md with build steps, instructions, and other important notes to keep all the existing and new developers aware of the whole application
A version of this blog post was earlier published on Medium.
It’s hard to add new features to a product when the base code is imperfect. Plus, existing bugs further slow down the product development process.
Just like many other early stage, fast-paced organizations, we were managing a project where the code was dreadfully cluttered due to multiple, rapid changes in the features based on customer feedback and an incomplete understanding of what a good Android architecture should look like.
We had fragments and classes that had codes ranging from 5000 Lines of Code (LOC) to 8000 LOC, violating clean code principles all over. We therefore decided to first clean up the code before the problem got worse.
In this post, we'll discuss:
● How we identified and fixed the issues in our code.
● How we didn't let migration and refactoring get in the way of sprints and deliverables.
● How anyone can adopt our methodology to write amazing Android applications with clean architecture.
Here’s a list of questions that’ll help you decide if your code needs minor cleaning up or if it needs refactoring.
● Does your code follow any coding architecture? Do words like Model-View-ViewModel (MVVM) or Model-View-Presenter (MVP) sound familiar? If the answer is yes, you need to plan for a major refactoring.
● Null pointer, illegal state, or out-of-memory exceptions are common? A few major cleanups might do the trick if you have set up an architecture with not-the-best-implementation.
● Does your code have cyclic dependencies? These are relatively difficult to fix. You need proper planning and an understanding of coding principles to clean up.
● Are the file sizes too big? If your answers to the above questions are no, then just splitting the larger files into smaller files should be a piece of cake.
We, as a rule for all similar projects, identify roadblocks before we begin to migrate or refactor the code to avoid costly surprises later.
● Set reasonable timelines for the project so that the cleanup initiative doesn’t turn messy due to a lack of time.
● We ensure that the refactoring has minimal impact on the current functionality of the product, and provide a team that’ll execute fast.
● Sprint Time — Deliverables will slow down for the next few sprints, and it is advisable to keep all the stakeholders in the loop to avoid any last minute surprises.
● Refactor feature by feature, in small chunks, to avoid any major breakdowns in the rest of the product now, or later.
● Product and code knowledge will speed up the whole process, irrespective of file size. In-depth prior understanding of this is key.
● Refactoring the app when it is already in production increases the overall risk. Make sure that end users are not impacted because of the decisions taken by developers and that they receive timely updates.
● Identify the features — Identify all the features of the app. Ad hoc changes or removals of code can cause unrecoverable damage, thereby increasing the overall time taken to refactor. Though messed up, our code had no or minimal hard coupling, and we could target one class at a time.
● Source control setup — Correct branching strategy in Git helped us track the changes correctly and revert to the stable version in case anything did not work as expected.
● Architecture — After some adequate research, we selected MVVM architecture for our code and decided to migrate the whole code base to MVVM since it was the best fit for our requirements. MVP architecture is equally good for smaller and simpler projects.
● Technology — We made smart decisions, and evaluated and chose our tech stack before starting the process with extensive research.
● Classes or files to target — We created a priority list of which tasks and codes to target first to keep the migration organized.
● Code Quality Setup — We added SonarQube to the project to make sure it keeps reporting all the unnoticed bugs and errors, and then we treated it like a checklist for the code cleanup process.
● Database management — Using Realm or SQLite or Room sounds straightforward, but we created an intelligent design to make it sustainable.
● Profiling — App profiling is one of the key factors that helped us improve the code. We used profiling metrics as proof of concept for the assumptions made during the cleanups. It convinces the stakeholders easily too.
● Test cases — We started simple, and then detailed out our test cases. It helped speed up the cleanup process significantly.
● Documentation — We prepared for the eventuality that other people will be working on this code and documented all our utility codes and business logic.
● Getting rid of the helper class— Helper.java, Utils.java, or Commons.java in almost all projects start as common reusable code and end up being a dumping ground. The size eventually crosses 5000 LOC. So we refactored these into dedicated classes.
● Resource cleanups — Unused or improperly created resources in the resources folder may cause major issues.
● Continuous integration (CI) checklist — This is easier for those who work on CI tools like Bitrise, Github actions, or Jenkins. We created a checklist of items to include in the CI workflow to make the integration smooth across the work of different developers. A simple checklist could include a Gradle test that validates both the code compilation and test cases. Adding SonarQube or SonarCloud to the pipeline is always a plus.
● Distribution of tasks — It is very important to understand that code cleanups are best done with minimal or no overlaps across developers.
● Never start a refactoring process without going through the checklist above, or create your own checklist if required
● Never start refactoring until you know what each part of the application does
● Always make sure that a proper source control environment like Github is set up and branching rules are strictly defined
● Don't mix refactoring and feature updates
● When refactoring, change only the structure of the code, not the functionality. We optimized the code logic only after it was refactored and merged into the stable branch of the code
Once we had all of the above in place, we started the cleanup. Please note that the sequence of these operations plays a crucial role.
● We added some utility libraries like Lombok that eliminated most of the boilerplate code and added SonarQube to identify code quality issues at an early stage.
● We added Kotlin support and migrated the code that we'd need to refactor or break. AndroidStudio converts existing Java code to Kotlin without requiring any major monitoring.
● We added Dagger 2 to introduce dependency injection.
● We used data binding to introduce the MVVM architecture. i.e. Our view was in the XML files which were linked to the reactive model. This reduced the code size, and made it more readable and manageable. It also eliminated if else, setter, and getter.
● We cleaned up the layout files to reduce multiple renderings. We moved to constraint layouts and removed old layouts and nesting.
● We divided the code into multiple independent logical units or modules. We shared and assigned among all the developers to have minimal overlaps and bugs during the process.
● We added Gradle scripts to introduce environments and build scripts that optimize the builds for different environments like dev, stage, and production.
● We optimized the ProGuard to obfuscate the code.
● We added JaCoCo for code coverage along with SonarQube.
● We set up Bitrise as our CI/CD tool to build and test the app on every pull request. It also generated the quality report and we merged the codes only when the minimum requirement set was met.
● We then introduced a repository pattern to the application to make handling Realm more efficient. This eliminated most of our transaction bugs.
● We introduced ViewModels to handle business logic and view manipulations. Our code in activities and fragments were trimmed and distributed to multiple classes. One key thing to remember is to try and maintain single direction dependencies.
● We made sure that the lower order classes had a single responsibility and were reusable.
● We reduced classes that needed the “Android context” to work. This allowed us to write unit tests much faster, without worrying about how the business logic will work based on the underlying operating system, overall future-proofing the app.
● We replaced most of the hard references, especially wherever async operations were involved, with SoftReference or WeakReference. This reduced our memory footprint drastically.
● We kept profiling performance regularly to make sure that our changes are improving performance too and not accidentally increasing memory usage.
● We then cleaned up our resources. We used correct-size images and copy for all different screen densities, reducing overall memory impact. The larger the image, the larger the impact will be while rendering. Using the wrong storage folder may lead to unexpected image scaling and out-of-memory (OOM) issues.
● We also cleaned up colors.xml and strings.xml to remove all the hardcoding from layout files and Java classes, and then externalized all the resources.
It took us six months to refactor the whole code gradually to a cleaner and manageable version. Later we introduced RxJava to further clean up the code, specially in case of asynchronous code and business logic. We were earlier using traditional callbacks, listeners and runOnUi codes, and they soon started becoming unmanageable.
One advantage of planned refactoring is getting results incrementally. It's also easier to verify progress. Here are some of the key outcomes from our overall refactoring effort.
● Reduction in overall app size from 108MB to 37MB
● Improved performance
● Reduced bugs
● Stabilized application with test cases
● More readable and manageable code
● Increased security with improved auth flow and data fetching
● Faster delivery with CI/CD
● Easier tracking with Changelogs and APK
When the app is already in production, the stakes are higher. Here’s how to transition smoother.
● Do not make the whole team work on the refactoring. While a part of the team can work on refactoring old code, other developers can continue working on new features, but with planned and finalized architecture.
● Begin with the architecture setup, like adding dagger, databinding, unit tests, etc. without actually making changes to other files. Test and merge it to a stable branch so that other developers can still continue building new features on top of it.
● Refactor in smaller chunks, test, and deliver. This will take longer to refactor, but will unblock the deliverables and reduce the overall impact on users who are already using the app.
● Plan for a controlled distribution release. Release the refactored app to a small set of users first, and keep tracking the behavior. If it all looks good, then gradually increase the distribution percentage.
● Understanding the front end architecture and memory impact on the underlying device is crucial
● Understanding and applying SOLID principles improves overall code quality
● Don't ignore some basic warnings to prevent long-term fall-out
● Regularly upgrade the libraries, and understanding the change-log to identify any breaking changes
● Always document the code. Maintain a README.md with build steps, instructions, and other important notes to keep all the existing and new developers aware of the whole application
A version of this blog post was earlier published on Medium.
It’s hard to add new features to a product when the base code is imperfect. Plus, existing bugs further slow down the product development process.
Just like many other early stage, fast-paced organizations, we were managing a project where the code was dreadfully cluttered due to multiple, rapid changes in the features based on customer feedback and an incomplete understanding of what a good Android architecture should look like.
We had fragments and classes that had codes ranging from 5000 Lines of Code (LOC) to 8000 LOC, violating clean code principles all over. We therefore decided to first clean up the code before the problem got worse.
In this post, we'll discuss:
● How we identified and fixed the issues in our code.
● How we didn't let migration and refactoring get in the way of sprints and deliverables.
● How anyone can adopt our methodology to write amazing Android applications with clean architecture.
Here’s a list of questions that’ll help you decide if your code needs minor cleaning up or if it needs refactoring.
● Does your code follow any coding architecture? Do words like Model-View-ViewModel (MVVM) or Model-View-Presenter (MVP) sound familiar? If the answer is yes, you need to plan for a major refactoring.
● Null pointer, illegal state, or out-of-memory exceptions are common? A few major cleanups might do the trick if you have set up an architecture with not-the-best-implementation.
● Does your code have cyclic dependencies? These are relatively difficult to fix. You need proper planning and an understanding of coding principles to clean up.
● Are the file sizes too big? If your answers to the above questions are no, then just splitting the larger files into smaller files should be a piece of cake.
We, as a rule for all similar projects, identify roadblocks before we begin to migrate or refactor the code to avoid costly surprises later.
● Set reasonable timelines for the project so that the cleanup initiative doesn’t turn messy due to a lack of time.
● We ensure that the refactoring has minimal impact on the current functionality of the product, and provide a team that’ll execute fast.
● Sprint Time — Deliverables will slow down for the next few sprints, and it is advisable to keep all the stakeholders in the loop to avoid any last minute surprises.
● Refactor feature by feature, in small chunks, to avoid any major breakdowns in the rest of the product now, or later.
● Product and code knowledge will speed up the whole process, irrespective of file size. In-depth prior understanding of this is key.
● Refactoring the app when it is already in production increases the overall risk. Make sure that end users are not impacted because of the decisions taken by developers and that they receive timely updates.
● Identify the features — Identify all the features of the app. Ad hoc changes or removals of code can cause unrecoverable damage, thereby increasing the overall time taken to refactor. Though messed up, our code had no or minimal hard coupling, and we could target one class at a time.
● Source control setup — Correct branching strategy in Git helped us track the changes correctly and revert to the stable version in case anything did not work as expected.
● Architecture — After some adequate research, we selected MVVM architecture for our code and decided to migrate the whole code base to MVVM since it was the best fit for our requirements. MVP architecture is equally good for smaller and simpler projects.
● Technology — We made smart decisions, and evaluated and chose our tech stack before starting the process with extensive research.
● Classes or files to target — We created a priority list of which tasks and codes to target first to keep the migration organized.
● Code Quality Setup — We added SonarQube to the project to make sure it keeps reporting all the unnoticed bugs and errors, and then we treated it like a checklist for the code cleanup process.
● Database management — Using Realm or SQLite or Room sounds straightforward, but we created an intelligent design to make it sustainable.
● Profiling — App profiling is one of the key factors that helped us improve the code. We used profiling metrics as proof of concept for the assumptions made during the cleanups. It convinces the stakeholders easily too.
● Test cases — We started simple, and then detailed out our test cases. It helped speed up the cleanup process significantly.
● Documentation — We prepared for the eventuality that other people will be working on this code and documented all our utility codes and business logic.
● Getting rid of the helper class— Helper.java, Utils.java, or Commons.java in almost all projects start as common reusable code and end up being a dumping ground. The size eventually crosses 5000 LOC. So we refactored these into dedicated classes.
● Resource cleanups — Unused or improperly created resources in the resources folder may cause major issues.
● Continuous integration (CI) checklist — This is easier for those who work on CI tools like Bitrise, Github actions, or Jenkins. We created a checklist of items to include in the CI workflow to make the integration smooth across the work of different developers. A simple checklist could include a Gradle test that validates both the code compilation and test cases. Adding SonarQube or SonarCloud to the pipeline is always a plus.
● Distribution of tasks — It is very important to understand that code cleanups are best done with minimal or no overlaps across developers.
● Never start a refactoring process without going through the checklist above, or create your own checklist if required
● Never start refactoring until you know what each part of the application does
● Always make sure that a proper source control environment like Github is set up and branching rules are strictly defined
● Don't mix refactoring and feature updates
● When refactoring, change only the structure of the code, not the functionality. We optimized the code logic only after it was refactored and merged into the stable branch of the code
Once we had all of the above in place, we started the cleanup. Please note that the sequence of these operations plays a crucial role.
● We added some utility libraries like Lombok that eliminated most of the boilerplate code and added SonarQube to identify code quality issues at an early stage.
● We added Kotlin support and migrated the code that we'd need to refactor or break. AndroidStudio converts existing Java code to Kotlin without requiring any major monitoring.
● We added Dagger 2 to introduce dependency injection.
● We used data binding to introduce the MVVM architecture. i.e. Our view was in the XML files which were linked to the reactive model. This reduced the code size, and made it more readable and manageable. It also eliminated if else, setter, and getter.
● We cleaned up the layout files to reduce multiple renderings. We moved to constraint layouts and removed old layouts and nesting.
● We divided the code into multiple independent logical units or modules. We shared and assigned among all the developers to have minimal overlaps and bugs during the process.
● We added Gradle scripts to introduce environments and build scripts that optimize the builds for different environments like dev, stage, and production.
● We optimized the ProGuard to obfuscate the code.
● We added JaCoCo for code coverage along with SonarQube.
● We set up Bitrise as our CI/CD tool to build and test the app on every pull request. It also generated the quality report and we merged the codes only when the minimum requirement set was met.
● We then introduced a repository pattern to the application to make handling Realm more efficient. This eliminated most of our transaction bugs.
● We introduced ViewModels to handle business logic and view manipulations. Our code in activities and fragments were trimmed and distributed to multiple classes. One key thing to remember is to try and maintain single direction dependencies.
● We made sure that the lower order classes had a single responsibility and were reusable.
● We reduced classes that needed the “Android context” to work. This allowed us to write unit tests much faster, without worrying about how the business logic will work based on the underlying operating system, overall future-proofing the app.
● We replaced most of the hard references, especially wherever async operations were involved, with SoftReference or WeakReference. This reduced our memory footprint drastically.
● We kept profiling performance regularly to make sure that our changes are improving performance too and not accidentally increasing memory usage.
● We then cleaned up our resources. We used correct-size images and copy for all different screen densities, reducing overall memory impact. The larger the image, the larger the impact will be while rendering. Using the wrong storage folder may lead to unexpected image scaling and out-of-memory (OOM) issues.
● We also cleaned up colors.xml and strings.xml to remove all the hardcoding from layout files and Java classes, and then externalized all the resources.
It took us six months to refactor the whole code gradually to a cleaner and manageable version. Later we introduced RxJava to further clean up the code, specially in case of asynchronous code and business logic. We were earlier using traditional callbacks, listeners and runOnUi codes, and they soon started becoming unmanageable.
One advantage of planned refactoring is getting results incrementally. It's also easier to verify progress. Here are some of the key outcomes from our overall refactoring effort.
● Reduction in overall app size from 108MB to 37MB
● Improved performance
● Reduced bugs
● Stabilized application with test cases
● More readable and manageable code
● Increased security with improved auth flow and data fetching
● Faster delivery with CI/CD
● Easier tracking with Changelogs and APK
When the app is already in production, the stakes are higher. Here’s how to transition smoother.
● Do not make the whole team work on the refactoring. While a part of the team can work on refactoring old code, other developers can continue working on new features, but with planned and finalized architecture.
● Begin with the architecture setup, like adding dagger, databinding, unit tests, etc. without actually making changes to other files. Test and merge it to a stable branch so that other developers can still continue building new features on top of it.
● Refactor in smaller chunks, test, and deliver. This will take longer to refactor, but will unblock the deliverables and reduce the overall impact on users who are already using the app.
● Plan for a controlled distribution release. Release the refactored app to a small set of users first, and keep tracking the behavior. If it all looks good, then gradually increase the distribution percentage.
● Understanding the front end architecture and memory impact on the underlying device is crucial
● Understanding and applying SOLID principles improves overall code quality
● Don't ignore some basic warnings to prevent long-term fall-out
● Regularly upgrade the libraries, and understanding the change-log to identify any breaking changes
● Always document the code. Maintain a README.md with build steps, instructions, and other important notes to keep all the existing and new developers aware of the whole application
A version of this blog post was earlier published on Medium.