Lecture
A model in programming and DDD is an abstraction that describes the domain, its data and behaviour. In DDD, the model is the central element that reflects the business logic.
Here is a detailed explanation with examples in JavaScript and PHP:
A model in programming is an abstract representation of a real-world object, process or system, created for the convenience of development, analysis and working with data.
Put simply, a model is a way of describing something from the real world so that a program can work with it.

In a general sense, a model is a structure that describes data and the operations on it. It can be part of architectural patterns such as MVC (Model-View-Controller), where the model is responsible for:
storing data,
business logic,
interacting with the database.
In DDD the term model has a special meaning:
Model = a formalised representation of the domain in code.
Therefore:
Entity
Value Object
Aggregate
Domain Service
Domain Event
These are all elements of the domain model (domain model).
That is, they make up the model of the domain, but on their own they are not “ORM models” or “Model from MVC”.
| Area | What the model means |
|---|---|
| OOP (object-oriented programming) | A class or object describing an entity (for example, User, Car, Order) |
| MVC, MVVM and other architectures | The part of the program responsible for data and the logic of working with it |
| Machine learning | An algorithm trained on data that can make predictions |
| Databases | A data storage structure (tables, relationships, schemas) |
| Business analytics | Description of processes, entities and their rules |
Simplify working with data
Allow the code to be structured
Make the program clear and extensible
Help with testing and maintaining the project
A model is a data structure and logic described in code that reflects an object or process from the real world.
A model in programming should not be confused with modelling: these are different concepts, even though they sound similar.
What it is:
A data structure and logic that describes an object or entity from the real world in a program.
Example:
A Car class with fields model, year, speed and methods drive(), stop() is a model of a car in code.
In DDD (Domain-Driven Design), a model is not just a set of classes, but a reflection of the domain in code, consistent with how domain experts think and talk about it.
In short:
model = knowledge of the business domain + rules + behaviour, expressed in code.
What a model in DDD includes
Objects with an identity that matters more than their current data.
Features:
have an id
state can change
remains «the same» object
Example:
User Order Account Character (in a game)
Where it is used:
OOP (classes and objects)
MVC/MVVM architectures (model = data)
Databases (tables and relationships)
Game logic (player model, enemy model, etc.)
What it is:
The process of creating and studying a model of a system's behaviour: an attempt to reproduce a real process or phenomenon.
Example:
Simulating car traffic in a city (traffic jams, traffic lights, driver behaviour) is modelling of a transport system.
Where it is used:
Scientific simulations (physics, biology, economics)
Game physics
Machine learning (building computational models)
3D modelling (creating objects for graphics)
| Term | Description | Example |
|---|---|---|
| Model | Representation of an object in a program | Car class |
| Modelling | The process of creating a dynamic simulation | Simulating car traffic in a city |
Model is what is described.
Modelling is how the model behaves and what happens to it over time.
The difference between a model and a class is subtle but important.
What it is:
A template (blueprint) for creating objects in OOP.
It defines the structure (fields) and behaviour (methods).
A class is a technical mechanism of the programming language.
Example:
class Car:
def __init__(self, brand, year):
self.brand = brand
self.year = year
def drive(self):
print("Driving")
The Car class can be used however you like: as a model, a utility, part of the business logic, and so on.
What it is:
The logical concept of the domain, a representation of a real-world object in a program.
A model is the idea and meaning describing an entity (User, Order, Product, Enemy, Player).
A model is most often implemented as a class, but it does not have to be
(for example, a data model can also take the form of a table in a database or a JSON structure).
Class = tool (form) Model = meaning (content)
The model answers the question: what is this in the real world?
The class answers the question: how is this implemented in code?
| Model | Class | |
|---|---|---|
| Idea | Player in the game | class Player |
| Meaning | The player's characteristics and logic | Fields hp, speed, methods jump() |
| Area | Domain logic | Code structure |
A model is a concept.
A class is its implementation in code.
The player model is the data and rules: health, speed, inventory, damage.
The PlayerController class is a component with C# code that implements this model.
Example in PHP (MVC):
class Product {
public $name;
public $price;
public function __construct($name, $price) {
$this->name = $name;
$this->price = $price;
}
public function applyDiscount($percent) {
$this->price -= $this->price * ($percent / 100);
}
}
Example in JavaScript (MVC):
class Product {
constructor(name, price) {
this.name = name;
this.price = price;
}
applyDiscount(percent) {
this.price -= this.price * (percent / 100);
}
}
In DDD, a model is not just a data structure, but a reflection of business reality. It includes:
Entities are objects with a unique identity.
Value Objects are objects without identity, defined by their value.
Aggregates are groups of related entities.
Domain services are operations that do not belong to a specific entity.
class Order {
constructor(id, items) {
this.id = id;
this.items = items;
}
getTotal() {
return this.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
}
class Item {
constructor(name, price, quantity) {
this.name = name;
this.price = price;
this.quantity = quantity;
}
}
class Order {
private $id;
private $items = [];
public function __construct($id) {
$this->id = $id;
}
public function addItem(Item $item) {
$this->items[] = $item;
}
public function getTotal() {
$total = 0;
foreach ($this->items as $item) {
$total += $item->getPrice() * $item->getQuantity();
}
return $total;
}
}
class Item {
private $name;
private $price;
private $quantity;
public function __construct($name, $price, $quantity) {
$this->name = $name;
$this->price = $price;
$this->quantity = $quantity;
}
public function getPrice() {
return $this->price;
}
public function getQuantity() {
return $this->quantity;
}
}
Focus on the business logic, not on the technical implementation.
A ubiquitous language between developers and the business.
Separation of responsibilities: the model does not depend on the UI or the database.
Simplifying complex systems through aggregation and contexts.
Objects without identity, defined only by their value.
Features:
immutable
compared by value
do not exist on their own
Example:
Money (amount + currency) Email Coordinates Damage
A group of related objects that can only be changed through the aggregate root.
Example:
Order (Aggregate Root) ├─ OrderItem ├─ DeliveryAddress (Value Object)
Rule:
from the outside you can only work with the Aggregate Root
Domain logic that does not belong to a single entity.
Example:
DamageCalculator PaymentPolicy MatchmakingService
Facts that have already happened in the domain.
Example:
OrderPaid UserRegistered BossDefeated
DTOs
ORM models as «bags of fields»
Controllers
Repositories (they serve the model, but are not part of it)
| OOP without DDD | DDD |
|---|---|
| Data + getters | Behaviour and rules inside the model |
| Business logic in services | Business logic in the domain |
| Technical names | Ubiquitous Language |
«Ubiquitous Language» is the term Eric Evans uses, within domain-driven design, to describe the practice of creating a common, precise language between developers and users. This language should be based on the domain model used in the software, which is why it needs to be precise, since software handles ambiguity poorly.
In Domain-Driven Design (DDD), a model is not just a set of classes with methods. It is a reflection of business reality, and you can do far more with it than simply call its own methods. Here is what you can do with a model beyond its internal logic:
Link the model with other aggregates via domain events or services.
Example: an order (Order) can trigger the creation of an invoice (Invoice) via a domain service.
Check the model against business rules.
Example: verifying that the order total does not exceed the customer's limit.
Moving operations that do not belong to a specific entity into separate services.
Example: calculating a discount using a complex formula that depends on external factors.
Converting the model into JSON, XML, SQL and other formats for storage or transmission.
Example: saving an order to the database or sending it via an API.
Recording changes to the model as events.
Example: logging every change to an order's status.
Using the Specification pattern to check conditions.
Example: IsEligibleForDiscountSpecification checks whether an order qualifies for a discount.
Converting the model into a convenient format for display.
Example: OrderViewModel shows only the fields of the order that are needed.
Unit tests that check the model's behaviour in various scenarios.
Example: a test that the applyDiscount() method never produces a negative price.
class OrdertService {
public function calculate(Order $order): float {
if ($order->getTotal() > 1000) {
return $order->getTotal() * 0.1;
}
return 0;
}
public function save(Order $order): float {
... }}
const order = new Order(123, [new Item("Book", 20, 2)]);
const json = JSON.stringify(order); // can be sent via API
Modelling in programming is the process of creating an abstract representation of a real system or process in order to understand, analyse, predict or reproduce that system's behaviour.
Or, more simply: we create a model in order to test an idea, study behaviour, or design a system before it is actually built.
Understanding the system
Figuring out how something works.
Prediction
Finding out how the system will behave under certain conditions.
Optimisation
Finding the best way to build a system or solve a problem.
Testing ideas without risk
Check a hypothesis without building the real object.
| Area | Example |
|---|---|
| Business logic | Models of company processes (BPMN, UML) |
| GameDev | Physics models, character AI behaviour |
| Machine learning | Predictive models: neural networks |
| System architecture | Service interaction models, ER diagrams |
| Scientific simulations | Climate models, models of biological systems |
UML diagrams (class, state, sequence)
SysML for complex systems
ER diagrams for databases
Simulators (MATLAB, Simulink, Unity physics, PySim)
Algorithmic models (functions, data structures)
Computer modelling algorithms
| Term | Description |
|---|---|
| Model | A specific data structure/class that represents an entity (for example, User in a program) |
| Modelling | The process of building a model of a system, its logic and behaviour |
A model is the result.
Modelling is the process of creating a model.
class Car: def __init__(self, speed, fuel): self.speed = speed self.fuel = fuel def drive(self, distance): self.fuel -= distance * 0.1
Here, Car is the model of the car.
If, on the other hand, we are designing how the car will move, what physics to use, how to consume fuel, that is already modelling.
Modelling is the process of designing and analysing a system
A model is the result: an abstraction that can be used in code
Used in planning, analysis, simulations, and architecture design
1. if, logically, transactions need to be used when saving to the database, where should they be used: in the model, in the repository layer, in the service layer, or somewhere else?
1 Transactions in DDD should be managed at the Application Service level (the service layer), not inside the domain model and not inside individual repositories.
Why the service layer specifically
In DDD there is a clear separation of responsibilities:
| Layer | Responsible for |
|---|---|
| Domain Model | business rules |
| Repository | data access |
| Application Service | orchestration (use-case scenario + transactions) |
A transaction is a technical mechanism for consistency, not a business rule.
That is why it does not belong in the domain model.
The correct execution flow
A typical use case in DDD:
Application Service ├── open a transaction ├── get the aggregate from the repository ├── call a business method on the aggregate ├── save the aggregate via the repository └── commit the transaction
Example (pseudocode)
class OrderApplicationService
{
public function payOrder(OrderId $orderId, Money $amount)
{
$this->transactionManager->begin();
try
{
$order = $this->orderRepository->getById($orderId);
$order->pay($amount); // business logic in the domain
$this->orderRepository->save($order);
$this->transactionManager->commit();
} catch (\Throwable $e) {
$this->transactionManager->rollback();
throw $e;
}
}
}
If the transaction is inside the repository:
saveOrder() savePayment() saveUser()
then you will not be able to guarantee consistency across multiple aggregates.
And in a real use case, this is usually:
we modify multiple aggregates
this means the transaction must cover the entire use case, not just one operation.
Why transactions should not be placed in the domain model
The domain:
should not know about the database
should not know about the ORM
should not know about transactions
Otherwise it is no longer a pure domain model.
What about Domain Events?
A common question.
The correct scheme:
the domain model generates events
they are collected in the aggregate
after the transaction commits, they are published
This is usually done in the Application Service or in the infrastructure layer.
Special case: one aggregate
If a use case works strictly with a single aggregate, then:
one transaction = one aggregate
This is the ideal situation in DDD (Aggregate boundary = transaction boundary).
Summary
Transactions are opened in the Application Service
Repositories do not manage transactions
The domain model knows nothing about transactions
One transaction = one use case
Mental model
One way to remember it:
Application Service = the director of the scenario
it decides:
when to start the transaction
which aggregates to load
which methods to call
when to save
when to commit
Comments