Stanislav Grujic https://www.stanislavgrujic.com Helping software developers write easy to read and maintainable code. Thu, 12 Apr 2018 07:31:21 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 115562609 Source control commit messages https://www.stanislavgrujic.com/2017/02/11/114/ https://www.stanislavgrujic.com/2017/02/11/114/#comments Sat, 11 Feb 2017 17:04:09 +0000 http://www.stanislavgrujic.com/?p=114 Continue reading Source control commit messages ]]> It might seem to many that this topic is quite insignificant, and should not take much space in the programming blogosphere. If you ever had to browse the history of several dozens of commits, trying to figure out which changes could have introduced a bug, and more importantly why, you understand the importance of it, for sure.

The issue with the generic commit messages is that they don’t provide enough history information. Once you find yourself looking into the file history, you’ll appreciate all the additional effort to which you, or your colleague, has put into thinking of a meaningful commit message. When you think about it, it’s not that much of an effort to think about what you have done and put it into writings for your future self.

You should avoid at all costs messages which don’t say what and why have you done changing the file. Examples of such messages are:

  • blah – when you are pressed by your deadlines, you may think that you don’t have time to think about the messages you write. You may be tempted to just put anything into commit message to fool the commit policy checker. Still, once you get to read it, looking for a reason and place where a bug was introduced, the only one feeling like a fool will be you, reading just blah, blah, blah.
  • Fixed issue, small fixes, further improvements, refactoring – once your project reaches mature stage, most probably many files will be touched in various bug fixes, improvements or refactoring. Having commit messages like these will only give you a hard time reading the file history and figuring out what was introduced when, and more importantly why.
  • [#ISSUE_NUMBER] – this one is a bit better, because it ties the changes you made to a story where, hopefully, exists a detailed explanation of what and why needed to be changed at that moment. On the other hand, when you read commit history, the issue number, without an additional message doesn’t give you any information about the changes made. In order to figure out what happened there, you would need to go to your issue tracking system and read the description. Going back and forth between the source control and issue tracking system can take quite some time and energy.

Could you figure out which changes are made for each of these commits?

Commit messages - bad example

You must be wondering, what would be a good commit message then, if none of the above is.

Well, it’s a bit difficult to answer the question easily, but think how would it feel if you were able to read the project history as a story. Each line (commit message) should give you a hint of the changes that were pushed with it, and the context, why the given change was made. That would allow you to be able to figure out what was changed, just by quickly reading through it, without the need to actually look at the code changes, to see if the change in that particular commit could have potentially introduced the bug you’re fixing.

Have a look at these commit messages, taken from the Spring Boot history. You can get a pretty good idea about what was changed.

Commit messages - good example

By now, I hope that you have a pretty good idea why good commit messages matter.

For a nice guideline on how to structure your commit messages, you could have a look at the Git documentation, chapter on Commit Guidelines.

How do you write your commit messages? Please feel free to share your thoughts.

]]>
https://www.stanislavgrujic.com/2017/02/11/114/feed/ 2 114
Magic literals issue – refactoring case 1 https://www.stanislavgrujic.com/2017/01/14/magic-literals-issue-refactoring-case-1/ https://www.stanislavgrujic.com/2017/01/14/magic-literals-issue-refactoring-case-1/#comments Sat, 14 Jan 2017 10:05:58 +0000 http://www.stanislavgrujic.com/?p=99 Continue reading Magic literals issue – refactoring case 1 ]]> Recently I got to fix a bug that was reported in our system, that the system does not allow PINs of odd length. So, when I looked into the code, I was really surprised to see the way that PIN block Format-1 encoding is implemented. It had several really bad coding practices. I thought it would be good to share it with you, and point out the things that are problematic, in my opinion.

Below you can see how the basic method looks like.

PIN format 1 original implementation

As you can see, there are several hardcoded literals in the method. For me, it was difficult to understand the algorithm for PIN block format 1 (a.k.a ISO-1) encoding is supposed to be applied, just from the reading this method. To understand it better I had to look at the actual definition of how should the PIN block format 1 be implemented. This is, in my opinion, the first issue with the method above – you have to move away from the code to be able to understand what and how the code works. For some complex things it’s always good to consult the available documentation, to make sure you understand the flow. On the other hand, for something simple such as PIN block encoding, I think the code should be written well enough that you don’t have to look further.

