×
  • Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
 

Domain Driven Design with the F# type System -- NDC London 2013

by on Dec 07, 2013

  • 9,183 views

Statically typed functional programming languages like F# encourage a very different way of thinking about types. The type system is your friend, not an annoyance, and can be used in many ways that ...

Statically typed functional programming languages like F# encourage a very different way of thinking about types. The type system is your friend, not an annoyance, and can be used in many ways that might not be familiar to OO programmers.

Types can be used to represent the domain in a fine-grained, self documenting way. And in many cases, types can even be used to encode business rules so that you literally cannot create incorrect code. You can then use the static type checking almost as an instant unit test — making sure that your code is correct at compile time.

In this talk, we'll look at some of the ways you can use types as part of a domain driven design process, with some simple real world examples in F#. No jargon, no maths, and no prior F# experience necessary.

Code, links to video, etc., at http://fsharpforfunandprofit.com/ddd

For more on DDD and F# see:

http://fsharpforfunandprofit.com/ddd/
http://tomasp.net/blog/type-first-development.aspx/
http://gorodinski.com/blog/2013/02/17/domain-driven-design-with-fsharp-and-eventstore/

Statistics

Views

Total Views
9,183
Views on SlideShare
8,661
Embed Views
522

Actions

Likes
26
Downloads
73
Comments
8

17 Embeds 522

https://twitter.com 294
https://t.co 135
http://www.scoop.it 76
https://kcw.kddi.ne.jp 4
https://docs.google.com 1
https://www.yammer.com 1
https://m.facebook.com&_=1386840560622 HTTP 1
https://mail.google.com 1
https://m.facebook.com&_=1386777911190 HTTP 1
https://m.facebook.com&_=1386758409996 HTTP 1
https://m.facebook.com&_=1386603332367 HTTP 1
https://m.facebook.com&_=1386603428074 HTTP 1
https://m.facebook.com&_=1386599713110 HTTP 1
http://www.linkedin.com 1
https://m.facebook.com&_=1386589024499 HTTP 1
https://m.facebook.com&_=1386572980888 HTTP 1
http://fpbridge.co.uk 1
More...

Accessibility

Categories

Upload Details

Uploaded via SlideShare as Adobe PDF

Usage Rights

CC Attribution-NonCommercial LicenseCC Attribution-NonCommercial License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

