Modelling the world with code: First steps in object oriented programming

Michał Jaglewicz
6 min readNov 21, 2021

--

Vision of modelling a car. CC 3.0 by Wikimedia Commons.

I would like to start a series of the articles to find the best practises on modelling the real world into code. But not into any code, but a code which is self explanatory, maintainable, refactorable.

This and further articles are not the final state, they are rather to open a discussion and exchange practises and ideas. So feel free to be critical to any of the presented thought.

First of the articles I would like to devote to object oriented programming as a start to any modelling some real world entities into the code. At this point I would like to be language agnostic. Later, when ideas like isolation of models will be discussed we can think of capabilities of different languages in this matter. Also code examples are very ascetic, just to focus on the discussed subject.

Car example

When you start some of the object oriented programming courses you can find some example with car. So here is kind of an example related to car object:

Car {
color
make
model
wheels
startEngine()
}

So this kind of examples may seem reasonable as they are trying to explain to the person who is doing her/his first steps in programming. Imo the person who is trying to learn something should be learned good principles from the very beginning. So, what is wrong with this kind of objects? From the object perspective there is nothing wrong, because objects are not self-conscious and do not care how they look. We can even generate the object like

Car {
colorOfDriversTie
hasHorseHeadInTrunk
fireACigarette()
playElvisPresley()
}

So I would say that first principle of modelling objects should be thinking of the modeled relationship between objects and what properties of the object are interesting to the modeled situation. This is exactly what physicist are doing when they are trying to understand the nature of the world. They are selecting only those properties/dimensions which are correlated to the phenomenon. Next they are trying to find out how the relations between those properties and phenomenon look like. The other useful concept could be the Occam’s razor: “Entities shouldn’t not be multiplied beyond necessity”. So let think together when there is a necessity to multiply and when not.

Car example in a context

We should ask ourselves in which context we are thinking about this car. Is this a concept of car seller? So maybe we just need to know properties like askPrice, colour, productionYear ,`dateOfPurchase`, …

If we are talking about context of car rental, we may think of the availabilityDates and functions like rent(..) , return(..) . So properties and functions without context are meaningless. And this should be stated in any entry level course of object oriented programming.

But is it Car class enough to be just one entity in the context of different aspects of car rental? We can think that we have a car which is just in our resources but is not rentable. Someone can say that we can add a property isRentable and it will solve the problem. But the question is when we want to just see what cars we have in stock, do we need to know is it rentable? If I want to understand if a given car is rented at this moment, do I need to know what is the colour of the car? So this brings the idea of context separation and its influence on modeled entities.

So maybe Car should stay as just kind of entity with some basic parameters about how it look from the material side, but the properties of its rental should be the other entites ie.

Rental {
car
beginDate
endDate
renter
}

At the same time we can think of which properties could have a car in context of being available to be rent:

RentableCar {
car
pricePerDay
...
}

The same way we can think of the entity which expresses car in context of the stock:

StockCar {
car
buyingPrice
buyingDate
...
}

A few words about inheritance

In many examples (especially on entry level) we can find that inheritance is so nice and tidy way of organize classes. But be careful with inheriting properties. I would say that inheritance a class to use it in a class for a new context is not the best idea. Imagine that we are inheriting a Carin a StockCar. Maybe right now it is fine, but maybe in the future we want to add a new property to the Car which is not needed in StockCar , this way we are adding unwanted coupling between classes. I am more often having common interfaces as some classes can have some common context, than to have inheritance. Because it is very rare that two classes are really used in their whole life cycle in the same context.

I saw it many times in e-commerce software, when someone was creating something like Product with some basic properties and then later was extending this class having something like NonMaterializedProduct because some of the properties of the first class was useful, but this NonMaterializedProduct was used in a different context, ie has no weight. And then you need to do some acrobatics like get weight() {return 0} but does non-materialized product has weight at all, and using weight property is justified? Or maybe on getting weight value we should throw an error: I am virtual, I have no weight. And if we go further with this zero weight we must then make sure in other systems that ie. we are not allowing to send by mail this virtual product. Because we are pretending that modeled not materialized product is just an extension of materialized product, which is questionable. But we can leave those two classes separate with no inheritance and just have some common interface ie. PricedProduct this way we now that every product with this interface has its price and it can be used in all price contexts.

Is object always a model of real entity from the context?

Let’s think that tomorrow I have scheduled a meeting with my friend. And I am sending him a message with some details:

Message {
action: "meet"
where: "restaurant"
when: 23/12/2020 7:00UTC
}

Is it a model a real meeting? Or is it only information about this meeting, some kind of projection of some properties of a real meeting? Message is never a materialized (in terms of modelling, but of course a message has to be passed using some real world medium) thing and must not be modeled as a real thing. This will be very important later when we will be thinking about storing/persisting some models in databases.

But at the same time I can model a real life entity Meeting which can have very similar properties, but conceptually they are not the same as properties in the message. Ie. I can have a function in Meeting class to reschedule(..) the meeting, because real life event can be rescheduled. But can I reschedule Message about Meeting ? Not really. I can take a phone and send a new message with new data about rescheduled meeting. This idea of the message can be materialized in programming as concept of data transfer object. So those data objects they don’t have to be modeled as real entities, they can have different properties, their structure can be flat, but also set of operations (functions) on them must be very limited to the construction, getters, sometimes setters.

So this bring another interesting ideas about objects like immutability. Some properties of models of real thing can change, but do messages can or should change? It lead to another discussion about function naming, setters, getters, etc. which I try to handle in the next article.

--

--