Let’s try to read this method and figure out what it does:
  1. Initialize the byte array of length 8 as the resulting pin block – OK, that sounds clear enough.
  2. Convert string “14” to packed BCD and add to the result value, at the first position – it’s really not clear why “14″ is used here, but let’s move on and see what we’ll find.
  3. Convert plain PIN to packed BCD – clear.
  4. Copy packed BCD representation bytes to the result value, one by one – this also looks a bit off, but it’s not clear what the issue is at the first reading of the method.
  5. Create a temporary variable with prefix ‘rnd’, suggesting random, with not so random value “7743438284” – this is really smelly, but ok, we’ll see.

Without knowing exactly the algorithm to create PIN block format 1, it’s not clear what exactly should be done to create it, just by reading this method.

Except for hardcoded values, one more problem that I find with the method above, is that every now and then I have to switch my thoughts and think about what does the method stringToPackedBcd do. I think that it is breaking the reading flow. Creation of the PIN block is interrupted each time by conversion to BCT. You can see in the refactored solution that my proposal is to encode PIN to PIN block and only after you are done with it, convert it to BCD, in a single step.

Below you can find the implementation of the stringToPackedBcd method.

Can you spot the bug(s), after reading these two methods?

You can visit this page to make sure you understand the PIN block format 1 encoding.

After reading the PIN block format 1 description, I figured out that there is not one, not two, but four bugs in the code. I will not torture you anymore with the uncertainty, here are the issues:
  1. Hardcoded value “14” – first part is fine, since it represents the PIN block format version, but the value 4 represents the PIN length. It should be deducted from the actual PIN length, not set to 4 always.
  2. PIN conversion to BCD and copying to the result value – it actually copies only the first four digits from the BCD encoded PIN, not the complete value.
  3. Random filler values are not random at all, but rather a hardcoded string value.
  4. The last one is the issue that caused a bug report – if the value passed to the BCD encoding method is not of even length, an exception will be thrown.

If you take a better look you will see that the method stringToPackedBcd declares one parameter, which is incorrectly named pin. Only in one call to this method the actual PIN is passed as an argument, in all other cases, it is just a numeric value that needs conversion.

Since the code had so many issues, I decided to rewrite it, and to make it more readable. Below you can see the new version of the method.

As you can see, the method now has a flow that clearly depicts the algorithm for PIN block format 1 encoding. Reading the method is straightforward and the conversion to BCD is performed only once, after the complete PIN block is created.
Also, you can see that the code is much more readable when you use constants with meaningful names, instead of the hardcoded values. You may know what it represents at the moment of writing, but you will most probably forget the meaning after some time, when you come back to the code.

You can find the complete refactoring case in my GitHub repository.

I’ll be happy to hear your thoughts and ideas for further improvements.

]]>
https://www.stanislavgrujic.com/2017/01/14/magic-literals-issue-refactoring-case-1/feed/ 1 99
Dependent method calls https://www.stanislavgrujic.com/2016/10/08/dependent-method-calls/ https://www.stanislavgrujic.com/2016/10/08/dependent-method-calls/#respond Sat, 08 Oct 2016 06:18:37 +0000 http://www.stanislavgrujic.com/?p=91 Continue reading Dependent method calls ]]> Recently I came across a Java library which gave me much headaches. There are several things that I don’t like in it, but I will explain one that caused me to have to investigate a strange behavior for several hours.

What has happened is that I was calling methods declared on a class in a wrong order. To explain, this code:

SomeClass someClassInstance = new SomeClass();
someClassInstance.method2();
someClassInstance.method1();

was causing an exception which did not give much details on what I’m doing wrong. It took me several hours to figure out that in order to be able to finish what I was doing, I had to do the method calls in the reverse order:

SomeClass someClassInstance = new SomeClass();
someClassInstance.method1();
someClassInstance.method2();

Unfortunately, this was not documented clearly, neither in the Javadoc, nor on the tutorials available online.

My opinion is that when you design your class, you should never have exposed methods which depend on other method execution. There is no guarantee that the user of your class will figure out that he needs to invoke methods in a specific order.

