Striving for better code

Recently we refactored our Android’s application navigation system – we replaced fragment transactions with Android Jetpack navigation component. We already had a good experience with migrating from Model View Presenter architecture to Model View View Model architecture (using Android Jetpack Architecture software components). During refactoring we had to convert our existing presenters and views into viewmodels and views with binding expressions. There was a risk of loosing time due doing unplanned activity, therefore before making the decision of migration we carefully estimated the risks related to refactoring. And the main question we were facing with was: will we see a benefit of a refactoring before the app’s release? (We already saw the benefit in a long term, but were not sure about the immediate gain). Calculations showed that even doing refactoring we would gain in development speed. And indeed it turned out that within a month our invested time started to pay off and we started faster implement new use cases even spending additional time on refactoring the existing use cases.

So we started to wonder if it is a worthwhile endeavor to switch to new navigation system. While estimating time for refactoring and immediate benefits I started to think why we started to consider this idea at all. What exactly drives us in making such decisions as going back to already written code and refactor it? And I decided to put some thoughts in this blog about the motivation behind the desire for better code.

I already wrote about clean architecture and design. And in this blog I will return to this topic but from a different angle. Let me first mention that in my experience clean code is very opinionated term because it is not strictly defined by rules but rather by feelings – if the given code is easy to read, perceive, extend, test and maintain it must be a clean code. And different developers this feeling can achieve by different coding approaches. Therefore there will always be disputes about the best language, framework or paradigm. And quite often different developers perceive the same code differently – the one might be convinced that the code is clean because from his perspective it is easy to understand and extend and at the same time another developer will claim that taking a different approach would lead to better code.

Therefore from my point of view it is pointless to argue only about the approaches in coding, but the languages, frameworks or paradigms should be discussed together with the measurable results these different approaches yield. And only then we can talk about the clean code.

And one such measurable indicator that we looked at, while were considering migration to the new Jetpack components, was overall development speed.

And here I want to emphasize the word overall, because initially coding in dirty way is much faster than structuring code and only after awhile the well written code starts to shine and only then the terms testable, extendable, maintainable really start to make sense for you. Actually I don’t see anything wrong in writing one big chunk of spaghetti code if all developers who work now and will work on such code in the future can understand it, test it and extend it as fast as very well structured code. But this is never the case, unless the developer is some kind of genius, and even then you need to make sure that every developer in a team is a same level genius. So that is why the abstraction levels were raised, that we don’t have to write mathematical expressions and well known business logic in machine code. That is why different paradigms were invented that we faster and easier grasp the problems we are coding. And that is why patterns and best practices are used that we can solve the problems faster and every developer can understand the solution. From the other hand the computer or the phone that runs our software doesn’t care about the code we wrote because it doesn’t use our code but the code produced by compiler or interpreter. The very bad code (from developers point of view) can be converted to the same machine code, that is produced from very well written code. Unfortunately in most cases the only people who care about the code quality are developers. No one else really care about it – stake holders, managers and users care only about the end result. As long as the application meets the requirements it is good enough to use it. But for us developers the well written code can greatly shorten development time and bring a peace in our mind.

But how come we get so much code which doesn’t follow the clean code principles? One obvious reason is lack of experience. At some point of time we developers all have written poor code, just because we didn’t now how to write it better, but along the time we learned and reached a certain level of mastery. Shouldn’t we write now only a clean code? Unfortunately no, and there are several reasons for it. The one we learned while migrating to Jetpack components is: it doesn’t matter how good the code is now there is always a room for improvement, we just don’t know yet how to do it.

FitRadar application versioning

In the last post, I wrote about FitRadar application’s release process and what kind of releases we are planning to have. And since every release is having a unique version number, I think it is a good time to talk about the release of versioning schemes in this post.

In our app we are planning to use the Semantic versioning schema that follows this pattern: Major.Minor.Patch, where

  • Major number will be increased by 1 when breaking changes will be introduced that are incompatible with the previous Major version
  • Minor number will be increased by 1 when a new functionality will be introduced that is backward compatible (at the same time patch number will be reset to zero)
  • Patch number will be increased by 1 when a bug or set of bugs will be fixed that is backward compatible

But before we can start to apply Semantic versioning schema we still have to reach the phase when the application is stable and ready for production and that will be version 1.0.0. But until then when we are still in the development phase we are using a little bit different versioning schema that follows the pattern 0.x.y.

Our versioning schema during the development phase is tightly coupled with the application development life-cycle. In the very beginning of our project, we decided to adopt some of the Scrum project management aspects, particularly sprints or iterations. The length of the sprint is such that our team can deliver at least one use case from the user requirement list. Mostly but not always after every sprint we release an application with new major version x. Every application release can contain one or more use cases. During a sprint beside a new user story, we have to fix bugs or make improvements in the previous user story. When a bug was fixed or improvement made we release a new version with increased minor number y. It means that our application started with version 0.1.0 when the first use case was implemented.

Once we started to release our application to Google Play Store tracks we extended application version with an additional label denoting the track like this 0.x.y-track_name.

As you can see this versioning schema is not quite suitable for the production where each release should be stable and finalized. But during the development phase when each use case is iterated several times and after each iteration, we should have an application that we can install, demonstrate and test, this kind of versioning schema serves us very well.

http://fitradar.me/