Object-Oriented programming became the dominant programming paradigm in the 90s, and its principles remain extremely valuable and widely adopted by several programming languages (e.g. Python, Java, TypeScript, etc.). If you're programming, you've must have met it on your way already.
The concept is very simple: turn everything you need to work with into an object. Then, it's up to you how many and what kind of objects you create. Today I want to share with you what I learned about separating app architecture into objects, starting with a quick introduction to Object-Oriented programming (OOP).
Table of Contents
It is a programming paradigm that structures a software program according to objects. Simply put, it creates objects that contain functions and data. This paradigm relies greatly on the concept of classes and objects.
In other words, in a OOP language, code is written to define the classes and respective objects by following four principles: encapsulation, abstraction, inheritance, and polymorphism.
Search anywhere else on the web and you'll quickly find a list of principles linked to OOP. Those are: encapsulation, abstraction, inheritance and polymorphism. Let’s see what these principles actually mean:
Encapsulation: the attributes of an entity are enclosed in itself. In other words, encapsulation is when an object (inside a class) keeps its state private and only exposes the selected information. This principle requires the ability to define some fields as either private or public.
Abstraction: hide important information in order to reduce complexity. It is when the user only interacts with specific object’s methods and/or attributes. By hiding complex details from the user, abstraction consequently reduces complexity.
Inheritance: as the name indicates, an entity can inherit attributes from other entities. More precisely, parent classes can extend their attributes and behaviors to child classes, which also means that this principle supports reusability.
Polymorphism: entities can have more than one form. Hence the ‘poly’. In sum, polymorphism is when objects are designed to share behaviors. By overriding or overloading, the same method can perform different behaviors.
This is not, however, where I'll focus on this article. At least, not on the more scholar version of the object oriented programming principles. Here you'll find more practical knowledge about object oriented programming and real insights on how to improve in the art of turning everything into an object. By the end of this article, it'll be perfectly clear why that is relevant for everyone who is programming out there.
1. Don't be afraid of creating too many classes
In my programming experience I'll always remember the day when I opened one of those big projects and the amount of files in it was simply overwhelming. That's when I though: this is impossible to understand. The concept of turning a simple idea into a huge amount of files seems an overkill, but very often it's not.
For me, the question I ask myself the most when designing app architecture is "should I create an object for that?" And, most of the time, the answer is simply:
Yes, I should.
In the end, it's much easier to read 10 files of different objects with names representing their function than 1 huge pile of code that does everything. The only issue here is organizing the large amount of files you create into a structure, that can be easy to understand and search through for anyone that might pick up your work later.
As an iOS developer, I follow what most of iOS developers use, which is the MVC model, and I always try to organize files into folders instead of just dropping them all into one place.
2. Use more subclassing
Instead of creating one class and giving it a set of properties and enum types to configure, think if it wouldn't be better just to separate those into elegant subclasses for easier identification of what they actually do, leaving the base one generic enough to keep scaling it later on.
3. Make objects generic
One of the beauties of object oriented programming is that the classes for the objects you create can be reused in other projects, which is a huge time saver. Think about that when you create objects and make them generic. The subclassing approach can definitely help you do that.
It's better to separate the class to manage API calls or in app purchases for the generic one that you can use across your projects and subclass with a specific one that will fetch you the data you need.
4. Don't tear objects apart
Sometimes I have to create a method that requires a lot of properties to be passed around. I don't want to ask for each one by one, so I decided to put them all in a dictionary or an array and pass it.
It seems convenient enough, but it never is.
I come back to it a month later, or worse, somebody else tries to use it and they have a really hard time putting the properties together exactly in the way I did, and maybe even spend some time debugging why one of those is perceived nil on their way.
In the end, it's much easier to pass the entire object of which the properties belong to, even if it has a lot more than you need. This solution also scales better because you never know when you'll need the whole object context, even if you start just with a small part of it.
All the programming languages I know are object oriented and, yet, I still keep finding different ways to answer this simple question: what kind of objects should represent this? The amount of possibilities might present a challenge when it comes to object oriented programming, but the alternative of not using is neither viable, nor desirable.
The object-oriented programming paradigm focuses on objects and on how these objects interact. It requires that the developer plans the coding upfront, which leads to better data structure and enables reusability.
This paradigm implies four main principles (encapsulation, inheritance, polymorphism, and abstraction) that must be followed when developing an object oriented software.
When OOP is implemented, some of the best recommendations developers can apply are:
1. Create as many classes as needed;
2. Use more subclasses;
3. Make objects more generic;
4. Do not tear objects apart.