Showing posts with label Single responsibility principle. Show all posts
Showing posts with label Single responsibility principle. Show all posts

Friday, June 17, 2016

Conjunctions we... hate

Recently I’ve written about implementation-related names and I’ve presented a few examples where the method name was incorrect because of its strong relation with the body.
At one moment, we had the following code:
boolean isComplexOrUnreadableWithTests() { 
    return (complex || unreadable) && tests.exist(); 
}

Just to remind you of the context: it was supposed to find out whether we may or may not do the refactoring:
if (code.isComplexOrUnreadableWithTests()) {
	doRefactoring(code);
}

Recently I’ve told you that the name is wrong because of its direct relation to the implementation. However, this is not the only problem. The use of conjunctions in the method’s name is a sign that we could not find a right name and we just list all known things that we’ve done. It does not matter whether this list is implementation- or logic-related.

Saturday, June 11, 2016

The name should express the intention

This time I will start with a code sample. Take a look at this:
if (code.isComplexOrUnreadable()) {
    refactor(code);
}

Can you tell me what is wrong with this code? No?

Let me ask you another question then. How do you think the implementation of isComplexOrUnreadable() method looks like?
I assume that many of you would imagine something similar to this:
boolean isComplexOrUnreadable() {
    return complex || unreadable;
}

Am I right?

Ok, so let me ask you again: can you tell me what is wrong with this code?

Wednesday, April 20, 2016

Code Review and Single Responsibility Principle

According to the Single Responsibility Principle each unit in our code should have only one reason to change.
Code Review, on the other hand, is a technique that helps us improve the quality of our code and increase its readability.
I believe that you know both the principle and the technique.
The question is: why do I juxtapose them in one article?

Well, if SRP is about one reason to change code, then I think that code in the review should be organized around one change. The author should organize the commit of the code which is sent to the review in a way that will reflect only one change.

Code Review and the effort

Code review is really useful and important. However, it requires some amount of effort from the reviewer. A developer that will read the code will have to understand what needs to be implemented. They need to know whether expectations are met. They need to have enough understanding to verify the quality of the code and its readability. All of it requires both time and full attention. During the review, if you want to do it right, you have to stay focused.

That’s why we should make code review as small as possible. To decrease the effort that must be put into this activity.

Code Review and only one change

Many changes mean that you are jumping from one place to another and you are trying to figure out which change is the reason of which modification of the code. It makes reading the code harder, because you need to keep in mind many contexts and reasons. It makes it harder to find bugs in such situation.
More things that are merged can go unnoticed..

When the code that is put to the review, it has various reasons for modifications than, except for everything I mentioned in the previous paragraph, we need to carry out two additional activities: switch contexts and group changes into subsets organized around each change. And we also have to remember that each change can have an impact on another.

So the amount of the effort and time that reviewer needs to invest into a code review is:
Number of changes * effort needed for one change + switching the context + understanding implication


I heard more than once that “it is better/easier/faster to do one code review instead of many, because you will do a review only once”. As you can see, though, putting many things into a code review is not simple multiplication of effort needed for one review.
Unfortunately there is additional complexity in this equation.

Many changes in one review

The additional complexity of the review is not the only thing that stands against putting many changes into one commit. What is also important, many changes in one commit mean less readable history so when you want to find something, it would be harder because some changes will be merged with other changes. What would be the name of your commit in that case? It will need to either focus on the most important change or it will be something meaningless, because you will try to use one sentence to explain many things that were modified.

Such thing doesn’t help when you have to find a root cause of some issue or you want to understand some part of the functionality. It is hard because of the same reasons that make the review of such code hard - complexity and presence of many contexts.

One change at a time

What do you think about this idea?
Let’s organize our commits around a single change.
Let’s make things simple and easier for us and all of those who will read the code.


Thursday, June 4, 2015

Let’s do something useless

