Skip to main content

Better Software Design: Object Oriented Design

Beyond Procedural Programming
In the old days, programming languages were procedural. That means they accomplished separation of concerns through placing code for each concern in a separate procedure (sometimes called a function or a subroutine). Like many developers, I learned procedural programming before object oriented programming languages were popular. We need to be warned to avoid anti-patterns (common big software mistakes) that come from trying to program in an object oriented programming language, in a procedural way. Let's take a look.

How is Object Oriented Design Different?
Object oriented design accomplishes separation of concerns by placing code for each concern in its own class or interface. Procedures in these classes and interfaces are called methods. Some examples of object oriented programming languages include Java, Objective C, C++, and, sometimes, C#. Also, many traditionally non-object oriented programming language include some object oriented features. For example, these languages include JavaScript, Python, and PHP.
Object oriented design accomplishes separation of concerns by placing code for each concern in its own class or interface.
The Dangers of Anti-patterns in Object Oriented Design
Before becoming a master developer, you may have attempted to program in an object oriented language in a non-object oriented way. Or, you may have designed the code to be partly object oriented and partly not object oriented. Code with such anti-patterns might kind of work for a while, but to be master programmers, we want to take our software development skills to the next level and produce the highest quality code. Code with anti-patterns is very low quality and causes serious software problems.

The Way of the Non-master
Using pseudo-code (plain English that resembles programming languages), we will consider an example. Imagine we received a project to rewrite a program that helps a user create a widget and save the widget for future use. The widget can be created in one of two colors: red or green. As is often the case with legacy software, this program was implemented by a non-master developer (which is sometimes your past self). Implementing that program in an object oriented language in the following way, would have been an anti-pattern:

Version 1:
  • class WidgetSaver
    • method start
      • Create the desktop UI
      • Add options to the desktop UI for a red or green color
      • Add a button to the desktop UI to save the colored widget, and attach the button to the save method
    • method save
      • Create a flat file
      • Retrieve the red or green color of the colored widget from the desktop UI
      • Save the colored widget of that red or green color to the flat file
We are assigned to rewrite the program to use a web UI instead of a desktop UI, to use a relational database instead of a flat file, and to add the option of the third widget color: blue. A non-master attempt may look like this:

Version 2:
  • class WidgetSaver
    • method start
      • Create the web UI
      • Add options to the web UI for a red, green, or blue color
      • Add a button to the web UI to save the colored widget, and attach the button to the save method
    • method save
      • Create a relational database record
      • Retrieve the red, green, or blue color of the colored widget from the web UI
      • Save the colored widget of that red, green, or blue color to the relational database record
As you will see, you did not have enough separation of concerns. At first this rewrite might seem short and simple enough. But, the program was intentionally oversimplified for the purposes of this example. A real program to do these things could be very long, and such a rewrite could be very complicated.

We will see that the ideas (methods) used to separate concerns in Version 1 no longer seem to serve their purpose effectively. You would have needed to make changes in many areas of the code to update code for each concern (the UI, business model, or persistence). Making the same kind of changes in multiple places takes longer and is prone to errors such as forgetting a place where changes are needed, or introducing inconsistencies. For example, it would have been easy to make mistakes like this:
  • class WidgetSaver
    • method start
      • Create the web UI
      • Add options to the bwe UI for a red, green, or blue color
      • Add a button to the desktop UI to save the colored widget, and attach the button to the save method
    • method save
      • Create a relational database record
      • Retrieve the red, green, or ubel color of the colored widget from the web UI
      • Save the colored widget of that red or green color to the flat file
Did you see how the changes were made fine in some parts of the code, but in others there were typos or missed changes, leading to inconsistencies?
  • In some places "web" was mis-typed as "bwe", and blue as "ubel"
  • The program still attempted to add the button to the desktop UI instead of the web UI--even though the desktop UI hadn't been created
  • The color blue was left out of save instructions
  • The program still attempted to save the widget to the flat file instead of the database--even though the flat file hadn't been created
This example might seem ridiculous, but these are exactly the kinds of problems that happen all the time. These problems are worse with bigger programs.

Implementing Object Oriented Design
The way to avoid the anti-pattern above, would be to put some thought into the program design before diving in and writing the program. A good question to ask yourself, is "What are the concerns in this program that should remain separate, and what are the logical classes and interfaces to create to separate those concerns?"

