1. Domain Primitives in Action
- Making it Secure by Design
@DanielDeogun @danbjson
DataTjej
February 15, 2018
2. @DanielDeogun @danbjson #SecureByDesign
About Us…
Dan Bergh Johnsson
Secure Domain Philosopher
Omegapoint, Sweden
Umeå
Malmö
Göteborg
Falun
New York
Stockholm
Daniel Deogun
Coder and Quality Defender
3. @DanielDeogun @danbjson #SecureByDesign
Key Take Aways
Domain Primitives
- are native to your domain
- form a conceptual whole
- easy way to improve and secure existing code
9. @DanielDeogun @danbjson #SecureByDesign
But Quantity is “just”
an integer…
Quantity
• a concept that’s well defined
with strict boundaries
• not closed under addition
• cannot be negative
Peano's Axioms
1. Zero is a number
2. If n is a number, the successor of n is a number
3. Zero isn’t the successor of a number
4. Two numbers of which the successors are equal are
themselves equal
5. If a set S of numbers contains zero and also the successor
of every number in S, then every number is in S
Abelian Group
• Closure: a + b = integer
• Associativity: a + (b + c) = (a + b) + c
• Commutativity: a + b = b + a
• Identity: a + 0 = a
• Inverse: a + (−a) = 0
🤔
12. @DanielDeogun @danbjson #SecureByDesign
But Room Number
is “just” an Integer…
🤔Peano's Axioms
1. Zero is a number
2. If n is a number, the successor of n is a number
3. Zero isn’t the successor of a number
4. Two numbers of which the successors are equal are
themselves equal
5. If a set S of numbers contains zero and also the successor
of every number in S, then every number is in S
Abelian Group
• Closure: a + b = integer
• Associativity: a + (b + c) = (a + b) + c
• Commutativity: a + b = b + a
• Identity: a + 0 = a
• Inverse: a + (−a) = 0
14. @DanielDeogun @danbjson #SecureByDesign
Domain Primitives
“A value object so precise in its definition that it, by its mere
existence, manifests its validity is called a Domain Primitive.”
- Secure by Design
• Can only exist if its value is valid
• Building block that’s native to your domain
• Valid in the current context
• Immutable and resemble a value object in DDD
15. @DanielDeogun @danbjson #SecureByDesign
Math and Hotel are
different Contexts
Math Domain
Integer
Hotel Domain
Room Number
Hotel Domain
Math Domain
Integer
(a.k.a Room Number)
Domain Primitive
16. @DanielDeogun @danbjson #SecureByDesign
Math and Webshop are
different Contexts
Math Domain
Integer
Webshop Domain
Quantity
Webshop
Math Domain
Integer
(a.k.a Quantity)
Domain Primitive
17. @DanielDeogun @danbjson #SecureByDesign
Quantity as a Domain
Primitive
public final class Quantity {
private final int value;
public Quantity(final int value) {
inclusiveBetween(1, 99, value);
this.value = value;
}
//Domain specific quantity operations...
}
18. @DanielDeogun @danbjson #SecureByDesign
Room Number as a
Domain Primitive
public final class RoomNumber {
private final int value;
public RoomNumber(final int value) {
isTrue(Floor.isValid(value));
inclusiveBetween(1, 50, value % 100);
this.value = value;
}
public Floor floor() {
return new Floor(value);
}
// other logic …
}
19. @DanielDeogun @danbjson #SecureByDesign
Invalid quantities are
rejected by Definition!
-1 : Integer
Quantity: {1 - 99}
OrderLine {ISBN, Quantity}
Math Context
Webshop Context
Only valid quantities are
accepted
Rejected
20. @DanielDeogun @danbjson #SecureByDesign
Less Simple
Domain Primitive
public void pay(final double money, final int recipientId) {
final String currency = CurrencyService.currencyFor(recipientId);
BankService.transfer(money, currency, recipientId);
}
public void pay(final Money money, final Recipient recipient) {
notNull(money);
notNull(recipient);
BankService.transfer(money, recipient);
}
But Money is a conceptual whole and
should be modeled as a domain primitive
21. @DanielDeogun @danbjson #SecureByDesign
Intelligent Machines -
not just values
class Rate {
private final Currency from;
private final Currency to;
Rate(Currency from, Currency to) {
this.from = notNull(from);
this.to = notNull(to);
}
Money exchange(Money from) {
notNull(from);
isTrue(this.from
.equals(from.currency));
BigDecimal converted = . . .
return new Money(converted, to);
}
}
22. @DanielDeogun @danbjson #SecureByDesign
Standing on the
Shoulders of Giants
• Domain Primitives act as building blocks
• Guy L. Steele Jr. “Growing a Language”
• Abelson, Sussman “Structure and
Interpretation of Computer Programs”
https://flic.kr/p/8cc44h https://creativecommons.org/licenses/by/2.0/
23. @DanielDeogun @danbjson #SecureByDesign
Domain Primitives in
Action on Legacy
https://flic.kr/p/Q7zV https://creativecommons.org/licenses/by-sa/2.0/
vs
https://flic.kr/p/djYc9H https://creativecommons.org/licenses/by/2.0/
Green Field Brown Field
24. @DanielDeogun @danbjson #SecureByDesign
Three Steps
https://flic.kr/p/wdBcT
https://creativecommons.org/licenses/by/2.0/
Untangle insideDraw the line
Harden your API
https://flic.kr/p/YgfS6s
https://creativecommons.org/licenses/by/2.0/
https://flic.kr/p/nEZKMd
https://creativecommons.org/licenses/by/2.0/
25. @DanielDeogun @danbjson #SecureByDesign
“Draw the Line”
- Find a Semantic Border
• We need to identify the semantic boundary of a context
• Add a layer that internally translates data to a domain
primitive and the back again
data -> domain primitive -> data
• This way, we have created a validation boundary that
protects the inside from bad input
• But, if rejecting data is to harsh, consider logging it for
insight
https://flic.kr/p/nEZKMd https://creativecommons.org/licenses/by/2.0/
public void checkout(final int roomNumber) {
new RoomNumber(roomNumber); //throws exception if invalid
houseKeepingService.registerForCleaning(roomNumber);
minibarService.replenish(roomNumber);
// other operations ...
}
public void checkout(final int roomNumber) {
if (!RoomNumber.isValid(roomNumber)) {
reporter.logInvalidRoomNumber(roomNumber);
}
houseKeepingService.registerForCleaning(roomNumber);
minibarService.replenish(roomNumber);
// other operations ...
}
26. @DanielDeogun @danbjson #SecureByDesign
Harden your API
- Enforce Data Quality
Generic
Specific
public void checkout(final int roomNumber)
public void checkout(final RoomNumber roomNumber)
Enforce data quality https://flic.kr/p/YgfS6s
https://creativecommons.org/licenses/by/2.0/
27. @DanielDeogun @danbjson #SecureByDesign
Untangle Inside
- Cluttered Entity
https://flic.kr/p/wdBcT
https://creativecommons.org/licenses/by/2.0/
class Order {
private ArrayList<Object> items;
private boolean paid;
public void addItem(String isbn, int qty) {
if(this.paid == false) {
notNull(isbn);
inclusiveBetween(10, 10, isbn.length());
isTrue(isbn.matches("[0-9X]*"));
isTrue(isbn.matches("[0-9]{9}[0-9X]"));
Book book = bookCatalogue.findByISBN(isbn);
if (inventory.availableBooks(isbn) >= qty) {
items.add(new OrderLine(book, qty));
}
}
}
//Other logic...
}
28. @DanielDeogun @danbjson #SecureByDesign
De-Cluttered Entity
class Order {
private ArrayList<Object> items;
private boolean paid;
public void addItem(ISBN isbn, Quantity qty) {
notNull(isbn);
notNull(qty);
if(this.paid == false) {
Book book = bookCatalogue.findByISBN(isbn);
if (inventory.availableBooks(isbn).greaterOrEqualTo(qty)) {
items.add(new OrderLine(book, qty));
}
}
}
//Other logic...
} https://flic.kr/p/wdBcT
https://creativecommons.org/licenses/by/2.0/
32. @DanielDeogun @danbjson #SecureByDesign
Key Take Aways
Domain Primitives
- are native to your domain
- form a conceptual whole
- easy way to improve and secure existing code