I’ve been trying to write something related to design patterns since last three months but the journey became really painful. Issue is simple. I felt like, it is really difficult to present this topic like a bed time material. Whatever I’m writing it is looking really dry for me.
Finally….
Finally what?
Finally nothing! I’m posting the same material which I’ve written in the very beginning, i.e. three months back. After couple of attempts, I felt like, giving you central theme of patterns is more useful than providing list of patterns and giving some code examples. In other words, I felt it is more useful giving you reason(s) how/why patterns helps you in your design than giving theory on patterns.
Shall we start?
As usual I will start with a question.
When you start a new project what generally you do?
This question is boring. Isn’t it?
Ok I will ask differently.
Which phase of the project you think people take lightly generally?
This is also not so interesting question. Ok, I will not ask any question, I will give the statement.
Most taken for granted phase in the software life cycle is, “Design phase”
Reason for this is simple. As I said in one of my previous articles, people can easily escape by doing a bad design or by not doing any design. At the same time, it is not that simple to measure quality of the design. Design is highly is subjective. By looking at the design we cannot straight away say design is good or bad. In most of the cases, design quality depends on the capability of the individual who is doing the design. Means, design is an area which became person centric than process centric.
As applications grow in size, poorly designed applications become hell to code and maintain. You leave about maintainability or re-usability. First of all, something should be codable (I know this word is not there in English but I think it gives you my intention). If design is poor, developers usually feel that project is complex. Sometimes, to achieve some requirement, they may have to code at multiple places within the solution. If they change something in one place, some other place might get affected. If their lead asks them to change any requirement or add a new requirement, the developer will not be sure on where to change. Interestingly, the person who designed the project also will not be clear on the impact.
To manage software complexity, object oriented design came. We all know what is object; principles object orientation like encapsulation, inheritance, polymorphism etc..etc..but not sure how to use these principles in design. If we simply write code in a class module doesn’t mean that we used object orientation principles effectively. It is just like writing sequential programming in a class module.
At the same time, designer/architect life is not easy. It is really a challenge translating requirements into design. While designing, every designer tries to achieve object orientation. But identifying objects in the project itself is a head breaking task. It is easy saying “Identify all the nouns, those become your classes. Identify all the verbs those become your functions/methods” but practically it is not that useful. Though this guideline is useful to start with, if designer is not careful he may end up by defining too less number of objects or object creep (too many classes). Again, design phase being person centric, for few designers whole module may looks like a single object and for few others, each independent sub modules within the module may look like separate objects.
What is the solution for this then?
There is no magic formula invented but there is a way!!
As you are expecting, the way is “Design Patterns”
Of course if you open any patterns book, definition of patterns you will hear something like “Best solutions for common/reoccurring problems” This definition is misleading to many like, patterns are only useful when you encounter some problems. If you ask me I will say Design patterns are basic guide lines to make good, maintainable, re-usable code. It is true design patterns is set of 20+ best solutions to set of 20+ common problems people generally encounter in their designs. It is also true, your project may not have these 20+ problems but the crucial thing is, design patterns changes the whole mindset of the designers. After going through the design patterns, we will get an understanding on “how to look for object oriented solutions in our project for our own problems which are not necessarily part of the 20+ problems identified with in patterns”.
What is the inside magic?
I think the magic lies on the fundamentals on which patterns are built. I don’t think all the 20+ patterns are based on few common fundas but most of them “yes”, they do. In this post I would like to introduce you those fundas (This also not an English word. Please don’t mind). The way I’m presenting may not be useful for you to tell in interviews or in your business meetings but my goal is not that. If it helps you while designing your projects and if it helps you in understanding patterns, that’s more than enough for me.
Shall I go ahead?
Thanks!!
In design, there are two key points.
I will explain these two concepts in detail. Hopefully after going through them, you will enjoy reading about patterns better than before.
Here we go.
Objects should be responsible and selfish:
Many a times, in most of the projects, we can see objects which are very generous. They perform number of tasks. They provide lot of functionality. If you have such kind of generous objects in your architecture it is most likely that you did not identify your objects properly or you just taken design for granted. Such objects in the design give you few side effects like, difficult to code, hell to maintain and inability to handle change.
This guideline says, make sure that your objects are really really selfish. It should not accept to do whatever work given to it. Authors Allan and James in their book “Design Patterns Explained” says beautifully,
"Objects should be identified with the responsibilities but not with the data and code".
Each object you defined in your problem domain should be given clear cut responsibilities. It should not do more than that. You might be identifying objects with "nouns" or any other approach but after identifying, while going through each requirement of your project, make sure you are clear on whose responsibility it is to full fill the given requirement.
True, your design might change with time during the design and coding phase. That is fine but looking at objects as something which is carrying some strictly defined responsibilities and not a generous social worker kind of thing, helps us to visualize the whole project in terms of few persons (objects) who are ready with their individual tasks to complete the project.
Needless to say, while identifying responsibilities do not think about code. It is not the time to do that. Of course, I do agree being developers we do think about code while designing the project. Bad habits die hard. Need to eliminate them by simply changing the way we think.
How to make sure your objects are selfish?
While assigning responsibilities just think like, is it possible that, this object can reject the responsibility? Can the object say firmly, "NO it is not my responsibility somebody else has to do it". In turn, if you can concretely say to the object like "NO. It is your responsibility!!" then we can assure our self that we are on the right track. This advice may look silly on paper but it works.
To conclude this guide line,
Do remember,
Objects should play Hide and Seek Game well:
This guideline, I think fundamental to any design pattern. Directly or indirectly most of the patterns built around this. Your design also should give top priority to this.
I thought of not giving any coding examples in this introduction but please do not mind for the below single line
MyObject myVaraible = new MyObject();
What does this line do? You have defined an object called MyObject() and accessing it with a variable called "myVariable". Now by using myVariable we can happily use functionalities provided by the MyObject. Of course we do create objects to be used by some part of the application like this only. But this guideline says as far as possible do not allow your objects to be created with "new" keyword. dot.
Then how anyone can use your object?
Through interface!!
Why?
Boss, objects are like your mother and wife. If you directly allow them to communicate, house becomes a mess. You just stand between them as an interface and allow them to communicate through you only.
?????????
I’m kidding and forgive me if you are a woman but there is no rocket science in this guideline.
Different people give this same guideline differently. Gang Of Four, in their book on Design Patterns says this guideline as "Design to interface, not to implementation". If you do not like technical words and ask me to explain in plain English here we go.
In any software project, what is single most common problem which we all know and experienced? I should not say single factor. In fact there are two things.
1. Missing requirements
2. Change in requirements
I know you will agree with this even though you are the most brilliant architect/designer currently living in this universe. Goal of any designer/architect is to take these factors into account while designing. Though it is not possible for any designer to anticipate when/where changes going to come but following this guideline helps us to effectively deal with known/unknown/missing requirements.
The goal of any designer should be to design in such a way that, his design allows him to change/add requirements at any point of time. Though this is quite optimistic goal, designer should try to achieve that.
The whole purpose of this guideline is to achieve that. How it achieves it?
In two ways
1. By hiding your objects under an interface. This way, calling applications always talk to the interface. They are no way it is connected to your real object. That allows your object to change at will.
2. Identify what is going to vary in your application and hide them under an interface. Again Allan and James in their book says this as "commonality and variability analysis"
Both are looking same?
May be yes.
Probably the first point can be combined with second point and conveyed. But, you know, this particular statement in the first point “That allows your object to change at will.” used to irritate me in the beginning of my learning.
For the same line, one more word people used to say..
What is that??
What is that??
Yeah!!!
”Loose coupling..”
I feel like slapping the person who says this. Don’t mistake me. My feeling about this word is nothing to do with object orientation but really I don’t know why I hate this word. Probably the word “Couple” in that ? No, not that ! May be “Loose” ? No, not that !! Ok, leave it.
Anyway still I have to use these words to make the concept clear. Otherwise shall we do another thing? We will define synonyms for tight coupling and loose coupling and use those words.
Ready!?
Tight coupling is wife and loose coupling is girlfriend. If your wife mood changes, you have to change otherwise your application (home) goes into infinite loop. Girlfriend is fine. You can change at will and she can also change at will!!
You are saying something…..
With your girlfriend also you have the same problem?
Marie her and die! Don’t ask me!!
Point is this. If the communication between the objects is loose, we can better manage the current/missing requirements and also changes. Objects should not be in direct contact with one another.
But why this point used to irritate me?
Because I was wondering, if we need to make changes to an object, we have to change. What is the difference between having an interface in between or not? How, if interface is there in between it becomes great design otherwise it becomes wife (sorry tight coupling)?
You have the same question?
Let me tell you in single line. “I was wrong. We should not create interface for each and every class”. Dot.
Think of having an interface in your design only if your application needs to talk to section of similar objects. Don’t blindly create an interface for each class you are having in your solution. Adding an interface everywhere doesn’t make your wife as girlfriend.
What I mean by section of similar objects?
Suppose your application need to behave differently for different users. Create an interface and provide access to user objects via that. Likewise, you want to handle sales tax for different countries. Create an interface for sales tax and provide access to the required object via that. That means, interface may be needed where one to many relationship between objects exists.
Here one more question comes.
You can say. I don’t create separate objects for different users. I will create a single class for users and I will write if conditions or switch conditions for user roles and write the code for each user role in that class. Likewise, you can say, I will not create separate sales tax objects for each country. I will create single sales tax class and using if else condition I will write code for each country.
I think this is the time to re-phrase the second point “Identify what is going to vary in your application and hide them under an interface.”
Point is, you are telling different user roles (new role may get added in future), different countries (new country may get added or sales tax rules may get changed for an existing country). These are the candidate objects going to change in future. Then go for an interface and hide them. If you do that, calling application code need not change as it always talk to the interface. New object types can be added for that interface and of course each individual object can be changed with minimum impact.
Again, it is a design decision. If user role is a simple property and based on that if you are changing little part of your code, going for separate objects might not be a good idea. You need to decide based on the context.
“Identifying what is going to vary and hide” is the key principle for most of the design patterns. Even though you follow patterns or not, try to follow this principle.
Identifying varying things in your design might be a conceptual challenge. If it is not looking very obvious and you have no clue on varying objects, just think which parts of your code you may implement with If conditions and/or switch conditions. If you could visualize any object specific If and switch conditions, that area you need to concentrate on to check if it is required to hide them under an interface.
That’s all boss.
Simple isn’t it?
Probably I may write about all 20+ patterns in my coming posts but I’m not very sure and excited to write on them. Posts on actual patterns will be like regular boring explanation of giving one sample for each pattern and some theory. If I can come up with any other interesting way, I will let you know.
Hope you enjoyed this journey. If possible, open any patterns book and read. If you are finding it more interesting than before, I’m done.
Finally….
Finally what?
Finally nothing! I’m posting the same material which I’ve written in the very beginning, i.e. three months back. After couple of attempts, I felt like, giving you central theme of patterns is more useful than providing list of patterns and giving some code examples. In other words, I felt it is more useful giving you reason(s) how/why patterns helps you in your design than giving theory on patterns.
Shall we start?
As usual I will start with a question.
When you start a new project what generally you do?
This question is boring. Isn’t it?
Ok I will ask differently.
Which phase of the project you think people take lightly generally?
This is also not so interesting question. Ok, I will not ask any question, I will give the statement.
Most taken for granted phase in the software life cycle is, “Design phase”
Reason for this is simple. As I said in one of my previous articles, people can easily escape by doing a bad design or by not doing any design. At the same time, it is not that simple to measure quality of the design. Design is highly is subjective. By looking at the design we cannot straight away say design is good or bad. In most of the cases, design quality depends on the capability of the individual who is doing the design. Means, design is an area which became person centric than process centric.
As applications grow in size, poorly designed applications become hell to code and maintain. You leave about maintainability or re-usability. First of all, something should be codable (I know this word is not there in English but I think it gives you my intention). If design is poor, developers usually feel that project is complex. Sometimes, to achieve some requirement, they may have to code at multiple places within the solution. If they change something in one place, some other place might get affected. If their lead asks them to change any requirement or add a new requirement, the developer will not be sure on where to change. Interestingly, the person who designed the project also will not be clear on the impact.
To manage software complexity, object oriented design came. We all know what is object; principles object orientation like encapsulation, inheritance, polymorphism etc..etc..but not sure how to use these principles in design. If we simply write code in a class module doesn’t mean that we used object orientation principles effectively. It is just like writing sequential programming in a class module.
At the same time, designer/architect life is not easy. It is really a challenge translating requirements into design. While designing, every designer tries to achieve object orientation. But identifying objects in the project itself is a head breaking task. It is easy saying “Identify all the nouns, those become your classes. Identify all the verbs those become your functions/methods” but practically it is not that useful. Though this guideline is useful to start with, if designer is not careful he may end up by defining too less number of objects or object creep (too many classes). Again, design phase being person centric, for few designers whole module may looks like a single object and for few others, each independent sub modules within the module may look like separate objects.
What is the solution for this then?
There is no magic formula invented but there is a way!!
As you are expecting, the way is “Design Patterns”
Of course if you open any patterns book, definition of patterns you will hear something like “Best solutions for common/reoccurring problems” This definition is misleading to many like, patterns are only useful when you encounter some problems. If you ask me I will say Design patterns are basic guide lines to make good, maintainable, re-usable code. It is true design patterns is set of 20+ best solutions to set of 20+ common problems people generally encounter in their designs. It is also true, your project may not have these 20+ problems but the crucial thing is, design patterns changes the whole mindset of the designers. After going through the design patterns, we will get an understanding on “how to look for object oriented solutions in our project for our own problems which are not necessarily part of the 20+ problems identified with in patterns”.
What is the inside magic?
I think the magic lies on the fundamentals on which patterns are built. I don’t think all the 20+ patterns are based on few common fundas but most of them “yes”, they do. In this post I would like to introduce you those fundas (This also not an English word. Please don’t mind). The way I’m presenting may not be useful for you to tell in interviews or in your business meetings but my goal is not that. If it helps you while designing your projects and if it helps you in understanding patterns, that’s more than enough for me.
Shall I go ahead?
Thanks!!
In design, there are two key points.
- Objects should be responsible and selfish.
- Objects should play hide and seek game well
I will explain these two concepts in detail. Hopefully after going through them, you will enjoy reading about patterns better than before.
Here we go.
Objects should be responsible and selfish:
Many a times, in most of the projects, we can see objects which are very generous. They perform number of tasks. They provide lot of functionality. If you have such kind of generous objects in your architecture it is most likely that you did not identify your objects properly or you just taken design for granted. Such objects in the design give you few side effects like, difficult to code, hell to maintain and inability to handle change.
This guideline says, make sure that your objects are really really selfish. It should not accept to do whatever work given to it. Authors Allan and James in their book “Design Patterns Explained” says beautifully,
"Objects should be identified with the responsibilities but not with the data and code".
Each object you defined in your problem domain should be given clear cut responsibilities. It should not do more than that. You might be identifying objects with "nouns" or any other approach but after identifying, while going through each requirement of your project, make sure you are clear on whose responsibility it is to full fill the given requirement.
True, your design might change with time during the design and coding phase. That is fine but looking at objects as something which is carrying some strictly defined responsibilities and not a generous social worker kind of thing, helps us to visualize the whole project in terms of few persons (objects) who are ready with their individual tasks to complete the project.
Needless to say, while identifying responsibilities do not think about code. It is not the time to do that. Of course, I do agree being developers we do think about code while designing the project. Bad habits die hard. Need to eliminate them by simply changing the way we think.
How to make sure your objects are selfish?
While assigning responsibilities just think like, is it possible that, this object can reject the responsibility? Can the object say firmly, "NO it is not my responsibility somebody else has to do it". In turn, if you can concretely say to the object like "NO. It is your responsibility!!" then we can assure our self that we are on the right track. This advice may look silly on paper but it works.
To conclude this guide line,
Do remember,
- Objects should be identified with responsibilities not with some code
- Objects should be selfish. It should not do other object’s tasks.
Objects should play Hide and Seek Game well:
This guideline, I think fundamental to any design pattern. Directly or indirectly most of the patterns built around this. Your design also should give top priority to this.
I thought of not giving any coding examples in this introduction but please do not mind for the below single line
MyObject myVaraible = new MyObject();
What does this line do? You have defined an object called MyObject() and accessing it with a variable called "myVariable". Now by using myVariable we can happily use functionalities provided by the MyObject. Of course we do create objects to be used by some part of the application like this only. But this guideline says as far as possible do not allow your objects to be created with "new" keyword. dot.
Then how anyone can use your object?
Through interface!!
Why?
Boss, objects are like your mother and wife. If you directly allow them to communicate, house becomes a mess. You just stand between them as an interface and allow them to communicate through you only.
?????????
I’m kidding and forgive me if you are a woman but there is no rocket science in this guideline.
Different people give this same guideline differently. Gang Of Four, in their book on Design Patterns says this guideline as "Design to interface, not to implementation". If you do not like technical words and ask me to explain in plain English here we go.
In any software project, what is single most common problem which we all know and experienced? I should not say single factor. In fact there are two things.
1. Missing requirements
2. Change in requirements
I know you will agree with this even though you are the most brilliant architect/designer currently living in this universe. Goal of any designer/architect is to take these factors into account while designing. Though it is not possible for any designer to anticipate when/where changes going to come but following this guideline helps us to effectively deal with known/unknown/missing requirements.
The goal of any designer should be to design in such a way that, his design allows him to change/add requirements at any point of time. Though this is quite optimistic goal, designer should try to achieve that.
The whole purpose of this guideline is to achieve that. How it achieves it?
In two ways
1. By hiding your objects under an interface. This way, calling applications always talk to the interface. They are no way it is connected to your real object. That allows your object to change at will.
2. Identify what is going to vary in your application and hide them under an interface. Again Allan and James in their book says this as "commonality and variability analysis"
Both are looking same?
May be yes.
Probably the first point can be combined with second point and conveyed. But, you know, this particular statement in the first point “That allows your object to change at will.” used to irritate me in the beginning of my learning.
For the same line, one more word people used to say..
What is that??
What is that??
Yeah!!!
”Loose coupling..”
I feel like slapping the person who says this. Don’t mistake me. My feeling about this word is nothing to do with object orientation but really I don’t know why I hate this word. Probably the word “Couple” in that ? No, not that ! May be “Loose” ? No, not that !! Ok, leave it.
Anyway still I have to use these words to make the concept clear. Otherwise shall we do another thing? We will define synonyms for tight coupling and loose coupling and use those words.
Ready!?
Tight coupling is wife and loose coupling is girlfriend. If your wife mood changes, you have to change otherwise your application (home) goes into infinite loop. Girlfriend is fine. You can change at will and she can also change at will!!
You are saying something…..
With your girlfriend also you have the same problem?
Marie her and die! Don’t ask me!!
Point is this. If the communication between the objects is loose, we can better manage the current/missing requirements and also changes. Objects should not be in direct contact with one another.
But why this point used to irritate me?
Because I was wondering, if we need to make changes to an object, we have to change. What is the difference between having an interface in between or not? How, if interface is there in between it becomes great design otherwise it becomes wife (sorry tight coupling)?
You have the same question?
Let me tell you in single line. “I was wrong. We should not create interface for each and every class”. Dot.
Think of having an interface in your design only if your application needs to talk to section of similar objects. Don’t blindly create an interface for each class you are having in your solution. Adding an interface everywhere doesn’t make your wife as girlfriend.
What I mean by section of similar objects?
Suppose your application need to behave differently for different users. Create an interface and provide access to user objects via that. Likewise, you want to handle sales tax for different countries. Create an interface for sales tax and provide access to the required object via that. That means, interface may be needed where one to many relationship between objects exists.
Here one more question comes.
You can say. I don’t create separate objects for different users. I will create a single class for users and I will write if conditions or switch conditions for user roles and write the code for each user role in that class. Likewise, you can say, I will not create separate sales tax objects for each country. I will create single sales tax class and using if else condition I will write code for each country.
I think this is the time to re-phrase the second point “Identify what is going to vary in your application and hide them under an interface.”
Point is, you are telling different user roles (new role may get added in future), different countries (new country may get added or sales tax rules may get changed for an existing country). These are the candidate objects going to change in future. Then go for an interface and hide them. If you do that, calling application code need not change as it always talk to the interface. New object types can be added for that interface and of course each individual object can be changed with minimum impact.
Again, it is a design decision. If user role is a simple property and based on that if you are changing little part of your code, going for separate objects might not be a good idea. You need to decide based on the context.
“Identifying what is going to vary and hide” is the key principle for most of the design patterns. Even though you follow patterns or not, try to follow this principle.
Identifying varying things in your design might be a conceptual challenge. If it is not looking very obvious and you have no clue on varying objects, just think which parts of your code you may implement with If conditions and/or switch conditions. If you could visualize any object specific If and switch conditions, that area you need to concentrate on to check if it is required to hide them under an interface.
That’s all boss.
Simple isn’t it?
Probably I may write about all 20+ patterns in my coming posts but I’m not very sure and excited to write on them. Posts on actual patterns will be like regular boring explanation of giving one sample for each pattern and some theory. If I can come up with any other interesting way, I will let you know.
Hope you enjoyed this journey. If possible, open any patterns book and read. If you are finding it more interesting than before, I’m done.