18 of 8 previous next Post a comment

  • robertwlaschin Robert Wlaschin, Staff Software Engineer at RockYou Very interesting talk. Cos' Maybe I'll check out F# and see how it can help me at my job. 1 week ago
    Are you sure you want to
    Your message goes here
    Processing…
  • Yevhen_Bobrov Yevhen Bobrov, Software Developer @ScottWlaschin ye, but with structs Null object pattern is often used. I understand that Null object pattern is less convenient but it's a trade-off between performance and convinience 4 months ago
    Are you sure you want to
    Your message goes here
    Processing…
  • ScottWlaschin Scott Wlaschin @MichaelRobin

    Interop with C# can be tricky, yes. The answer is to not use C#!

    Seriously though, if you really need to interop with C#, I normally define helper methods in F# (see http://bugsquash.blogspot.co.uk/2012/03/algebraic-data-type-interop-f-c.html) or even whole interfaces.

    As to ORMs in F#, I think that we need a different approach. The relation algebra is much closer to functional, anyway, so why use an ORM? I generally use a CQS pattern, queries for reads (via LINQ) and sprocs for updates, using a simple wrapper library.

    For storing unions, I convert the tags to a discriminator or booleans, just as for an inheritance hierarchy (see http://www.agiledata.org/essays/mappingObjects.html#MapHierarchyToTable). Of course, it is annoying to have to do this, but is generally quite quick to implement. And for single case unions, I just map directly to the primitive type.

    So, yes, there is extra work in all this, but even so, I find the benefit of having domain types greatly outweighs the cost.

    For example, I recently did a major refactoring of a domain, and for three days, the code would not compile... but when I did get it to compile finally, it worked like a charm.

    BTW, 'There's nothing that can't be solved by wrapping in a type' is meant to be a DDD twist on this quote (http://www.quora.com/Who-said-Theres-no-problem-that-cant-be-solved-with-another-level-of-indirection)
    4 months ago
    Are you sure you want to
    Your message goes here
    Processing…
  • MichaelRobin Michael Robin 'There's nothing that can't be solved by wrapping in a type'
    Well, there's one thing: serialization/storage and interop. From a DDD perspective, I agree that using single case DU's, etc., rather than bools is very nice and enforces a certain set of constraints at compile time, but the resultant object is not so easy to deal with from other languages (even C#) and to store and retrieve from a database, ORM, etc., as it introduces more of the classic 'impedance mismatch' problem by introducing many sub-type relations that may be better served as bools externally. As executable code that also happens to be a nice-looking (if limited) contract, F# is great, but what is elegant in F# can be harder to consume elsewhere, where you end up wrapping the functional code in an OO wrapper, meaning there are now two pieces of code to maintain. I suppose the F# compiler *could* represent certain sub-type relations without introducing actual types (perhaps directed by attribute hints) but that would be pretty major global opt. trickery. (For the record, I love F# and have been using it since it was available - I'm just thinking out loud now because I'm coming across some of these issues currently.)
    4 months ago
    Are you sure you want to
    Your message goes here
    Processing…
  • Yevhen_Bobrov Yevhen Bobrov, Software Developer @ScottWlaschin ok. It's very frequent to use Null object pattern with structs. I understand that this then requires checks if you pass VOs, but it's a trade-off between performance and convenience. 4 months ago
    Are you sure you want to
    Your message goes here
    Processing…
  • ScottWlaschin Scott Wlaschin @Yevhen_Bobrov

    'Usually ppl use structs with public readonly fields for VOs not classes'

    Jimmy Nilsson disagrees. For example in his book: http://books.google.co.uk/books?id=8RueQPUOPssC&pg=PT254&lpg=PT254&ved=0CG0Q6AEwBw#v=onepage&q&f=false

    My reason not use to structs is so that I can enforce a non-default constructor to ensure correctness of the data going in.

    Thanks!
    4 months ago
    Are you sure you want to
    Your message goes here
    Processing…
  • Yevhen_Bobrov Yevhen Bobrov, Software Developer Scott, slide 22 - it's not really fair. Usually ppl use structs with public readonly fields for VOs not classes. So it much less code then what you've shown 4 months ago
    Are you sure you want to
    Your message goes here
    Processing…
  • ScottWlaschin Scott Wlaschin Just to address some common concerns:

    'This is an anemic domain model'.

    That concept is not applicable to functional-style DDD because the focus is indeed on data rather than behaviour.

    However, 'data' in the functional world also includes verbs, not just nouns! So we are not talking about just dumb data structures.

    Many of the constraints and invariants that would be dealt with by methods in C# (i.e. behavior) can be dealt with instead by using static types.

    You can see this in slide 90, where many invariants are enforced without behavior.

    'Where's the behavior?'

    And for other kinds of behaviour, functional DDD focuses on *transformations*: inputs and outputs (which are described as types, btw). This makes it a very good fit for CQRS and event sourcing.

    Unfortunately, I didn't have time to get into this in my talk, but I hope to blog about it (at fsharpforfunandprofit.com) soon.

    'How can I enforce encapsulation'

    Slide 30 talks about all code going through 'tryCreatePerson'. How can you enforce this?

    The approach I like to use is 'signature files', described here: http://stackoverflow.com/a/1844881/1136133

    and also under 'Forcing use of the constructor' here: http://fsharpforfunandprofit.com/posts/designing-with-types-single-case-dus/

    'Can't strings be null?'

    Yes, they can. For compatibility with other .NET code, all reference types in F# can be null.

    So, when I accept a string value (or any object) from an external system, I always immediately convert it into a safe value.

    You can see some code here: https://github.com/swlaschin/NDC_London_2013/blob/master/ddd.fsx#L436

    Generally you should not be dealing with 'strings' anyway, but 'email address', 'phone number', and other types that have meaning in the domain. And as part of converting a raw string to one of these, you can check for nulls.
    4 months ago
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Domain Driven Design with the F# type System -- NDC London 2013 Domain Driven Design with the F# type System -- NDC London 2013 Presentation Transcript