There are several ways to solve this problem. I list them according to my personal preference on how to solve it:

  • put it together in a single method – I think it would be the best to prevent a user from being able to call methods in inappropriate order. You can call the first method in the first line of the method that depends on it.
  • throw an exception – this was the case with the problem I had. However, the problem with it was that it was referencing something that seemed completely unrelated to the method execution order. The origin was deeply nested in the class hierarchy and it was not clear why it occurs. My though was that the cause was in the input data, not in the method invocation order. The data needed to be processed in the method1(), in order to be able to do some processing in method2(). The exception did not mention that there are any preconditions that need to be fulfilled or that data is not processed properly, in order to successfully execute this method2().
  • make it clear in the method documentation – this is the least safe way to handle dependency between your methods. Still, if your method depends on another method execution, please, at least put it down in the method comments and hope that it will read by the one that uses it. If you are creating a library, and are writing tutorial, make sure that this dependency is clearly noted in it.

Have you encountered similar method invocation dependencies? How do you prevent situations like this? Please feel free to share your thoughts in comments.

]]>
https://www.stanislavgrujic.com/2016/10/08/dependent-method-calls/feed/ 0 91
Member ordering https://www.stanislavgrujic.com/2016/10/02/member-ordering/ https://www.stanislavgrujic.com/2016/10/02/member-ordering/#respond Sun, 02 Oct 2016 19:01:49 +0000 http://www.stanislavgrujic.com/?p=57 Continue reading Member ordering ]]> As I’ve already mentioned before, I think that member ordering is quite important for the code readability. Classes that don’t have members grouped / ordered by any logical sense can be very difficult to read. Please note that below I will explain ordering that I find logical. It may be that you apply your own ordering, that is logical for you and your team, and that is perfectly fine, as long as you don’t order your members by the addition time.

The idea of logical ordering of members is that the reader of the class can go through it without his reading flow being broken by something that drops in unexpectedly.

In the next several paragraphs I will show you how I structure my classes, from the perspective of members ordering.

Constants

public static final String CONSTANT = "myConstant";

You should put your constants at the top of the class. Most of the times, this is also defined by the coding style guide.

Fields

private int field = 1;

Next in the class file, below the constants, you should place your fields. Also, my recommendation is to order them by their access modifiers:

  • public – if you have any, such fields should go just below class constants. In general, you should avoid having public fields in your class, and only provide methods with public access for altering or fetching the field value;
  • protected – fields with protected access should go next, after the public fields, or after the constants;
  • package private (default) – in my opinion, you should avoid having fields with package private access, but, in case that you need to have them, I would place them at this place;
  • private – private fields should go next. I would expect that most fields in the class are defined as private.

It will make the code more readable, and easier to understand, if you do some kind of logical grouping for your private fields, so that it is clear which fields are related one to another, and are used together.

Constructors

public MyClassConstructor() {}

After your fields are defined, you should place your constructors. If you have several constructors, try to sort them from the least amount of parameters at the top to the most number of parameters below. It will make it easy for the reader to figure out where all the meat of your constructor is used, considering that you are reusing them and invoking always the one with one extra field defined.

Methods

public int myMethod() {}

Next, after you have defined your class constructors, you should put your methods. Similar ordering should be applied to the methods. I propose to make an exception here, in sense that if you have a method used by another method in your class, for easier readability, and continual reading flow, you should place it just below method that uses it. If there are several public methods that invoke that private method, you should place the private method below the lowest placed method that uses it. I propose this way of ordering, because it makes reading the class easy. It helps contain the natural reading flow, from the top to the bottom, instead of having to jump up and down all the time. The second will be the case, if you don’t apply the ordering, but just write down the methods as you need it, or ordered by the time they are added.

If there are any simple helper methods, that do not contain any interesting logic, but are just wrappers to make the code more readable, I would suggest to put them at the bottom, below other methods.

If you have any generated methods, such as equals() and hashCode(), I suggest to put them at the bottom, since most of the time the implementation is known, and the reader is not interested in it.

Nested classes

private class MyInnerClass() {}

Another member type, that can be defined in a class is a nested class. You can choose to have a nested class for variety of reasons. I propose to place nested classes at the bottom of the outer, parent class, so that it does not break the reading flow, once somebody else is reading your code. Most of the times, nested classes are something that does not change very often, and it is enough to have a look at it once, or twice, to know what it represents, and how it works.

I have added a simple class where I have applied the ordering that I propose, so that you could see it in an example, as well. You can find it in my GitHub repo. Please not that the sole idea of the example class is depict the propose the member ordering, and it can be improved in other aspects.

