SlideShare ist ein Scribd-Unternehmen logo
1 von 59
Last year:
TechDays 2016
• Event-Driven Applications in F#
• Programming Quantum Computers in F# using
LIQUi|>
• Functional-first programming
language
• Perceived as being only for
math/science/fintech
• Has its own vocabulary and
design patterns
• Take a boring business domain
• Use familiar approaches
• Use F# constructs to solve known problems
• Fit nicely in Azure
• Show the benefits
Our Business
Domain:
Issue Tracker
• Types
• Functions
• Pipelines
Scenario 1:
Create an Issue
// Our first F# type
type IssueCreatedEvent = {
Id: string
Title: string
Description: string
}
type IssueId = Id of string
type IssueCreatedEvent = {
Id: IssueId
Title: string
Description: string
}
type CreateIssueCommand = {
Title: string
Description: string
}
let createIssue (command: CreateIssueCommand) = {
Id = generateId command
Title = command.Title
Description = command.Description
}
// createIssue: CreateIssueCommand -> IssueCreatedEvent
module Domain =
type IssueId = Id of string
type IssueCreatedEvent = {
Id: IssueId
Title: string
Description: string
}
type CreateIssueCommand = {
Title: string
Description: string
}
let createIssue (command: CreateIssueCommand) = {
Id = generateId command
Title = command.Title
Description = command.Description
}
[<DataContract>]
type NewIssueDTO = {
[<DataMember>] title: string
[<DataMember>] description: string
}
[<DataContract>]
type IssueEventLogDTO = {
[<DataMember>] id: string
[<DataMember>] created: NewIssueDTO
}
module SerDe =
let parseNewCommand (command: NewIssueDTO) = {
Title = command.title
Description = command.description
}
let initializeHistory (event: IssueCreatedEvent) =
let (Id idString) = event.Id
{ id = idString
created = { title = event.Title
description = event.Description }
}
module API =
let create (dto: NewIssueDTO) =
let command = SerDe.parseNewCommand dto
let event = Domain.createIssue command
let eventLogDTO = SerDe.initializeHistory event
eventLogDTO
module API =
let create =
SerDe.parseNewCommand
>> Domain.createIssue
>> SerDe.initializeHistory
type public IssuesApp() =
[<FunctionName("CreateIssue")>]
static member CreateIssue (
[<HttpTrigger("post")>]
request : NewIssueDTO,
[<DocumentDB("IssuesDB", "Issues")>]
documents: ICollector<IssueEventLogDTO>) =
let eventLogDTO = API.create request
documents.Add eventLogDTO
eventLogDTO.id
• 5 types
• 3 functions
• 1 pipeline
• 0 explicit I/O operations
Scenario 2:
Change an Issue
type User = User of string
type IssueAssignedToUserEvent = {
User: User
}
type IssueCommentedEvent = {
User: User
Comment: string
}
//type IssueClosedEvent = { }
//type IssueReopenedEvent = { }
type AssignIssueCommand = {
User: User
}
let assignIssue (command: AssignIssueCommand) = {
User = command.User
}
You shouldn’t assign an issue if it’s Done
type IssueStatus =
| New
| Done
type Result<TSuccess, TError> =
| Ok of TSuccess
| Error of TError
// Function type is:
// IssueStatus -> AssignIssueCommand -> Result<IssueAssignedEvent,string>
let assignIssue (status: IssueStatus) (command: AssignIssueCommand) =
match status with
| New -> Ok { User = command.User }
| Done -> Error "Can't assign closed issue"
let closeIssue (status: IssueStatus) command =
match status with
| New -> Ok ()
| Done -> Error "Issue is already closed"
let reopenIssue (status: IssueStatus) command =
match status with
| Done -> Ok ()
| New -> Error "Can't reopen open issue"
type ChangeIssueCommand =
| Assign of AssignIssueCommand
| AddComment of AddCommentCommand
| Close
| Reopen
type IssueChangedEvent =
| Assigned of IssueAssignedToUserEvent
| Commented of IssueCommentedEvent
| Closed
| Reopened
module Domain =
// let createIssue ...
let changeIssue (command: ChangeIssueCommand) status =
match command with
| Assign a -> assignIssue status a
| Comment c -> commentIssue status c
| Close -> closeIssue status
| Reopen -> reopenIssue status
type IssueEvents = {
Created: IssueCreatedEvent
Changes: IssueChangedEvent list
}
let apply status event =
match event with
| Closed -> Done
| Reopened -> New
| _ -> status
let replay (events: IssueEvents): IssueStatus =
List.fold apply New events.Changes
Full Flow of Change
module Domain =
// let createIssue ...
let changeIssue (command: Command) (events: IssueEvents) =
let status = replay events
match command with
| Assign a -> assignIssue status a
| Comment c -> commentIssue status c
| Close -> closeIssue status
| Reopen -> reopenIssue status
Service & Deployment Diagram
module API =
// let create = …
let change (req: IssueCommandDTO) (log: IssueEventLogDTO) =
let command = SerDe.parseCommand req
let eventLog = SerDe.parseHistory log
let result = Domain.change command eventLog
append log result
httpResponse result
let httpResponse result =
match result with
| Ok _ ->
new HttpResponseMessage(HttpStatusCode.OK)
| Error e ->
new HttpResponseMessage(
HttpStatusCode.BadRequest, Content = new StringContent(e))
// httpResponse: Result<T, string> -> HttpResponseMessage
type public IssuesApp() =
[<FunctionName("ChangeIssue")>]
static member ChangeIssue (
[<HttpTrigger("put")>]
request : IssueCommandDTO,
[<DocumentDB("IssuesDB", "Issues", Id = "{id}")>]
state: IssueEventLogDTO) =
API.change request state
• Concise types
• Choice types (discriminated union)
• Immutability by default
• Explicit concepts
• No nulls, no exceptions
• Make invalid state unrepresentable
• Type as documentation
• Types as guard
• Pure Functions
• Determinism
• Totality
• Testability
• Composability
• Functional Architecture
• No circular dependencies
• 10 years of open source
• Community contributions to Compiler, Tooling,
Libraries, Documentation
http://fsharp.org will get you started
Event Driven Applications in F#

