A Simple Guide to Object Orientation
Designing and implementing object-oriented systems require skills that take time to master. Here’s some food for thought for those of you who are just starting out.
Classes are used to encapsulate related data fields and functions that operate on those variables. We define a class when we want to use objects of this type more than once in the same program.
The object-oriented thought process is similar to how we think in real life: we have a mailbox, a car, or an ATM. All of these objects have some properties which determine their look and function. Similarly, we should identify the distinct entities that will play a well-defined role in our system and map them to classes.
Let’s start with the classic program that prints “Hello, World!” to the console. What entities do we need here?
We don’t need any classes since our program is a one-liner (okay, it might be multiple lines depending on the programming language, but you get the point). On the other hand, if we want to build a budget tracker application, the situation will be different.
Our budget tracker needs to keep track of income and expenditure items. We have already identified the entities that our application will handle: income and expenditure items. So, we create two classes: Income and Expense. These classes need at least two attributes to represent the amount and the date of the transaction. But what if we spend or receive in multiple currencies? Then, we will need to add another attribute to specify the currency.
We don’t want our users to store random stuff in the Income or Expense class; we want to ensure that the amount and date properties store valid data. Here’s where data hiding comes into play. Instead of allowing to set the amount and date field directly, we make them private and provide the corresponding setter and getter methods.
We also want to persist the income and expense items–otherwise, everything would be lost once the user quits the app. So, we define a Persistence class to manage the saving and restoring of these objects.
It would be helpful also to show the total amount of daily, weekly, monthly, or yearly transactions. You guessed it: we need yet another class to perform these calculations–let’s call it Calculator.
As new needs arise, we identify the new entities and add the corresponding classes to the application.
One important thing to note: In OOD/OOP, nothing is carved in stone.
Some may question our decision to create two separate classes to represent the income and expense items. Instead, they’d suggest defining a single Transaction class and adding a property called isExpense. If this property is set to true, we’re dealing with an expense. Otherwise, it’s an income.
Perfect! We got rid of a class and simplified our design. But let’s say we need to add a third type of transaction: donations. We need to adapt our design by changing the isExpense field’s name to, say, transactionType. Also, we must update its type from Boolean (which can only hold two values: true or false) to something that can hold multiple values, such as an enumeration. And then, we need to refactor our code to use transactionType property instead of the obsolete isExpenseproperty.
The process of designing and implementing object-oriented systems is beautiful but also challenging. Although there are some guiding rules and best practices in place, the OOP world is quite blurry.
We have to rely on our experience and knowledge to make the best decisions. There are many different solutions to the same problems–and usually, none of them is without compromises.
If you want to learn more about object-oriented design, check out my course UML and Object-Oriented Design Foundations:
https://www.udemy.com/course/uml-and-object-oriented-design-foundations/?couponCode=UML-SEP2021
The link contains a promo code that will save you 84% on the course.
Best,
Karoly
Responses