Feel free to try out my proposal and share with me your thoughts in comments. Also, if you have an idea for a further improvement, please let me know.

]]>
https://www.stanislavgrujic.com/2016/10/02/member-ordering/feed/ 0 57
On consistency https://www.stanislavgrujic.com/2016/09/11/on-consistency/ https://www.stanislavgrujic.com/2016/09/11/on-consistency/#comments Sun, 11 Sep 2016 19:00:28 +0000 http://www.stanislavgrujic.com/?p=48 Continue reading On consistency ]]> Personal

One of the most important traits of a good software developer, in my opinion, is consistency. Consistency is needed in so many different aspects of a daily programmers life, and yet it can be easily forgotten when hard times come.

Consistent learning

This one is, I’d say, the most obvious. If you want to get on top, and stay there, you have to consistently invest your time and energy to learn new things. Be it new technologies, new concepts or a new version of a language in which you consider yourself as an expert, you have to constantly devote some time and energy to be able to grasp it. Constant and consistent wish for learning new things is something that puts you on a good path of becoming a better software engineer.

Consistent performance

Whatever you do, you should be consistent. Unless, of course, you slack and under perform. To explain, we all have our good days and bad days, but you should try to do your best, even on a bad day. Being a consistent performer makes you reliable, and, I believe, most teams would rather have a reliable team player with average software engineering skills than a brilliant one from whom you never know what will come out as a product of the day. When you perform consistently, no matter what level, it makes it easier for others to plan with you, because they know what they can expect.

Consistent behavior

This is one aspect that can be easily forgotten. We, as software engineers, are often regarded as introvert geeks who the most prefer to be left alone and talk to a computer. However, that is so far away from the truth. In 21st century it is very difficult for a single person to create something, without much interaction with others, so we should all try to be as good as possible colleagues one to another. You should try to make yourself a valuable member of every team, and you will become so not only with your technical skills, but also with predictable behavior and solid soft skills. Consistent behavior will make it easy to other people to know what they can expect from you, how will you behave in most situations, and that will help them avoid one thing that most people don’t like – uncertainty. When you consistently behave nicely to other people, provide constructive solutions and help others be better, you are becoming a valuable team member and most people will want to work with you.

Source code

This one is as much a team effort as a personal one. I highly value code which is consistently written. I think that consistency makes it much easier to read it. When the same patterns are applied in each and every class/file, you don’t have to spend much time thinking about the representation of authors idea. Consistency is the reason why we have the code style guides, so that we don’t have to spend energy trying to figure out some common things. When the source code is consistent, it is easy to read and update it, or to say it differently, communicate with it.

You can find style guides for the language of your choosing, freely available on the Internet, so I won’t go into details explaining it. However, there are some things that are usually not explained by these documents, and can improve the consistency and readability of your code.

Methods alignment

One might argue that it’s really not important how methods within a class are aligned, because all modern IDEs can take you directly to a method. Still, I think that it makes the class much easier to read, for all those whom might be interested in doing it, if you align methods consistently throughout your project. So, if in one class you put your private methods below methods that use them, and static methods below them, for example, then use the same way to organize methods everywhere, and don’t put in another class private methods on the top, since you will break the consistency.

Class naming

You should name your classes consistently, in a way that if you name a class of specific usage as *Helper, don’t name the other one, in the same project, with the similar usage *Util, or vice versa. The consistency in naming will help a reader figure out what the class does without the need to open it, if he is not actually interested in looking into the implementation.

Arguments

This is one more thing that can mess up the readability of a class. If you consistently put arguments of the same type or usage at the same place in the method header, it will make it easier for a reader to memorize the code. It will help him avoid spending energy figuring out what argument is for what, especially if you don’t enforce the type safety and pass the arguments of type String, or similar, to your methods.

I think these small examples should be enough to show what I mean by having software that is written consistently. Code that is consistent, looks nice and is easier to read than inconsistently organized code. From my own experience, such source code is much easier to maintain, upgrade or refactor. When someone needs to make a change to it, it will not give them a headache of only trying to figure out what is happening where.

To reflect on applying consistency on a personal level – just as the source code, it will help you become a better developer and coworker, and your consistency will help your coworkers communicate with you. It will make you a reliable team member, from whom people know what to expect in which situation, and a more pleasant person to work with.

