Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / programming / architecture

Application Design - A Post Mortem of a Bad Design

3.36/5 (9 votes)
14 May 2017CPOL4 min read 14.2K   57  
Application design - a post mortem of a bad design

Application Design

Readers of this Topics - Application Architect, Developer

Coverage Topic

How we can improve our application design? How to use state pattern for a single object with multiple states? Guessing, you have an initial knowledge about GOF design pattern. No? If no, never mind.

  • What's state pattern
  • When, where and how to use state pattern
  • What's the main reason to use
  • What's the benefit

Let's Drill Down the Basic Concept

My Problem

I have learned the design pattern and I know the implementation. But the question is, why, I need the pattern. If I don’t use any pattern, then nobody ever complains about the code. It means that I can avoid the pattern during my design. Can I do that? Why should I take extra headache?

Investigation

Scenario 1: Software Professional

I’m a software professional and I have to implement micro services application. So, at the beginning, I prepare the architectural design document (say, high level design document). After this phase, I work with developers and implement the design. Finally, I write unit testing. So, I have different roles. The role means an expected behavior associated with a particular position.

Image 1

Therefore, a software professional has different behaviors depending on the roles or states.

  • Architect role: Preparing architectural design document
  • Developer role: Writing codes and implementing the business functionality
  • White-Box Tester Role: Writing test scenarios, test cases and unit testing

Scenario 2

Image 2

I had a puppy and in the morning, I liked to play with it; so, it ran, jumped, barked. But suddenly, a car hit it and now it does not move, run, jump, and bark. So the state has been changed from live to dead.

Still Have Doubt About the Scenarios?
  • Lamp has two states, turn on and turn off.
  • Water has states, such as - hot, cold, normal, liquid, and solid.
  • Person has moods like - angry, happy, sad, tired, and drunk.

Therefore, in these scenarios, it is clear that a single object has different states and behaviors.

Implementation Magic

Class Diagram

Image 3

Design Implementation and Source Code Analysis

Image 4

In the above image, there is a “DoYourJob” method and I can implement the functionalities using either If-Else statement or switch statement.

Post Mortem Report Analysis

In the above image, I’ve marked numbers such as 1, 2 and 3.

Marked No. 1: I'm creating roles in the SoftwareProfessional class. But the problem is, these dependencies are tightly coupled in this class.

As a result, unit testing is not possible for the method of the “DoYourJob”. Why?? Because, according to the first principle, "Test the logic of the class only, nothing else”.

Therefore, if I want unit testing for this class, then it should have to be loosely coupled; otherwise, object mocking is not possible.

Marked No. 2 indicates that in future, if I want to extend another role, then I need to create an object in this class.

Marked No. 3 indicates that I need to add one more if-else or switch case for the new extended role or state.

Therefore, marked no. 2 and 3 are also the violation of the open-closed principle. Because, I want to implement one more role and it's fine; but I shouldn’t touch the “SoftwareProfessional” class. It means, if I implement another role, then I shouldn't modify anything into this class.

Why Need Good Design

  • Do I need unit testing?
  • Do I want to remove if-else or switch-case statement?
  • Do I want to remove the code duplication?
  • Do I want to minimize implementation effort for future?
  • Do I want to minimize the bug?

Considering the above questions, if my answer is - yes, then I need a technique to solve the above problem.

Note: I am considering the above given design and example.

What’s State Pattern

An object changes its behavior according to its state change.

In the class diagram, Context is SoftwareProfessional and state is an IRole.

Image 5

Class Diagram for Scenario 2

Image 6

Advantages

Removing conditional logic duplication and replacing conditional code with polymorphism.

Damn Good Design

The above example indicates that single object has multiple roles or states and if state changes, then it changes the behavior during runtime. So, considering the State Pattern of the GOF, I can solve this problem.

Class Diagram

Image 7

Design Implementation

Image 8

Good Design Analysis

  • Because of the loose coupling, I can mock the object of the IRoleState; as a result, I can test the logic of the method of DoYourJob.
  • I have removed the if-else or switch-case statement.
  • Anytime, I can implement new IRoleState; but I don't need to modify the SoftwareProfessional class. So, it satisfies the open-closed principle.
  • Clean code and easy to understand.

Demo Time!!

Image 9

The first time when I learned the if-else statement and for-loop statement and understand how to apply it to the application, then I realized that I am a developer. You need if-else statement; but you also need to know when and how to use it. If you realize that, then you are on the way to being an excellent developer.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)