mercury: a functional review
TRANSCRIPT
Mercury:A Functional Review
Retrospective on a first commercial F# project
Mark Cheeseman
http://hombredequeso.id.au/
Why Use F# ?
• Less Code
• Easier to reason about the code
• Easier to multi-thread.
• You get to say “monad”
Why Did We Use F# : Immutability
By default, F# Record Types are immutable
type Point = {X: intY: int
}
class Point{
Point(int x, int y){
X = x;Y = y;
}public int X { get; private set; }public int Y { get; private set; }
}
Why Did We Use F#: Value Equality
F# records have structural (value) equality.
Classes have reference equality by default, but can implement value equality.type Point = {
X: intY: int
}
public class Point : IEquatable<Point>{
public Point(int x, int y){
X = x;Y = y;
}
public int X { get; private set; }public int Y { get; private set; }
public bool Equals(Point other){…
public class Point : IEquatable<Point>{
public Point(int x, int y){
X = x;Y = y;
}
public int X { get; private set; }public int Y { get; private set; }
public bool Equals(Point other){
if (ReferenceEquals(null, other)) return false;if (ReferenceEquals(this, other)) return true;return X == other.X && Y == other.Y;
}
public override bool Equals(object obj){
if (ReferenceEquals(null, obj)) return false;if (ReferenceEquals(this, obj)) return true;if (obj.GetType() != this.GetType()) return false;return Equals((Point) obj);
}
public override int GetHashCode(){
unchecked{
return (X*397) ^ Y;}
}
public static bool operator ==(Point left, Point right){
return Equals(left, right);}
public static bool operator !=(Point left, Point right){
return !Equals(left, right);}
}
Why Did We Use F#:Functional is the New SOLID
(or the end/goal of SI at least)
public interface IWidgetFactory
{
Widget Create(T1 t1, T2 t2);
}
http://blog.ploeh.dk/2014/03/10/solid-the-next-step-is-functional/
Base
Type1 Type2
Base
Type1 Type2
BaseA
Type1 Type2
BaseB
Inheritance Composition
Refactored Composition
Why Did We Use F#:Emergence of Functional Style with
Composition over Inheritance
Major Challenges
• Libraries/Frameworks to use
• Getting the most out of F# (idiomatic F#)
• How to put together a project
Local Server
Po
lling
(WC
F)
Shipment Polling
Endpoint
(C#)
External Shipping
System
Azure Web
Website
WebJob
Shipment
Processing
Endpoint
Bus
Shipment Polling DB
Shipment DB
(SQL Azure)
Mercury System Overview
Putting the Pieces Together
Requirement Technological Solution
Distributed Communication between company server and Azure
NServiceBus
Db Access (SQL Azure) F# (Sql) Dbml Type Provider
Website (Azure) Nancy
Unit Testing FsUnit, FsCheck
Browser Aurelia
Website Security BrockAllen.MembershipReboot, IdentityServer3
class Shipment{
public void Depart(T1 d){
// mutate _state}
public void Arrive(T2 a){
// mutate _state}
private State _state}
type Shipment {// state of shipment: record type
}
type Operation =Depart of T1Arrive of T2
let depart (d: T1) (s: Shipment) : Shipment =// departs shipment s, and returns a new// instance of Shipment in departed state
let arrive (a: T2) (s: Shipment) : Shipment =// arrives shipment s, and returns a new// instance of Shipmente in arrived state
let apply (operation: Operation) (shipment: Shipment): Shipment =
match operation with| Depart(d) -> depart d shipment| Arrive(a) -> arrive a shipment
Domain Code: C# and F#
Domain
Shipment DB (SQL Azure)
DAL
Composition Root
Bus (NSB)
NServiceBus Handlers
Nsb to Domain Transforms
Domain
Shipment DB (SQL Azure)
DAL
Composition Root
type Shipment
type Operation
apply:
Shipment -> Operation -> Shipment
… other entities
Bus (NSB)
NServiceBus Handlers
(ICmd -> unit)
Nsb to Domain Transforms
ICmd -> ShipmentEntity.Operation
Sql Type Provider
type dbContext.Shipment
type Dal.Shipment
dbContext.Shipment -> Dal.Shipment ->
Domain.Shipment
C# syntaxint GetHashCode(string s){
...}
F# syntaxlet GetHashCode (s: string) : int =
...or justlet GetHashCode s =
...
F# function signatureGetHashCode: string -> int
Domain
Shipment DB (SQL Azure)
DAL
Composition Root
type Shipment
type Operation
apply:
Shipment -> Operation -> Shipment
(ShipmentEntity.fs)
… other entities
Bus (NSB)
NServiceBus Handlers
(ICmd -> unit)
NsbHandlers.fs
Nsb to Domain Transforms
ICmd -> ShipmentEntity.Operation
(NsbToDomainTransform.fs)
Sql Type Provider
type dbContext.Shipment
type Dal.Shipment
dbContext.Shipment -> Dal.Shipment ->
Domain.Shipment
ShipmentViewModelDal.fs
Pattern Hints
• Making illegal states unrepresentable with single case unions.
http://fsharpforfunandprofit.com/posts/designing-with-types-making-illegal-states-unrepresentable/
• Do not throw exceptions.
http://fsharpforfunandprofit.com/rop/
Resources
http://fsharpforfunandprofit.com
One of the best, practically oriented F# resources.
http://blog.ploeh.dk/
Mark Seeman’s blog. Regularly blogs on F#.
https://www.youtube.com/watch?v=MHvr71T_LZw
Domain-Driven Design, Event Sourcing and CQRS with F# and EventStore
Syme et. al., Expert F# 4.0
Petricek, Real-World Functional Programming With Examples in F# and C#