Please feel free to share your thoughts in comments on consistency, in every aspect of developers life. Also, if you disagree with anything I wrote, I’d be happy to hear your arguments.

]]>
https://www.stanislavgrujic.com/2016/09/11/on-consistency/feed/ 3 48
Code reviews – checklist https://www.stanislavgrujic.com/2016/09/03/code-reviews-checklist/ https://www.stanislavgrujic.com/2016/09/03/code-reviews-checklist/#respond Sat, 03 Sep 2016 06:08:40 +0000 http://www.stanislavgrujic.com/?p=35 Continue reading Code reviews – checklist ]]> While writing the post on code reviews, it occurred to me that I could also write about the things I look at while doing it and provide you with a checklist that you could use to perform your own reviews. I will try to explain why I find each of these points important, but you can use or modify the list however it suits you.

So, without further ado, here is the list.

  1. Code formatting – in general, this is something that you should let your IDE do for you and the whole team should have a common code formatter configuration file to use. It is important that everybody uses it, because it will make the code looks consistent, and as such much more readable. If I notice anything that looks as if the code formatter is not setup, I’ll ask the author of the code to configure the formatter, and setup the Save actions so that the code is automatically formatted on each save. It is a configure once and forget action that does not take much effort, but helps a lot.
  2. Spelling – no matter how trivial this sounds, having a spelling error in a name of a class/method or a variable can make it pretty difficult to find it. This can become specially frustrating if you know the name of the class you look for, but are not aware of the spelling error. All modern IDEs provide you with a keyboard shortcut to directly jump to a class, or a method inside it, so if there is a spelling error it may be a difficult task to find it. All IDEs have an integrated spell checker, so it really is easy to write properly spelled code, and you as a reviewer should really point out these, if you spot them.
  3. Naming – having a properly named class or a method is really something that can help you and your team to make the code as readable and expressive as possible. It is not without reason said that naming things is one of the most difficult things in programming. Sometimes it is very difficult to choose a proper name, so whenever I’m in doubt I ask the author of the code, or reviewer of my own, if we could come up with a better name together. Clear class / method names can help everyone to remember  and reuse them, when needed. Finding a good name can be difficult, but once you figure it, it makes it clear what a class or a method does. This makes it easy for anyone reading the code to understand what’s its usage and how it fits with the rest of the code.
  4. Proper usage of existing methods – sometimes, developers are not aware of all the methods that they have at their disposal, and are either creating the similar ones, or using the code that could be replaced with a single method call. I think that it is very important to point out things like this, because whenever you can replace something that you’ve written, with something that does that same thing, already exists and is tested, you should do it.
  5. Conventions – whatever conventions we have on a team level, I expect all the team members to pay attention to it and respect it. For example, the whole team should stick to the same coding conventions. Using conventions makes the code uniform and easier to read, and you, as a reviewer, should make sure that the author of the code respects them.
  6. Unit tests – whenever I’m doing the code review, I like to check the unit tests. They can show the thought process of the author. Are both happy flow and marginal cases covered? How well are they written, and do they test the right thing? Aiming for the high coverage per se can be very tricky, and I would rather like the developer to cover only the most complex part of the patch, but do it well, rather than to have everything covered poorly.
  7. Implementation correctness – you should briefly check if the implementation is correct by comparing it with the feature specification. Sometimes, it’s relatively easy to spot the bugs in the pull requests, if the author has missed to cover an alternative flow. I don’t go into details, but try to figure out what and how the functionality should do, and try to rehearse the implementation in my head, and see if it all fits.
  8. Method locationin file – is the method properly positioned in the class file? Are all methods that invoke it above, or there are some above, and some below. This may look as splitting hairs, but it will make the code much more readable if you place it all below. This way, when someone reads a class, he does not have to jump all over it to find it, but can read it in the natural way, from top to the bottom.
  9. Method location – in module/project – sometimes, a developer does not pay attention to where the method or piece of code actually belongs. A misplaced piece of code left to sit at the wrong place can cause much deterioration of the code base. Just one simple example would be a misplaced null check, if you decide to ever pass or return nulls from your methods. If you don’t put the null check at the lowest possible level, inside the method which actually does something with the nullable parameter, you will have to check it in many places. As a consequence, this will make it obligatory to always do the null check, will lead to surplus code, and even can cause bugs.
  10. Simplicity – is the produced code the simplest possible solution? Sometimes, specially with young developers, the code is unnecessary made very complex, and can be simplified just by using different data structures or method constructs. For example, one might use a list where a map would be a better fit. If you spot an overly complex solution, you should point it out, and maybe even propose a simpler one.
  11. Data structures – are proper data structures used to solve the problem? Would it make it more efficient to use some other structure? I think that one of the things that make a good developer is knowing which data structures should be used where, and which are the benefits and drawbacks of using each of them. Special case here is using hash structures, which require that you also have equals() and hashCode() methods overridden for classes you’re storing in them, so please always check if they are present and properly implemented.
  12. Resource usage – are any resources that are being used properly handled. Is the file reading stream closed always? Is there a usage of remote systems and does the author use it optimally? Inefficient or improper usage of various resources does not have to create a problem during the development. You might not even notice it there. Still, once your system is under heavy load in production, you can have serious problems because the resources are not released properly, or not used efficiently.
  13. Patterns – be it the design or architectural patterns, check if they are properly implemented and in place. They can help a lot to to make the code more readable and maintainable, if used correctly.  Missing to apply one can lead to code which is more complex than needed, the same as overusing it.
  14. Optimization – is something prematurely optimized even if it is not a bottleneck? I’m strongly against premature optimizations because mostly they add complexity to the source code. Whenever you see something that looks like it, you should ask why it’s done. Sometimes, the explanation is reasonable, and other times it’s really not needed and you can agree to remove it.
  15. SOLID principles – are these principles applied together? Proper application of these principles should make it reasonably easy to maintain and extend your application, so you should check if they have been thought of during the implementation. If you see something that looks like it’s against these principles, it might point out at a code smell, and you should at least discuss it with the author, why it’s done the way it is done.

