Abstract Object Oriented Analysis and Design in Python
Often, when programmers are introduced to “serious programming”, one of the first things they are taught is Object Oriented Analysis and Design (OOAD). In this software design methodology, things in the “real world” are mirrored within the code; a person becomes a Person object, a car becomes a Car object and an electricity transmission line becomes an Electricity Transmission Line object.
The thinking behind this design methodology goes as follows.
“It works in the real world, as you can see. Therefore, if you mirror exactly what you see in the real world within the computer system, then it must work.”
Things are not always that simple, however.
Distinct Systems and Indistinct Systems
Generally speaking, when we come to model a real-world system in a program, we may be presented with two types of systems: distinct systems, and indistinct systems.
Distinct Systems
A distinct system is one in which everything is well defined and things proceed according to a specified plan. An example of a distinct system is a car engine. Here, every part is mechanically engineered to a nicety, and only interacts with the other parts in the engine according to a strict set of rules which were precalculated prior to constructing the engine.
If we adopt the classic object-oriented design methodology here, we will be on firm ground. Since “real life” is modelled precisely, there is no reason we cannot represent reality in an exact object model.
Indistinct Systems
In contrast to distinct systems, indistinct systems are marked by fluid dynamics, nebulous boundaries and unpredictable interactions. For example, think about trying to exactly model an economy in a object-oriented programming language.
Here, the clear-cut categories and predictable interactions loved by object-oriented design quickly dissolve. For instance:
- Business Definition: A business can quickly “change shape” from being a small startup to being an internal corporation.
- Interest Rates: Interest Rates can be viewed from many different perspectives:
- Central Bank Perspective: Raising interest rates can be a measure to curb inflation, ensuring long-term economic stability.
- Consumer Perspective: The same rise can mean higher borrowing costs, dampening the ability to buy homes or make large purchases.
- Business Perspective: Higher interest rates could increase the cost of financing, potentially discouraging investments in expansion or R&D.
- Currency Evolution: What might begin as a novel form of digital currency, e.g. Bitcoin, can evolve into a major financial asset class influencing central bank policies and facilitating international trade.
If a programmer attempts to use classical object-oriented design to model a system that handles these realities, they may soon find that they have designed themselves into a corner, and the clear-cut distinctions they made between different classes prevents them from being able to implement the functionality required by end-users.
For this reason, there is currently a movement back towards functional programming, which focuses on on transformations and flows of data, instead of trying to model individual, discrete entities. For example, instead of trying to fit an economy into neatly defined objects and their interactions, functional programming would instead model the flow of data (like money, goods, or services) through various transformations (like investments, taxes, or trade).
Modelling the Abstraction
A third option in object-oriented program design is to model the system abstraction, this means that instead of modelling concrete objects (or notions) such as cars, people and financial institutions, we can instead model the abstracted qualities of these entities, which interact with each other within the system that the cars, people and financial institutions operate in.
For example:
Entity | Traditional OOP Approach | Modelling the Abstraction |
---|---|---|
Car | Create classes for wheels, engine, or doors. | Model the forces at play in the power generation and transmission system of the entire car, the computer control system of the entire car and the safety system of the entire car. |
Person | Create different classes that a person can “fit into”. For example, a person could “be” a customer, a salesperson or admin staff. | Model the person’s resources (e.g. financial), capabilities (e.g. skills) and activities. |
Financial Institutions | Create classes for banks, lending societies or mortgage providers. | Model institution liquidity, reliability, or risk. |
By modelling the entity abstraction up-front, the programmer can allow system interactions to occur natively within the software system without having to first provide a layer of abstraction on top of classes that represent concrete realities.
Abstract Object Oriented Model of a Tree
As an example of this approach to Object Oriented Design, let’s write a object-oriented Python program that models the functioning of a tree. In classical object-oriented design, we would model the trunk, the branches, the roots and the leaves as individual classes, and then implement the interactions that occur between them.
In the suggested system abstraction object-oriented design, we will instead model the energy aspects of the tree, the logical aspects of the tree and the control aspects of the tree as the objects in our program. This qualitative division of concerns (energy, logic and control) is based on previous posts where this was introduced as a universally applicable method of qualitative systems analysis (see Qualitative Systems Analysis using ChatGPT and Expanding Triadic Systems Analysis).
In other words, instead of grouping the functionality of a tree according to the functions of discrete physical elements of a tree, we will group tree functionality as perceived from the triadic division of energy, logic and control.
This gives us the following grouping of functions:
Functional Group | Description | Examples |
---|---|---|
Energy related functions | Grouping of functions related to the tree’s energy processes. |
|
Logic related functions | Functions that make decisions based on energy levels and tree health. | Decide growth and fruit production according to energy level and tree health |
Control related functions | Functions related to maintaining and assessing the tree’s health. | Assess health |
In this way, we have kept the advantages of the object-oriented paradigm, but have avoided the constraints that arise when modeling a rigid structure to represent an organic system. Using an abstracted model means the program is adaptable to change, instead of being rigidly tied to the initial analytical division of reality.
Class Design
The program uses the following class design.
- DynamicAspect: A base class for the triadic design philosophy. No direct functionality but serves as a parent class for the Energy, Logic, and Control aspects.
- EnergyAspect: Deals with the tree’s energy, including its photosynthesis process, respiration, growth, and water requirements.
- LogicAspect: Manages the tree’s internal logic, deciding its growth and fruit production.
- ControlAspect: Assesses the tree’s overall health based on various factors.
- Tree: A holistic class that integrates all the triadic aspects to represent a tree.
EnergyAspect
- Uses photosynthesis to generate energy (stored nutrients). The efficiency of photosynthesis is influenced by:
- Temperature
- Humidity
- CO2 concentration
- Latitude (affects day length)
- Tree size (affecting its canopy)
- It also computes the amount of water required by the tree based on temperature.
- Captures energy consumption for the tree’s respiration and growth. Tree growth (increase in tree size) happens only if there are sufficient nutrients.
LogicAspect
- Decides the growth rate and fruit production of the tree based on:
- Stored nutrients
- Day of the year (seasonal influence)
- Tree’s age
- Tree’s size
- Health of the tree
ControlAspect
- Assesses the overall health of the tree considering stored nutrients and any disease factors.
Tree
- Integrate all the three triadic aspects.
- Every day, it updates:
- The age of the tree.
- Checks if the tree should have leaves (based on the day of the year).
- Generates energy.
- Assesses health.
- Decides growth and fruit production.
- The get_data method retrieves the current data of the tree, which includes:
- Age
- Stored nutrients
- Growth rate
- Tree size
- Fruit count
- Health
- Health status
Simulation
The simulate_growth function:
- Initializes a tree.
- Simulates the daily growth of the tree for a set number of days (years * 365 days). Each day:
- Sunlight, water, temperature, humidity, CO2 concentration, and disease factor values are fed into the tree.
- The tree’s data for that day (stored nutrients, growth rate, fruit count, health) is collected and stored in lists.
- Finally, it visualizes the simulation results using matplotlib. The graphs represent:
- Stored nutrients and growth rate (on one y-axis).
- Fruit count and health (on a second y-axis).
When the script is run, the tree’s growth is simulated over 5 years, and the results are visualized in a plot.
In summary, the code sets up a comprehensive simulation environment for a tree, integrating environmental factors, the tree’s energy processes, logical processes, and health considerations to understand how the tree grows, how healthy it remains, and how many fruits it produces.
Sample Output
The following graph shows the simulation of a tree’s activity over the course of 5 years.
- Stored nutrients: Nutrients are generated during the summer by photosynthesis, and are consumed by tree growth, fruit production and expiration (breathing).
- Growth: The growth rate increases during spring and summer but is controlled by the availability of sufficient nutrients.
- Fruiting: Fruits are generated after the third year of growth, according to nutrient availability.
- Health: If the nutrients level falls below a specific value then the tree’s health is adversely affected.
Code Listing
The full Python code for the triadic tree activity simulation is available on GitHub here: https://github.com/edwardchalk/TreeGrowth/
Summary
Using classical Object Oriented Analysis and Design (OOAD) to model complex, dynamic systems can be challenging and limiting. Distinct systems, which are predictable and well-defined, are suited to traditional object-oriented modelling. However, indistinct systems, characterized by fluid dynamics and unpredictability, tend to resist exact modeling.
To respond to this challenge, and not to do away with OOAD altogether, we can model the system abstraction. Rather than modelling concrete entities, this OOAD method models the abstracted qualities and interactions of entities within the system. The triadic division between energy, logic, and control can serve as a generic guide for this abstracted modeling.