For this example, we might recognize that the widget is the central concern of the program, that the color is a separate concern, and that we will probably want to change the user interface and persistence without changing the business logic and vice versa. Therefore, a logical design may include these high level types:
  • class Widget
  • enumeration Color
  • class WebUserInterface of interface UserInterfaceable
  • class RelationalDatabaseRecord of interface Persistable
  • class WidgetSaver
At first this design might seem more complicated, because the example is so simple. But in complex software, it soon becomes easy to see that such good design has many advantages.
A good question to ask yourself, is "What are the concerns in this program that should remain separate, and what are the logical classes and interfaces to create to separate those concerns?"
Example of Better Design:
  • class Widget - Has property: Color
  • enumeration Color - Has possible values: RED, GREEN, BLUE
  • class WebUserInterface (of interface UserInterfaceable)
    • Use a web UI
    • method build
      • Create
      • Add options for each possible value of Color
      • Add a button to save the widget, and attach the button to the save method of WidgetSaver
    • method retrieveColor: Retrieve the color of the widget
  • class RelationalDatabaseRecord (of interface Persistable)
    • Use a relational database record
    • method saveWidget
      • Create
      • Save the widget of its color
  • class WidgetSaver
    • method start: Build the WebUserInterface
    • method save: Save the widget using the RelationalDatabaseRecord
The resulting code is compact and orderly, and the changes are isolated to the area of code they concern. It is easier to change without introducing inconsistencies. Often, when a customer requests a certain type of software changes, they are likely to request more similar changes in the future. With this design, it would be relatively very quick and easy to add, remove, or change colors, or to change to using a different type of UI or persistence in the future. For example:
  • class Widget - Has property: Color
  • enumeration Color - Has possible values: RED, YELLOW, BLUE
  • class MobileUserInterface (of interface UserInterfaceable)
    • Use a mobile UI
    • method build
      • Create
      • Add options for each possible value of Color
      • Add a button to save the widget, and attach the button to the save method of WidgetSaver
    • method retrieveColor: Retrieve the color of the widget
  • class CloudStorageRecord (of interface Persistable)
    • Use a cloud storage service
    • method saveWidget
      • Create
      • Save the widget of its color
  • class WidgetSaver
    • method start: Build the MobileUserInterface
    • method save: Save the widget using the CloudStorageRecord
For programming in an object oriented language, by investing a little extra time up front to implement high quality object oriented design, you will be well on your way to becoming a master software developer.

Popular posts from this blog

What We're About

About UsMission Statement: We provide a product to make high performing software developers happy by giving them a chance to work in a more self-directed way on software that is more meaningful to them. Core Values (in priority order):Integrity: Honesty, trustworthiness, and faithfulnessPreparation: Research, planning, and goalsReputation: Branding, naming, presence, and networkingProfitability: Product salesProduction: Product development, ideas, online contentImprovement: Research and trainingSupport: Minimal overhead Who We Are
Isaac Serafino is a Software Architect in Omaha, Nebraska. He has a strong experience developing technology solutions. He has long had the dream to lead his own startup business.
Our ProductsSnap Screen™
More efficiently provide a safe environment for using electronic devices. Sends pictures of what is on the display at somewhat random times so user knows they could be observed at any time, but the supervisor does not need to be their watching over their sho…

The Invasion of the Developer Commandos™

I. Why Deploy Commandos? It's hard to find the best people to solve difficult problems. By deploying Developer Commandos™, you can get great software developed without needing to figure out how to find the software developers. II. What are Developer Commandos? Unlike an old fashioned developer, a commando works independently. They manage themselves so you won't need to. III. How Can You Deploy Commandos? A. Create a Project Use a project host like GitHub to create a shared workspace online. Commandos will be able to contribute to your software project through this workspace. B. Obtain Incentives Use a cryptocurrency exchange like Coinbase to purchase an amount of a cryptocurrency such as Ether. You will be able to use this cryptocurrency to provide an incentive for commandos. C. Post Opportunities Use a bounty network such as Gitcoin to post bounties. A bounty describes the software problem you need resolved, and allows you to attach a cryptocurrency incentive for resolving i…