Here are some additional checks that I do, before I ask somebody else for a review. Although these seem quite obvious, it happens that I forgot to check it, or I see somebody else commit the code without doing it, that I have to add it here.

  1. Static code analysis – I certainly hope you have setup a continuos build process, at least, which has a static code analysis running on each build, or at least a nightly. If not, I strongly suggest you use one, because they can point out to potential bugs or security issues in your code. You can also run the static code analysis tools (e.g Checkstyle, FindBugs) locally, and spot the potential issues before you push your code to the master development branch.
  2. Check if it all works – this is more a checkpoint for the author, than the reviewer, but I’ve seen it so many times, I have to mention it. After you’ve merged the latest main development branch revision to your feature branch, to make it mergable, did you check if it works? Did you run the build and see if all unit tests pass?

Please note that this list is meant to be used only as a starting point. There are so many other things that you should/might look for in a code review, that whole books are written about it.

Feel free to modify this list however it suits your team, by adding or removing items. Here you can find a downloadable PDF checklist version.

How do you do your code reviews? What are the things important to you? Please feel free to comment, I’d love to hear your opinion.

]]>
https://www.stanislavgrujic.com/2016/09/03/code-reviews-checklist/feed/ 0 35
Code reviews https://www.stanislavgrujic.com/2016/08/28/code-reviews/ https://www.stanislavgrujic.com/2016/08/28/code-reviews/#respond Sun, 28 Aug 2016 08:44:59 +0000 http://www.stanislavgrujic.com/?p=24 Continue reading Code reviews ]]> Before I dwell into practices that I find useful for improving the code readability, I would like to describe one of my favorite tools for keeping the code clean – code reviews. While it may seem cumbersome and overhead to some, having someone else to have a look at your master piece, you will be surprised how many different things one can find in it. The reviewer might point out to some things that you might’ve overlooked or forgotten, or even point out to a better way to implement a feature, or a piece of it. For example, in the simplest case, a reviewer could have a better knowledge of the source code of the system, or part of it. During the review, he can point it out for you that a method that does exactly the same thing already exists, so that you can remove it. Even better, you could analyze both methods, choose a better implementation, and remove the other one. You know the saying: “Less code, less bugs.“?

In my opinion, everyone should participate in code reviews – from the very beginner, junior developer that has joined the project yesterday, to the senior developer, who has a vast knowledge of the system, and many years of software development in his fingers. The reason for believing so is that I think that everybody has something to offer. It may be expressed even in a form of a simple question when something is not clear, and yet the benefits can be huge. It will trigger you to think about it one more time, and maybe figure out a better solution.