Weitere ähnliche Inhalte

Ähnlich wie Event Driven Applications in F#

09 01 tasks
09 01 tasks09 01 tasks
09 01 tasks
tflung
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfolio
mwillmer
 

Ähnlich wie Event Driven Applications in F# (20)

A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015
 
09 01 tasks
09 01 tasks09 01 tasks
09 01 tasks
 
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
 
JEDI Slides-Intro2-Chapter20-GUI Event Handling.pdf
JEDI Slides-Intro2-Chapter20-GUI Event Handling.pdfJEDI Slides-Intro2-Chapter20-GUI Event Handling.pdf
JEDI Slides-Intro2-Chapter20-GUI Event Handling.pdf
 
Asp.net tips
Asp.net tipsAsp.net tips
Asp.net tips
 
Workflow Management with Espresso Workflow
Workflow Management with Espresso WorkflowWorkflow Management with Espresso Workflow
Workflow Management with Espresso Workflow
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
Web-First Design Patterns
Web-First Design PatternsWeb-First Design Patterns
Web-First Design Patterns
 
A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014
 
Scala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional ProgrammingScala UA: Big Step To Functional Programming
Scala UA: Big Step To Functional Programming
 
The Ring programming language version 1.2 book - Part 5 of 84
The Ring programming language version 1.2 book - Part 5 of 84The Ring programming language version 1.2 book - Part 5 of 84
The Ring programming language version 1.2 book - Part 5 of 84
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
 
2310 b 05
2310 b 052310 b 05
2310 b 05
 
Unit3.pptx
Unit3.pptxUnit3.pptx
Unit3.pptx
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfolio
 
Lightbend Lagom: Microservices Just Right (Scala Days 2016 Berlin)
Lightbend Lagom: Microservices Just Right (Scala Days 2016 Berlin)Lightbend Lagom: Microservices Just Right (Scala Days 2016 Berlin)
Lightbend Lagom: Microservices Just Right (Scala Days 2016 Berlin)
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
 
