Forget the Domain, the Model and MVC; Let's Talk About Layered Applications
In my job, as technical lead, I am frequently asked general programming questions by the junior developers. I love the questions because it gives me an opportunity to share the knowledge I've been fortunate to acquire over the years. Also, it helps me find out or to ponder on things that I don't know.
A couple of days ago I presented a class titled "On Clean Code", based on the philosophy presented by Robert C. Martin in his book Clean Code. The class consisted of several exercises, one of which consisted of a challenge to clean up a function that was poorly written. The function contained many violations of clean code that Martin outlines, such as abbreviated variable names, non-descriptive variables, etc, but the biggest fallacy in this function was that it had too many responsibilities.
The function's responsibilities included
Most of the class members did a good job of identifying most issues, such as the removal of the abbreviations and getting rid of multiple return values, etc. Some even re-factored the code into multiple functions to abstract some of the logic. I commended one of the solutions because the developer separated the UI concerns by totally removing the message box out of the class. Which, finally, leads me to the point of this blog.
A junior developer later told me that he didnt't understand what my reasoning was for commending that solution. He asked me why it was necessary to pull UI logic out of the business layer (err.. Domain). I explained to him that it was necessary to separate concerns. Many times when we talk about concerns, we are really talking about responsibilities. For example a function to authenticate login should not validate user/password and also return a reason. It shoud do either or but not both. Let's assume that's a correct statement (I know some of you will dissagree so let's just assume that it is correct). That is a violation of the Single Responsiblity Principle, and in my opinion requires a separation of responsibilities, but it is not a violation of Separation of Concerns. Separation of Concerns is concerned more with separating the overall responsibilities of each layer in a layered application.
I went on to explain that applications should be layered. I explained that we (the community) have been talking about layering for many years and while there are different ways to accomplish this, the basic goal is to separate UI Logic, Business Logic and Data Logic into their own separate layers. In this case that goal failed because a message box was popping up right from the business layer - basically going from Business Layer to the User. The UI had contaminated the business layer or better said the Business Layer was contaminated with UI Logic.
To add some context to the problem, one of the scenarios described was that the business logic in this challenge was shared by a windows application and also by a web service. The problem with the message box popping up was that it created a timeout exception error. This occurred whenever the login was attempted from a handheld device that made use of the web service(whenever the login was not valid). So while the application worked fine from the windows application, from the web-service it would result in a time out error. Simply put a web service cannot pop up a message box, there is not UI for a web service!
I walked over to the whiteboard with him and drew up the usual layers; UI, Presentation, Domain, Data Access and pointed out that business logic should not be cluttered with code that belongs in the UI layer. I pointed out that the message box was UI and as such it belongs in the UI layer. Below is my depiction of this drawing (recreated from memory).
I thought I had done a good job of explaining the concept of layering, but his understanding was that it was just a set of rules that had been established. He still didn't understand why. I explained to him that each layer should only talk to other classes within its layer or to the layer beneath it. I also explained that at no time should a layer beneath bypass the layers above it and assume one of their responsibilities. I went on to explain that in order to re-use the business logic, that it should have no side effects or perform additional responsibilities. That type of violation rids business function of it's capabilities for reuse. Eventually it clicked and he understood the concept of layering. This is when some things dawned on me.
1. Layering Applications is a New Concept - Ok, ok it is not new at all, not to you or me at least. However it is new to junior developers. Schools just barely gloss over the topic and even in their best attempts they fail to enlighten the student. Keep this in mind with your junior developers.
2. We need more new speakers at our user groups - Don't get me wrong here. We definitely need our existing speakers. Those that are leading the rest of us. The seasoned speakers are talking at moderate to advanced levels, which demands a mid-level to advanced audience. Perhaps newer speakers feel more comfortable with introductory topics. And introductory topics are nothing more than just labor for more seasoned speakers.
We need the speakers that will speak to our most junior developers. I am not just talking about this topic in particular. I am talking about any topic that the more advanced developers now take for granted such as Continuous Integration, Unit Testing, Writing Build Scripts, Writing Better Code, Intro to this or to that.
3. Forget the Model - If you are a newbie, begin with understanding the concept of separation of concerns. Sure the model conversation is great, and MVC is a great pattern for layering your application but you should have a high level understanding of the basis for this concept.
4. Forget MVC - read item number 3
5. I am exagerating all of my points to make one point and also being facetious - let's talk about layering before we move to it's more specialized components such as Domain Driven Desing (DDD), MVC, Killer Domain and Models, etc.
Here is the code in question that prompted this whole discussion.
What are your thoughts on this post? Please post your comments below.
A couple of days ago I presented a class titled "On Clean Code", based on the philosophy presented by Robert C. Martin in his book Clean Code. The class consisted of several exercises, one of which consisted of a challenge to clean up a function that was poorly written. The function contained many violations of clean code that Martin outlines, such as abbreviated variable names, non-descriptive variables, etc, but the biggest fallacy in this function was that it had too many responsibilities.
The function's responsibilities included
- Authenticating a login (username and password) by returning a boolean value to indicate if the login was valid
- Alerting the user why the login failed - by using a Message Box
- Returning a string value as an out parameter to provide the message for the failure to login
Most of the class members did a good job of identifying most issues, such as the removal of the abbreviations and getting rid of multiple return values, etc. Some even re-factored the code into multiple functions to abstract some of the logic. I commended one of the solutions because the developer separated the UI concerns by totally removing the message box out of the class. Which, finally, leads me to the point of this blog.
A junior developer later told me that he didnt't understand what my reasoning was for commending that solution. He asked me why it was necessary to pull UI logic out of the business layer (err.. Domain). I explained to him that it was necessary to separate concerns. Many times when we talk about concerns, we are really talking about responsibilities. For example a function to authenticate login should not validate user/password and also return a reason. It shoud do either or but not both. Let's assume that's a correct statement (I know some of you will dissagree so let's just assume that it is correct). That is a violation of the Single Responsiblity Principle, and in my opinion requires a separation of responsibilities, but it is not a violation of Separation of Concerns. Separation of Concerns is concerned more with separating the overall responsibilities of each layer in a layered application.
I went on to explain that applications should be layered. I explained that we (the community) have been talking about layering for many years and while there are different ways to accomplish this, the basic goal is to separate UI Logic, Business Logic and Data Logic into their own separate layers. In this case that goal failed because a message box was popping up right from the business layer - basically going from Business Layer to the User. The UI had contaminated the business layer or better said the Business Layer was contaminated with UI Logic.
To add some context to the problem, one of the scenarios described was that the business logic in this challenge was shared by a windows application and also by a web service. The problem with the message box popping up was that it created a timeout exception error. This occurred whenever the login was attempted from a handheld device that made use of the web service(whenever the login was not valid). So while the application worked fine from the windows application, from the web-service it would result in a time out error. Simply put a web service cannot pop up a message box, there is not UI for a web service!
I walked over to the whiteboard with him and drew up the usual layers; UI, Presentation, Domain, Data Access and pointed out that business logic should not be cluttered with code that belongs in the UI layer. I pointed out that the message box was UI and as such it belongs in the UI layer. Below is my depiction of this drawing (recreated from memory).
I thought I had done a good job of explaining the concept of layering, but his understanding was that it was just a set of rules that had been established. He still didn't understand why. I explained to him that each layer should only talk to other classes within its layer or to the layer beneath it. I also explained that at no time should a layer beneath bypass the layers above it and assume one of their responsibilities. I went on to explain that in order to re-use the business logic, that it should have no side effects or perform additional responsibilities. That type of violation rids business function of it's capabilities for reuse. Eventually it clicked and he understood the concept of layering. This is when some things dawned on me.
1. Layering Applications is a New Concept - Ok, ok it is not new at all, not to you or me at least. However it is new to junior developers. Schools just barely gloss over the topic and even in their best attempts they fail to enlighten the student. Keep this in mind with your junior developers.
2. We need more new speakers at our user groups - Don't get me wrong here. We definitely need our existing speakers. Those that are leading the rest of us. The seasoned speakers are talking at moderate to advanced levels, which demands a mid-level to advanced audience. Perhaps newer speakers feel more comfortable with introductory topics. And introductory topics are nothing more than just labor for more seasoned speakers.
We need the speakers that will speak to our most junior developers. I am not just talking about this topic in particular. I am talking about any topic that the more advanced developers now take for granted such as Continuous Integration, Unit Testing, Writing Build Scripts, Writing Better Code, Intro to this or to that.
3. Forget the Model - If you are a newbie, begin with understanding the concept of separation of concerns. Sure the model conversation is great, and MVC is a great pattern for layering your application but you should have a high level understanding of the basis for this concept.
4. Forget MVC - read item number 3
5. I am exagerating all of my points to make one point and also being facetious - let's talk about layering before we move to it's more specialized components such as Domain Driven Desing (DDD), MVC, Killer Domain and Models, etc.
Here is the code in question that prompted this whole discussion.
What are your thoughts on this post? Please post your comments below.
Comments