I believe that code reviews are a very good way for one to learn. By performing them, new team members can get into the business domain faster and also see how different technologies/frameworks are being used on the project. They may see things that are unclear to them and immediately ask for clarification. As for the senior members, they can spread the knowledge and experience by doing the review to the less experienced colleagues, and are making sure that the things are going in the right direction, technology wise.

There should be the same ruleset for everybody regarding commits to the source control, and it should contain a rule that no code is pushed to the master development branch, unless at least one developer did a code review for the patch and approved it. Using a source control tool like git makes it much easier to perform code reviews before the new code is merged with the rest of existing application.

Even if you work on your own project, and you are a single developer, you should review your changes before you commit the code and mark the task as done. You’ll be surprised how many things you can introduce during coding and find in the review, even for your own code. And you never know, this same project might become your showcase project when you apply for a job position. Believe me, when you do that, you want to have a nice looking code for somebody else to see. It is easy to continually care about the quality of the code, and have it as good as possible. When applying for a new position, when you want to have time to prepare yourself for an interview, and stress and time constraints, it’s much more difficult to clean it up in bulk, so you’ll appreciate to have it ready.

I personally have a habit of doing a code review to myself, before I ask somebody else to do it. It’s a great way to prevent being embarrassed for forgetting to fix some simple issues that I might have skipped because I was focused on other things.

There are various techniques for the code reviews. I will not go into each of those, but will only explain how I do it and the positive and negative sides of each of them.

General comments

Before I explain the techniques I use, I’d like to share also some of my thoughts, how to approach the code review.

One of things I’ve noticed is that there are always one or two developers that are eager to do code reviews, and then everybody else relies on them to do it. If they are to busy, or absent, the others are reluctant to do it. That is one of the reasons why I ask of everyone, on my projects, to participate the review process. No matter the seniority level, all team members should do it. As I already mentioned, I strongly believe it is a great way to keep the code as clean and readable as possible and it is a great tool for introducing new team members to the project.

If you are a reviewer, don’t take the review lightly. It may make more harm than benefit if you superficially do it, and approve it for being merged, and only later on people find out that it’s a big ball of mud, and not a nice looking piece of code. Take the time you need to prepare yourself. Ask the author of the patch the push the branch to remote, so that you can have a look at it yourself for some time, before you go through the code together. This will let you have a decent image of what is made before the review, and you could already some questions in mind, after the first look.

Try to have a look at the bigger picture. How the changes fit in with the existing code base? Are there any duplicate, or similar methods introduced, that could be avoided with better code organization? Are desired architectural decisions applied to the changes? You could make yourself a checklist of things to have a look at the code at, and go through it each time you’re a reviewer. Even if you’re an author of the code, you could use the same checklist to make sure that your code with pass the review with flying colors.

Last, but the most important – please don’t take it personally and don’t make it personal. The code review is not used to show that one is a better developer than the other. It is not supposed to be used to make someone feel bad because of a crappy code he made. It happens to everyone, whether you like to admit it or not. Always think that the next time you could be on the other side, and imagine how would you feel for the negative or rude comment. Don’t be offended by a comment. It is not an attack on your persona, but rather an attempt to make the code base better. If you feel that the comment is intentionally used to point out how someone thinks of himself better than you, please keep calm and politely ignore it. You don’t want to be the one that negatively affects the team consistency.
Look at the review as an opportunity to learn, and to teach, and you will see how the quality of your code rises over time.
We are all on the same team and with the common goal – to deliver the software of the best possible quality.
Peer-to-peer review

Peer to peer review requires that both the author of the code and the reviewer are present. It is a synchronous process where one shows changes made in the patch and other one is trying to find and pinpoint the potential issues or things that could have been done better.

Author of the code can use the diff tool to show the changes in the patch to the reviewer. Assuming that you use git, you have a tool name git diff coming with it. It is very powerful, and can help you do the code review. All modern IDEs have Git integration, so it’s very easy to see the changes, add comments and implement a fix immediately. After all comments are resolved, you can make a commit and merge your branch to the development branch.

I will not go into the details on how to use Git here, however I strongly suggest that you have a look at the various workflows that it supports. You can find a very nice article with explanations here. My suggestion is to skip the Centralized workflow, which mimics the Subversion, and have a look at the Feature branch workflow or Gitflow workflow.

