visit
The essence of an entity of reality is that which makes it be itself and not another.//app.gzht888.com/stats/there-are-no-silver-bullets-for-this-werewolf-2t213woi
Photo by on
Being true to our bijection, in our computable model we should be able to distinguish when an object changes in terms of the accidental and prohibit all essential changes (because they would violate that bijection which is our only principle).Objects should know how to defend themselves against invalid representations. They are the powers against mutants.
Photo by on
However, those of us who have worked in economic, financial or banking domains have built systems that violate these rules in a systematic way with some excuse related to laziness or performance (our favorites).
As a personal anecdote, in one of my first jobs for a large international bank, we modeled financial transactions with an isDataOK attribute that we had as a Boolean flag until we made sure that the transaction was indeed a valid and actionable transaction. This brought us multiple coupling problems on multiple occasions.
Besides, many of those fields remained with null values (instead of modeling the incompleteness or indefiniteness of the data), so we had to spread the code with multiple controls by ifs to validate that some of the data against nulls.
class Movement {
public $party;
public $counterparty;
public $amount;
public $date;
public $isDataOK = false;
}
A hollow class with a lot of attributes and no encapsulation but with a flag (isDataOK) should when it could be safely used.
Let’s start by hiding the decision to know when it is an actionable movement.class Movement {
function isDataOK(): bool {
return !is_null($this->party) && !is_null($this->counterparty) && !is_null($this->amount) && !is_null($this->isDataOK);
}
}
private $party;
function getParty(){
return $this->party();
}
function setParty($aParty){
$this->party = $aParty;
}
.....
final class Movement {
private $party;
private $counterparty;
private $amount
private $date;
}
function __construct($aParty, $aCounterParty, $anAmount, $aDate){
$this->party = $aParty;
$this->counterparty = $aCounterParty;
$this->amount = $anAmount;
$this->date = aDate;
}
}
Simple, elegant, immutable, without dataOk, always valid, without setters or getters.
function __construct($aParty, $aCounterParty, $anAmount, $aDate){
if ($aParty == $aCounterParty) {
throw new PartyAndCounterpartyCannotBeTheSameException($aParty, $aCounterParty);
}
$this->party = $aParty;
$this->counterparty = $aCounterParty;
$this->amount = $anAmount;
$this->date = aDate;
}
$halvingTransaction = new Movement($wallet, $destination, $bitcoins, Date(12,5,2020));
But this violates our unique design principle of maintaining a bijection with the real world. Let’s be loyal to our single rule.
$day12 = new Day(12);
$year2020 = new Year(2020);
$may2020 = new YearMonth(5, $year2020);
$halvingDay = new Date($day12, $may2020);
$halvingTransaction = new Movement($wallet, $destination, $bitcoins, $halvingDay);
We model reality’s entities such as a day of a month, a calendar year, and a date, forgetting about arbitrary implementations with integers because bijection and declarativity are more important than performance and laziness.
Let us dwell for a minute on the mutability of a date. One hopes that a date will never mutate because it does not do so in the real world. No non-computer person would ever think of changing a date.Now let us analyze by the method of reduction to the absurd what would happen if we allow a date to change.Our accredited transaction on the day of halving knows its imputation date. If it changes internally all consecutive blockchains should be recalculated and this is expressly prohibited by the financial domain. It is clear that the date should never mutate.
Let’s review the Date class in the most widely used languages in today’s industry.
Date problem’s domain is probably one of the oldest and best known to humanity. The excuse that these getters are being deprecated speaks about poor initial design in most modern languages.
A possible attack is to reverse the burden of proof. Objects are completely immutable unless otherwise stated.
Should they evolve they must always do so in their accidental aspects. Never in their essence. This change should not be coupled to all the other objects that use it.
If an object is complete since its creation, it will always be able to answer to messages.
An object must correctly represent the entity since its inception. If we work in a concurrent environment it is essential that the objects are always valid.
An object must be immutable if the entity it represents is immutable. Most entities are immutable.
These rules keep the model consistently consistent with representation.
As a corollary of the demonstration by the absurd we can derive a series of rules:
Objects must be complete since their creation.
Setters must not exist.
Nude Models - Part I : Setters
Getters should not exist (unless they exist in the real world and then the bijection is valid). It is not the responsibility of any reality entity to reply to a getXXX() message.