module Observable
from Microsoft.FSharp.Control
val filter : predicate:('T -> bool) -> source:System.IObservable<'T> -> System.IObservable<'T>
Full name: Microsoft.FSharp.Control.Observable.filter
val map : mapping:('T -> 'U) -> source:System.IObservable<'T> -> System.IObservable<'U>
Full name: Microsoft.FSharp.Control.Observable.map
val x : int
val merge : source1:System.IObservable<'T> -> source2:System.IObservable<'T> -> System.IObservable<'T>
Full name: Microsoft.FSharp.Control.Observable.merge
val subscribe : callback:('T -> unit) -> source:System.IObservable<'T> -> System.IDisposable
Full name: Microsoft.FSharp.Control.Observable.subscribe
Acronym Soup
3 slightly different things
- CQRS: Command Query Responsibilty Seperation
- ES: Event Sources
- FRP: Functional Reactive Programming
CQRS
- Seperate Reads (Queries) from Writes (Commands)
- Reads vs Writes to system rarely the same rate, decouple them
- Also called SQS - Command-query seperation
- Queries: return state and are pure
- Command: change state and returns unit
Advantages
- Optimise reads via queries, database projections, search engines, etc.
- Security e.g. read only connection string for queries
- Use Domain Model only for writes, SQL joins for reads, seperate types
Disadvantages
- Complexity over simple SQL data access
- What about things like
Stack.pop()
?
ES
- Immutable append only store
- Define changes in business terms (e.g. ChangeOfAddress) not SQL
- Snapshops for performance
- Java LMAX disrupter
Advantages
- All code is stateless, easy to test.
-
Advantages of append only stores:
- Replication
- Audit
- History
- Replay
Disadvantages
- Can be more complex to implement than a CRUD approach
- Too much logic in command handler
- Versioning of events
- Data sizes (define, jet)
FRP
- Like ES, but with more than one command processor
- Also called stream processing
- Command handler does minimal work, downstream processors
- Combine, project, fold streams
- EventStore javascript projections
- Eventually consistent reads (e.g. via database)
- Rx, RxJava, RxJS
- Enumerable dual, sync pull vs async push
1:
2:
3:
4:
5:
|
eventSouce
|> Observable.filter ((>) 2)
|> Observable.map (fun x -> x*2)
|> Observable.merge otherEvents
|> Observable.subscribe
|
Advantages
- Decouples stateful logic from other non-intrinsic logic.
- Add and remove domain logic without affecting the core command handler
- Multiple stores
- Lambda architectures
Disadvantages
- Enterprise-wide versioning issues
- Even more complicated