Good thing about peer-to-peer review is that since it is a process where all parties are present at the same time, it is easy to avoid ping-pong in comments where people argue if something could/should have been done in the other way or not. It’s also good that all the potential misunderstanding can be clarified right away. Changes can be applied on the spot, and even the author and the reviewer can do pair programming to update the parts of code for which there are comments.
Peer-to-peer review can be used also as a great tool for learning. Of course, the author of the code can learn if a reviewer points out for things that could have been done better, either from technology, architecture or business domain perspective. On the other side, the reviewer can also learn from the author by asking questions on things that are not clear, on each of the previously mentioned areas.
The author can guide the reviewer in a structured way through all the changes, and explain each of the affected files, so that it is relatively easy to connect it all together.

On the downside, the peer-to-peer review requires much more time than the tool supported, asynchronous review. Sometimes, when the change is bigger, or more complex, it can take more than an hour, from my experience, which can add up for several hours in a day, if one participates in several reviews. In order to get the most benefit from it, the reviewer should be able to prepare himself and get some knowledge about the implemented feature, the affected part of the system, and architecture and technology that are used.

Tool supported, asynchronous review

Tool supported code review allows the author to create the so called pull request, to merge his patch to the main development branch. It does not require simultaneous presence of both the author and the reviewer, which makes it very convenient for distributed teams.

Again, in the process explanation, I will rely on git, and in this case GitHub, which gives you a nice, graphical overview, of all the changes that have been made in a pull request.

The reviewer can go through all the changes and think without interruption about each of them. He can pay attention to details, which can be easily skipped if peer-to-peer review preparation is done poorly. GitHub handles comments nicely, so each comment on a pull request is delivered in an e-mail, and even the team members that are not directly involved in the review can see what the comments are, and learn from them. Also, it’s very easy for everybody to participate in the review, and even if they don’t make the comments on the code, they can see what the changes are, which comments were made on the pull request and how it’s all resolved. I always ask all of my team members to participate the reviewing process because, as I already mentioned, I think it’s a great way to learn and share knowledge.

The asynchronous review has its bad sides, also. One of the most annoying ones is that it can happen that pull requests pile up. As a consequence this can cause many merge conflicts to be resolved, after the pull requests are merged to the main development branch. This can take a lot of time to resolve, and can produce some frustration with the responsible developers.
Also, files affected by the change are not displayed in the order that helps figure out the flow needed for the feature, but are alphabetically ordered. This can cause a need for constant scrolling up and down, in order to figure out how the changes in different files are connected.
To conclude, code reviews are a great tool for making sure code quality does not diminish over time. It is a great tool to share knowledge among the team members, and while it may seem as a burden and that a lot of time is needed, the benefits are much bigger than the investment. My advice is that, if you don’t already do it, you start doing it as soon as possible. There are several techniques that can be used to do it, and you should try and choose the one that best fits your team’s needs. At the beginning it may take a bit of effort, but after you make it a habit on the team level, you will reap the rewards. Start small, and see how it goes. Remember, stay polite no matter what you think of the code.
To quote the Nike slogan – Just do it! – and you’ll soon see the benefits.

Please share your comments on how and if you do the code reviews regularly.

]]>
https://www.stanislavgrujic.com/2016/08/28/code-reviews/feed/ 0 24
Yet another coding blog? https://www.stanislavgrujic.com/2016/08/20/hello-world/ https://www.stanislavgrujic.com/2016/08/20/hello-world/#respond Sat, 20 Aug 2016 05:29:24 +0000 http://www.stanislavgrujic.com/?p=1 Continue reading Yet another coding blog? ]]> So, you came here, either on purpose or by accident, and you must be wondering – Why on Earth there is another guy writing about the code quality, readability, maintainability and all the other -ilities?
Well, the thing is that during the daily work I get to meet and work with many software developers, with various backgrounds and seniority levels, and I see things that can be improved. Of course, they also see things…
In posts I’ll be writing, I will try to share my experience and the things I find as best practices in writing software, so that it is easily readable. I will try to point out the difference between the readable and not so readable code, in my opinion.
Everything that I write here is my personal opinion, which does not have to be the best one. If you have an idea on how the code for which I think that’s readable can be further improved, please feel free to point it out. I am always happy to learn new ways to be able to write better code.
I hope that on this journey that begins, we’ll grow together, and that we’ll make each other better!
]]>
https://www.stanislavgrujic.com/2016/08/20/hello-world/feed/ 0 1