2. Why Use F# ?
• Less Code
• Easier to reason about the code
• Easier to multi-thread.
• You get to say “monad”
3. Why Did We Use F# : Immutability
By default, F# Record Types are immutable
type Point = {
X: int
Y: int
}
class Point
{
Point(int x, int y)
{
X = x;
Y = y;
}
public int X { get; private set; }
public int Y { get; private set; }
}
4. 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: int
Y: 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)
{
…
5. 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);
}
}
6. 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/
7. 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
10. 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
11.
12. 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 T1
Arrive 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#
13. Domain
Shipment DB (SQL Azure)
DAL
Composition Root
Bus (NSB)
NServiceBus Handlers
Nsb to Domain Transforms
14. 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# syntax
int GetHashCode(string s)
{
...
}
F# syntax
let GetHashCode (s: string) : int =
...
or just
let GetHashCode s =
...
F# function signature
GetHashCode: string -> int
15. 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
16. 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/
18. 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#
Hinweis der Redaktion
Some blog posts related to this talk on the blog.
Why we were interested in using F# (and why you might also be interested)
What were some of the practical problems in actually getting an F# project underway.
Was it worth it?
Some commonly given reasons.
What were OUR major reaons.
Style of programming:
use of value objects (immutable with value equality)
event store like approaches
Generated by Resharper of course…
Let’s not get diverted by the less code = better issue
But: code is communication, and there is a lot of code here to communicate something (and a lot of code to go wrong).
SOLID
Single Responsibility
a class should only have one responsibility
Open/Closed
Liskov substitution
Interface Segregation
a class should not be dependent on anything more than necessary
Dependency Inversion
(e.g. a class with single responsibility of persistence or reading/writing to a db, say a repository,
one responsibility, could give it two interface roles, read, and write)
Emergence of smaller classes with less methods (but more classes)
Static methods (trying to dream up static class names when a namespace would suffice)
Linq chains (with static methods).
Mark Seeman: Role based interface/classes (ISP) following the SRP push in the direction of an interface with one method.
As composition is used more often, the reduction of specifically object-oriented features further reduces the need to be using an object oriented language
Rule of thumb: use composition over inheritance.
Some guidelines:
do not use inheritance simply because there are common set of properties between objects, unless those properties truly reflect a common model item.
do not use inheritance simply to gain access to common functionality required by two objects.
carefully consider whether you really need inheritance if you are not mutating common base state with common methods, or as directed by common methods.
if you are only using common base state, this state can still be provided as function parameters.
How do I get my distributed, website-front end project which must persist something into Azure, and using webjobs?
How do I go from that elegent F# code I keep seeing, with all the promise of no-null land and easy to reason about, to a product?
How do I go from that immutable, pure functional business, into a product which inevitably mutates something (usually the db, but inevitably some user output, unless you want a completely inert product).
Database Access (SQL)
Distributed Communication (Bus)
Website
Unit/Integration Testing
Pros
use familiar frameworks in dev and production (along with familiar prod. tooling)
Can pick up F# libraries as one feels comfortable
Cons:
C# interop code tends to be non-functional, can be messy, and is amongst the first code written
May need C# to F# anti-corruption layer between outer parts of program (where frameworks interact) and core domain code to get the full benefits of F#
Need to think about 2 styles of F#: purely functional, object-oriented/imperative. Try to keep them separate, but does put another burden on learning.
Domain code: pure functional F#
Main blocks of code.
Nature of code in each block can be quite different.
(bit on right: C#/F# syntax explanation)
Composition Root:
Includes some framework code (e.g. Nsb UnitOfWork)
Includes minimal use of IOC container, mostly because we were using Nsb and Nancy.
Most composition occurred within the handlers, or the top level Get/Post functions on the nancy module.
Keep C# interop code separate from F#
Consider anti-corruption against C#
Single Responsibility functions will tend to fall naturally into composable layers – keep the responsibilities separated.
How does one mutate the database : i.e. mutate the db based on an immutable domain.
PROJECT LAYOUT- NOTABLE FEATURES:
No directories
Typically what would go in multiple C# files goes in one F# file.
F# files must be in dependency order (NO CYCLIC DEPENDENCIES)
Single Case Unions: equivalent of forcing use of a constructor.
Exceptions are not functional. Just don’t
Cons:
Slower development time
Whether a significant factor another issue.
You are learning a new language, that comes at some cost.
Team will inevitably be at different stages of F# usage (kind of like other languages, but even more exaggerated)
C# interop: yuck.
Pros:
Benefits of immutability, value equality, functional push towards single responsibility, composition
No nulls.
Easier to refactor (I think). The strong alliance between types and functions make moving things around a whole lot easier.
No cyclic dependencies: yes really it is a good thing.
Easier to reason about code.
It will make you a better programmer. Choose your paradigm (functional/OO) and stick with it.
Either paradigm can be done in F# or C#
Both paradigms can easily coexist in one program (preferably just not together).
Focus on which one – the code as communication will be clearer.