Never end up to this!
Last week I was visiting my alma mater with some of my school mates, we were mesmerized to see that almost everything has been changed! The campus was renovated so amazingly that we all loved it. But then after spending the whole afternoon, when we were leaving the campus, we saw this:
We were laughing to our heart’s content and could not come into a conclusion on how on earth they came to build this useless veranda!
While working on large projects, developers sometimes end up to this as well, designing things that we don’t use ever making our code-base clumsy! So, in this blog post I will rewind some common code-smells aka anti-patterns for those who don’t want to mix-up their code-base.
We need to talk about anti-patterns too!
When a projects grows, your code-base fattens as well. At this point, if you are experiencing that changing a single method of a class needs you change two or more other classes, or let’s say whenever you think of adding something new, it does always seem to be added to a particular class and so on, then your code-base is already suffering from some serious anti-patterns. So, to minimize the cost in the long run, we need to be cautious about adding anti-patterns in our code-base from the very start of the project.
Principle of Demeter
It is common to compose a class with other classes that might have been composed of some others. So, if at any time we need to check any property of any lower level class, we may end up to a long message chain, like this:
if you have something like this,
this->company->department->employee->set_name("Dr. No Man");
when all you wanted was just to set the name of a new employee (or perhaps you wanted to check the name of an old one’s) then you need to rethink about your api calling. Try to design you classes and apis in such a way that you don’t need to call more than one or two level lower.
Class designers often suffers from this obsession too, they keep some extra api thinking that these may be come in handy in future. Follow Just In Time(JIT) philosophy instead. Only implement methods when you actually need them. This will keep your code-base thin and clean.
You don’t call a Room to be a Bus just because it has Doors and Windows like a bus does, right? Like here, the Room class is refusing the Wheel property of the Bus.
Likewise, if one of your child classes is refusing any property of it’s parent class than it is violating the mighty Liskov’s Law. One work around to this is to use composition over generalization(I hope to write a solo article about other solutions on this anty-pattern in future 😀 ). Like, you can make another class that is composed of Doors and Windows and your Bus and Room class can have that class as one of their properties like below:
Developers often tend to use primitive data types like int, string and so on almost everywhere even when using these may refrain you from detecting invalid inputs from user. Say for example, the following code may seem nothing dangerous to you:
setUserEmail(String emailAddr): bool
setTodaysDate(int day, int month, int year): bool
but what if the user tries to set (intentionally or unintentionally) his email address like this:
which is invalid in a sense that it doesn’t contain any
'@' character, you can check valid email wiki page for other email validations, or let’s say if someone tries to set a date like this:
setTodaysDate(-1, 2.5, 2020)
setTodaysDate(1, 20, 2020)
you can’t set negative or floating values as day or month. But you know what? Clients(caller of your api) are always right! And trust me, they are also developers like you and you know, bug happens!
So, to control user by validating their inputs in these cases and by enforcing the uses of explicit data types like below you can save your application from unwanted failures!
Now, the callers are to create that
Date object first and then call
setTodaysDate, and you can book a ticket to Cox’s Bazaar with no-worries 🙂
Date date = Date(-2, 5, 2020);
Date date = Date(13, 3, 2020);
setTodaysDate(date); /*no exceptions here any more, will be handled by the constructor of the Date type*/
even it will be better if you create separate classes for
Year and segregate their validations thereby as well!
Sometimes you will see bunch of data items tend to wander around together in a number of function signatures frequently. Simply take the following function signatures for example:
setBirthDate(Day day, Month month, Year year): bool
setMarriageDate(Day day, Month month, Year year): bool
setJoiningDate(Day day, Month month, Year year): bool
If they want to stay together, let them be!
if you notice these sort of love birds to flock together, it will be wise to create a custom class that comprises of these data items:
and use that into your function signature as a single argument instead!
setBirthDate(Date date): bool
setMarriageDate(Date date): bool
setJoiningDate(Date date): bool
To End Or Not To End!
I will write other anti-patterns followed by a series of popular Design Patterns inShaAllah! The series may include a short intro to UML as well! So, keep following.
If you see anything foggy or have any comment to put, all you need is just to scroll a little bit down!