Ok, this one will be trivial, but it needs to be written and, what’s more important – remembered. Doing anything makes sense only if there is a reason to do it. You should not write a line of code just for its own sake. And there are several reasons why you shouldn’t do this. Firstly, there a chance that you really would never need this code. Secondly, you are making an effort that is needed for maintenance. Someone has to take care of this code, someone will read it and so on. And thirdly, useless code makes everyone confused, because “if someone added it, there has to be a reason why he did it”.

But it is not only the case that useless code is not used anywhere. There are situations when you can notice in your application code appearance of methods that, yes, are used, but are only the part of some functional whole. They bring no value on their own except problems.
And those are the “creations” that I would like to write about today.

single responsibility principle – it’s not all

SRP tells us that each class needs to be responsible for only one thing. When creating your own classes/methods, it is also important to remember that our elements need to follow those rules when we are taking context of the application into consideration.

What’s the matter?

You won’t create a method that returns a list of all customer’s invoices if the only thing you need is to get those that aren’t timely paid. Instead of such a method, you should create the one that returns the list of those that you are interested in. The problematic thing is that when you look at the method outside the context, it looks all right. Yet, when you will take context into consideration, then it is obvious the method is not a whole on its own. It is just a part of a bigger whole.

maybe you would like to look at the code?

Let’s look at the example that describes what I just shared.

Let’s imagine that we are working on an application which manages various types of events. Each event has got its own state:
enum EventState {
    CREATED, INITIALIZED, READY_TO_GO, FINALIZED, CANCELED
}

Sometimes it happens that an event somehow is hanging. That’s why once a day applications send notifications about those events to all people who are interested in which events weren’t finalized or canceled:
EventsBatch events = EventRepository.getAll().notFinalized().notCanceled();

if (events.notEmpty()) {
    notyify(events);
}


The code above is quite good, isn’t it? Well, not really. What problems can we expect from such implementation?

First, we can notice violation of SRP. Method’s code is not responsible only for sending a notification when specified conditions will occur. We also defines the events about which user will be notified.

Secondly, let’s imagine that at some moment in time we will add a new functionality and we need to do some kind of operations using exactly the same pool of events. Most of developers would go to EventRepository class first, but there they will see that the method they are looking for does not exist. Do you think that all of them will go over the code to find out whether someone had ever the same need, but instead of creating method he done it inline, as a yet another code instruction? Would you do that? Should we even take such a steps into consideration?
On the other hand, even if a developer will invest his effort into searching there is always a chance that code won’t be found.

And in such situation a developer would create method that doing exactly the same what is done in different place. And it result with next problems that directly comes from violation of DRY. We have two places that need to be refactored no each change (i.e. we are adding another non notifiable state – DUPLICATED). I believe you won’t have a problem imagining how easy it is to forget about any of them.

Also, implementation details can leak to the outside world. We can’t talk about encapsulation and, what is even worse, an external object is the one who takes care of valid state of the object. The truth is that until the batch will be useless events are filtered out. It is in invalid state.

We also have twice as big chances to make a mistake. We need to write more tests, because the same functionality is created in two different places. Even if we find bug in one place, there is no guarantee that we will remember to fix it in another. As a result, correctness of the same functionality in different places can be different. Worse than that, we will be sure that the bug was fixed and even if one day we will find out about an affected place, we won’t even think about an “already fixed” bug.

The last problem is the existence of getAll() method at all. It can happen that this method is never used in application as a result provider. What I mean is that we would not do any additional operation on method’s result, because it is exactly what we need. What if the usage of it ends always with “doing something more” with the result? What does that mean? Well, it means that we have more issues with DRY and SRP that we even thought. There can be many places in the code which generate problems mentioned above.

and in the end…

How many times did you write a method whose results you always had to change? Predicate that was always negated? The method that returns a list that you always have to filter?
If you have to do something with the result of the method execution, if you want to make it usable, then remember that it would be good to read this article once again and think how to refactor your code :)