engineering-hub

Knowledge index of IT engineering

View project on GitHub

Source

Functional architecture - The pits of success - Mark Seemann

Ports and Adaptors (a.k.a hexagonal architecture, a.k.a onion architecture)

onion-architecture

The greenish boxes in the center represent the domain model and domain/business logic. Other layers represent real world systems that the business logic interracts with (ex databases, sending emails and etc) but you dont want your business logic to be too dependant on those technical concerns because they might change.

Pure functions

Benefits

  • easy to reason about
  • easy to manipulate
  • easy to compose
  • easy to test

Characteristics

  • Deterministic - same return value for same input
  • no side effects

Notes

  • Pure function can call another pure function
  • You can call impure function from another impure function - doesnt change that it is impure
  • You can call pure function from impure function
  • You SHOULDNT call impure function from pure function - it changes it to impure

Reservation application logic example

reservation-booking

Note: Pure functions are in green. Impure are in red

Pure function handling reservation validation in Haskel

reservation-booking-haskel-implementation

Note: in Haskel all functions are pure by default

Get Reserved seats from DB

Function signiture

reservation-booking-haskel-reserved-seats-implementation

Note: has side effect (IO Int)

Check capacity

reservation-booking-haskel-check-capacity-implementation

Void save reservation

reservation-booking-haskel-save-reservation-implementation

Note: has side effect (IO void)

Diagram of code

reservation-booking-haskel-reservation-diagram

Services and data

When people initially learn OOP they are often taught that objects are data with behaviour.

Active record pattern example

active-record-pattern

Note: probably can be considered an antipattern - Ex: Sending emails to users, storing them and etc shouldnt be part of the User class; It bloats the User class and creates a “God class” which is an known antipattern

Domain driven design

About the book by Eric Evans

You can treat your objects in 2 categories:

  • Entities - objects that have long lasting identity (Ex: users)
  • Value Objects

The business logic should be put into Services (obects that manage entities and value objects)

Refactored user

plain-user

plain-repository

send-email-service

Note: there is an argument about having “anemic domain models” after your User object have been made simpler

Functional programming architecture

It splits into “data” and “functions”. Ex:

fp-user

user-module-is-fp-service

Note: the module in F# plays the role of a service in typical OOP. The above code in the module is impure

Function isolation

When the only information a function has about the external world is passed into it via arguments. In short the function doesnt have any implicit knowledge about the external world.

A pure function is isolated.

Unit testing

A unit test is an automated test that tests a unit in isolation from its dependencies