To-Do App With Flutter: Step By Step Guide
To-Do App With Flutter: Step By Step GuideTo-Do App With Flutter: Step By Step Guide
To-Do App With Flutter: Step By Step Guide
 

Mehr von ☁️ Mikhail Shilkov

Mehr von ☁️ Mikhail Shilkov (9)

Monads Explained for OOP Developers
Monads Explained for OOP DevelopersMonads Explained for OOP Developers
Monads Explained for OOP Developers
 
Performance Tales of Serverless - CloudNative London 2018
Performance Tales of Serverless - CloudNative London 2018Performance Tales of Serverless - CloudNative London 2018
Performance Tales of Serverless - CloudNative London 2018
 
Performance Tales of Serverless
Performance Tales of ServerlessPerformance Tales of Serverless
Performance Tales of Serverless
 
Monads Explained for OOP Developers
Monads Explained for OOP DevelopersMonads Explained for OOP Developers
Monads Explained for OOP Developers
 
Azure F#unctions
Azure F#unctionsAzure F#unctions
Azure F#unctions
 
Azure F#unctions
Azure F#unctionsAzure F#unctions
Azure F#unctions
 
Why Learn F# and Functional Programming
Why Learn F# and Functional ProgrammingWhy Learn F# and Functional Programming
Why Learn F# and Functional Programming
 
The taste of F#
The taste of F#The taste of F#
The taste of F#
 
Introduction of Functional Programming
Introduction of Functional ProgrammingIntroduction of Functional Programming
Introduction of Functional Programming
 

Kürzlich hochgeladen

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 

Kürzlich hochgeladen (20)

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 

