Functional architecture The pit of success Mark Seemann
- Slides: 69
Functional architecture The pit of success Mark Seemann http: //blog. ploeh. dk @ploeh
@ploeh
@ploeh
@ploeh
@ploeh
@ploeh
Parallelism Ports and adapters Services, Entities, Value Objects Testability @ploeh
PARALLISM
public void Update() { // when a generation has completed // now flip the back buffer so we can start // processing on the next generation var flip = this. next. Generation; this. next. Generation = this. world; this. world = flip; Generation++; this. Process. Generation(); } @ploeh
public void Update() { lock(this. sync. Lock) // when a generation has completed // now flip the back buffer so we can start // processing on the next generation var flip = this. next. Generation; this. next. Generation = this. world; this. world = flip; Generation++; this. Process. Generation(); } @ploeh
public void Update() { lock(this. sync. Lock) // when a generation has completed // now flip the back buffer so we can start // processing on the next generation var flip = this. next. Generation; this. next. Generation = this. world; this. world = flip; Generation++; this. Process. Generation(); } @ploeh
public void Update() { lock(this. sync. Lock) { // when a generation has completed // now flip the back buffer so we can start // processing on the next generation var flip = this. next. Generation; this. next. Generation = this. world; this. world = flip; Generation++; this. Process. Generation(); } @ploeh
public void Update() { lock(this. sync. Lock) { // when a generation has completed // now flip the back buffer so we can start // processing on the next generation var flip = this. next. Generation; this. next. Generation = this. world; this. world = flip; Generation++; this. Process. Generation(); } @ploeh
public void Update() { lock(this. sync. Lock) { // when a generation has completed // now flip the back buffer so we can start // processing on the next generation var flip = this. next. Generation; this. next. Generation = this. world; this. world = flip; Generation++; this. Process. Generation(); } @ploeh
public void Update() { lock(this. sync. Lock) { // when a generation has completed // now flip the back buffer so we can start // processing on the next generation var flip = this. next. Generation; this. next. Generation = this. world; this. world = flip; Generation++; this. Process. Generation(); } } @ploeh
let tick live. Cells = let is. Alive = function Alive -> true | _ -> false live. Cells |> Seq. collect find. Neighbors |> Seq. distinct |> Seq. filter (calculate. Next. State live. Cells >> is. Alive) |> Seq. to. Array |> Set. of. Array @ploeh
let tick live. Cells = let is. Alive = function Alive -> true | _ -> false live. Cells |> PSeq. collect find. Neighbors |> PSeq. distinct |> PSeq. filter (calculate. Next. State live. Cells >> is. Alive) |> PSeq. to. Array |> Set. of. Array @ploeh
PORTS AND ADAPTERS
@ploeh
Same return value for same input Pure function No sideeffects @ploeh
Impure function Pure function @ploeh
validate. Reservation : : Reservation. Rendition -> Either Error Reservation validate. Reservation r = case parse. Date (r. Date r) of Just d -> Right Reservation { date = d , name = r. Name r , email = r. Email r , quantity = r. Quantity r } Nothing -> Left (Validation. Error "Invalid date. ") @ploeh
get. Reserved. Seats. From. DB : : Connection. String -> Zoned. Time -> IO Int @ploeh
check. Capacity : : Int -> Reservation -> Either Error Reservation check. Capacity capacity reserved. Seats reservation = if capacity < quantity reservation + reserved. Seats then Left Capacity. Exceeded else Right reservation @ploeh
save. Reservation : : Connection. String -> Reservation -> IO () @ploeh
to. Http. Result : : Either Error () -> Http. Result () to. Http. Result (Left (Validation. Error msg)) = Bad. Request msg to. Http. Result (Left Capacity. Exceeded) = Status. Code Forbidden to. Http. Result (Right ()) = OK () @ploeh
post. Reservation : : Reservation. Rendition -> IO (Http. Result ()) post. Reservation candidate = fmap to. Http. Result $ run. Either. T $ do r <- hoist. Either $ validate. Reservation candidate i <- lift. IO $ get. Reserved. Seats. From. DB conn. Str $ date r hoist. Either $ check. Capacity 10 i r >>= lift. IO. save. Reservation conn. Str @ploeh
check. Capacity @ploeh
let imp candidate = either { let! r = Validate. reservation candidate let i = Sql. Gateway. get. Reserved. Seats connection. String r. Date let! r = Capacity. check 10 i r return Sql. Gateway. save. Reservation connection. String r } new Reservations. Controller(imp) : > _
SERVICES AND DATA
public class User { public int Id { get; } public string User. Name { get; } public static User Create. New(string user. Name) public static User Read(int id) public void Update() public void Delete() } @ploeh
public class User { public int Id { get; } public string User. Name { get; } public static User Create. New(string user. Name) public static User Read(int id) public void Update() public void Delete() } @ploeh
public class User { public int Id { get; } public string User. Name { get; } public static User Create. New(string user. Name) public static User Read(int id) public void Update() public void Delete() public void Send. Email(Email message) } @ploeh
@ploeh
Entities Services Value Objects @ploeh
public class User { public User(int id, string user. Name) public int Id { get } public string User. Name { get } } @ploeh
public class Sql. User. Repository : IUser. Repository { public User Create. New(string user. Name) public User Read(int id) public void Update(User user) public void Delete(User user) } @ploeh
public class Email. Sender : ISend. Email { public void Send. Email. To(User user, Email message) } @ploeh
Anaemic Model @ploeh
Anaemic Model @ploeh
Anaemic D Model @ploeh
Anaemic Do Model @ploeh
Anaemic Dom Model @ploeh
Anaemic Doma Model @ploeh
Anaemic Domai Model @ploeh
Anaemic Domain Model @ploeh
Entities Services Value Objects @ploeh
Data Functions @ploeh
type User = { Id : int; User. Name : string } @ploeh
module Persistence = // string -> User let create. New user. Name = //. . // int -> User let read id = //. . // User -> unit let update user = //. . // User -> unit let delete user = //. . @ploeh
module Mail = // User -> Email -> unit let send. Email. To user message = //. . @ploeh
public sealed class Money { public Money(decimal amount, string currency) public decimal Amount { get } public string Currency { get } public override bool Equals(object obj) public override int Get. Hash. Code() } @ploeh
type Money = { Amount : decimal; Currency : string } > { Amount = 1 m; Currency = "EUR" } = { Amount = 1 m; Currency = "EUR" }; ; val it : bool = true > { Amount = 2 m; Currency = "EUR" } = { Amount = 1 m; Currency = "EUR" }; ; val it : bool = false > { Amount = 1 m; Currency = "EUR" } = { Amount = 1 m; Currency = "GBP" }; ; val it : bool = false @ploeh
TESTABILITY
Test-induced damage https: //www. flickr. com/photos/davehamster/8667991007 @ploeh
public class Capacity. Checker : ICapacity. Checker { private readonly int capacity; private readonly IReservation. Repository repo; public Capacity. Checker(int capacity, IReservation. Repository repo) { this. capacity = capacity; this. repo = repo; } public bool Has. Capacity(Reservation reservation) { var reserved = this. repo. Get. Reserved. Seats(reservation. Date); return this. capacity < reservation. Quantity + reserved; } } @ploeh
let check capacity get. Reserved. Seats reservation = let reserved. Seats = get. Reserved. Seats reservation. Date if capacity < reservation. Quantity + reserved. Seats then Failure Capacity. Exceeded else Success reservation @ploeh
[<Fact>] let ``check returns right result at no prior reservations`` () = let capacity = 10 let get. Reserved. Seats _ = 0 let reservation = { Date = Date. Time. Offset(Date. Time(2014, 8, 10), Time. Span. From. Hours 2. ) Name = "Mark Seemann" Email = "mark@ploeh. dk" Quantity = 4 } let actual = Capacity. check capacity get. Reserved. Seats reservation let expected : Result<Reservation, Error> = Success reservation test <@ expected = actual @> @ploeh
Jessica Kerr Isolation When the only information a function has about the external world is passed into it via arguments. https: //twitter. com/jessitron @ploeh
Isolation Pure function @ploeh
Unit Test A unit test is an automated test that tests a unit in isolation from its dependencies. @ploeh
Unit Test A unit test is an automated test that tests a unit in isolation from its dependencies. @ploeh
Isolation Testinduced damage OOP @ploeh
Encapsulation Testability Object-Oriented Programming Isolation @ploeh
Functional Programming Testable Isolated Ideal function @ploeh
@ploeh
@ploeh
Parallelism Ports and adapters Services, Entities, Value Objects Testability @ploeh
Mark Seemann http: //blog. ploeh. dk http: //bit. ly/ploehralsight @ploeh
- Welcher seemann liegt bei nanni im bett
- The pit of success
- Your child's success or lack of success
- Your child's success or lack of success
- Cantilever type space maintainer
- Non functional plasma enzyme
- Plasma enzymes
- Functional and non functional
- Isdn termination multidrop
- Tmn telecommunications management network
- Tmn functional architecture
- Tmn
- Hát kết hợp bộ gõ cơ thể
- Bổ thể
- Tỉ lệ cơ thể trẻ em
- Chó sói
- Chụp phim tư thế worms-breton
- Bài hát chúa yêu trần thế alleluia
- Các môn thể thao bắt đầu bằng tiếng nhảy
- Thế nào là hệ số cao nhất
- Các châu lục và đại dương trên thế giới
- Công thức tiính động năng
- Trời xanh đây là của chúng ta thể thơ
- Cách giải mật thư tọa độ
- Phép trừ bù
- Phản ứng thế ankan
- Các châu lục và đại dương trên thế giới
- Thơ thất ngôn tứ tuyệt đường luật
- Quá trình desamine hóa có thể tạo ra
- Một số thể thơ truyền thống
- Bàn tay mà dây bẩn
- Vẽ hình chiếu vuông góc của vật thể sau
- Nguyên nhân của sự mỏi cơ sinh 8
- đặc điểm cơ thể của người tối cổ
- Thế nào là giọng cùng tên
- Vẽ hình chiếu đứng bằng cạnh của vật thể
- Vẽ hình chiếu vuông góc của vật thể sau
- Thẻ vin
- đại từ thay thế
- điện thế nghỉ
- Tư thế ngồi viết
- Diễn thế sinh thái là
- Dot
- Số nguyên tố là
- Tư thế ngồi viết
- Lời thề hippocrates
- Thiếu nhi thế giới liên hoan
- ưu thế lai là gì
- Sự nuôi và dạy con của hổ
- Khi nào hổ con có thể sống độc lập
- Sơ đồ cơ thể người
- Từ ngữ thể hiện lòng nhân hậu
- Thế nào là mạng điện lắp đặt kiểu nổi
- Twj e-pit
- Flush terminal plane
- Burmese tiger pit
- Rdso guidelines for earthwork
- Fissure dental definition
- Ensaio de integridade pit
- Ows pit
- Strip mining vs open pit mining
- The pit and the pendulum plot diagram
- Inner stage elizabethan theatre
- Globe theatre flags
- Disadvantages of pit latrines
- Pit and the pendulum setting
- Difference between profile levelling and cross sectioning
- Strip mining vs open pit mining
- Peripheral controller chip