Event Driven Applications in F#

  • 1.
  • 3.
  • 4. • Event-Driven Applications in F# • Programming Quantum Computers in F# using LIQUi|>
  • 5. • Functional-first programming language • Perceived as being only for math/science/fintech • Has its own vocabulary and design patterns
  • 6. • Take a boring business domain • Use familiar approaches • Use F# constructs to solve known problems • Fit nicely in Azure • Show the benefits
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 15. // Our first F# type type IssueCreatedEvent = { Id: string Title: string Description: string }
  • 16. type IssueId = Id of string type IssueCreatedEvent = { Id: IssueId Title: string Description: string }
  • 17.
  • 18. type CreateIssueCommand = { Title: string Description: string }
  • 19. let createIssue (command: CreateIssueCommand) = { Id = generateId command Title = command.Title Description = command.Description } // createIssue: CreateIssueCommand -> IssueCreatedEvent
  • 20. module Domain = type IssueId = Id of string type IssueCreatedEvent = { Id: IssueId Title: string Description: string } type CreateIssueCommand = { Title: string Description: string } let createIssue (command: CreateIssueCommand) = { Id = generateId command Title = command.Title Description = command.Description }
  • 21.
  • 22.
  • 23.
  • 24. [<DataContract>] type NewIssueDTO = { [<DataMember>] title: string [<DataMember>] description: string } [<DataContract>] type IssueEventLogDTO = { [<DataMember>] id: string [<DataMember>] created: NewIssueDTO }
  • 25. module SerDe = let parseNewCommand (command: NewIssueDTO) = { Title = command.title Description = command.description } let initializeHistory (event: IssueCreatedEvent) = let (Id idString) = event.Id { id = idString created = { title = event.Title description = event.Description } }
  • 26. module API = let create (dto: NewIssueDTO) = let command = SerDe.parseNewCommand dto let event = Domain.createIssue command let eventLogDTO = SerDe.initializeHistory event eventLogDTO
  • 27. module API = let create = SerDe.parseNewCommand >> Domain.createIssue >> SerDe.initializeHistory
  • 28.
  • 29.
  • 30. type public IssuesApp() = [<FunctionName("CreateIssue")>] static member CreateIssue ( [<HttpTrigger("post")>] request : NewIssueDTO, [<DocumentDB("IssuesDB", "Issues")>] documents: ICollector<IssueEventLogDTO>) = let eventLogDTO = API.create request documents.Add eventLogDTO eventLogDTO.id
  • 31. • 5 types • 3 functions • 1 pipeline • 0 explicit I/O operations
  • 33.
  • 34. type User = User of string type IssueAssignedToUserEvent = { User: User } type IssueCommentedEvent = { User: User Comment: string } //type IssueClosedEvent = { } //type IssueReopenedEvent = { }
  • 35. type AssignIssueCommand = { User: User } let assignIssue (command: AssignIssueCommand) = { User = command.User }
  • 36. You shouldn’t assign an issue if it’s Done
  • 37. type IssueStatus = | New | Done
  • 38.
  • 39. type Result<TSuccess, TError> = | Ok of TSuccess | Error of TError
  • 40. // Function type is: // IssueStatus -> AssignIssueCommand -> Result<IssueAssignedEvent,string> let assignIssue (status: IssueStatus) (command: AssignIssueCommand) = match status with | New -> Ok { User = command.User } | Done -> Error "Can't assign closed issue"
  • 41. let closeIssue (status: IssueStatus) command = match status with | New -> Ok () | Done -> Error "Issue is already closed" let reopenIssue (status: IssueStatus) command = match status with | Done -> Ok () | New -> Error "Can't reopen open issue"
  • 42. type ChangeIssueCommand = | Assign of AssignIssueCommand | AddComment of AddCommentCommand | Close | Reopen type IssueChangedEvent = | Assigned of IssueAssignedToUserEvent | Commented of IssueCommentedEvent | Closed | Reopened
  • 43. module Domain = // let createIssue ... let changeIssue (command: ChangeIssueCommand) status = match command with | Assign a -> assignIssue status a | Comment c -> commentIssue status c | Close -> closeIssue status | Reopen -> reopenIssue status
  • 44.
  • 45. type IssueEvents = { Created: IssueCreatedEvent Changes: IssueChangedEvent list }
  • 46. let apply status event = match event with | Closed -> Done | Reopened -> New | _ -> status let replay (events: IssueEvents): IssueStatus = List.fold apply New events.Changes
  • 47. Full Flow of Change
  • 48. module Domain = // let createIssue ... let changeIssue (command: Command) (events: IssueEvents) = let status = replay events match command with | Assign a -> assignIssue status a | Comment c -> commentIssue status c | Close -> closeIssue status | Reopen -> reopenIssue status
  • 49.
  • 51. module API = // let create = … let change (req: IssueCommandDTO) (log: IssueEventLogDTO) = let command = SerDe.parseCommand req let eventLog = SerDe.parseHistory log let result = Domain.change command eventLog append log result httpResponse result
  • 52. let httpResponse result = match result with | Ok _ -> new HttpResponseMessage(HttpStatusCode.OK) | Error e -> new HttpResponseMessage( HttpStatusCode.BadRequest, Content = new StringContent(e)) // httpResponse: Result<T, string> -> HttpResponseMessage
  • 53. type public IssuesApp() = [<FunctionName("ChangeIssue")>] static member ChangeIssue ( [<HttpTrigger("put")>] request : IssueCommandDTO, [<DocumentDB("IssuesDB", "Issues", Id = "{id}")>] state: IssueEventLogDTO) = API.change request state
  • 54.
  • 55. • Concise types • Choice types (discriminated union) • Immutability by default • Explicit concepts • No nulls, no exceptions • Make invalid state unrepresentable • Type as documentation • Types as guard
  • 56. • Pure Functions • Determinism • Totality • Testability • Composability
  • 57. • Functional Architecture • No circular dependencies
  • 58. • 10 years of open source • Community contributions to Compiler, Tooling, Libraries, Documentation http://fsharp.org will get you started

Hinweis der Redaktion

  1. Build a bridge from usual to unusual, Broaden toolbox
  2. I said I want it to be boring! Developers are domain experts.