Functional SOLID
(Can I apply SOLID to FP?)
Alexandr Sugak,
Software Architect at Sigma Software,
https://github.com/AlexSugak
SOLID is about OOP
OR IS IT?
SOLID example
https://www.pluralsight.com/courses/encapsulation-solid
• Implement a message store;
• Messages are stored as files on disk;
• Messages are cached;
• Access to messages is logged.
SRP: one reason to change
• A module/class must encapsulate one thing;
• How to find this one thing?
• RCM’s answer: object must have one reason
for change.
SRP: file store
OCP: closed for modification
• Could it be that behavior of a class/module
may be extended/changed in future?
• How can we extract this reason for change as
an abstraction?
• How can we program that class/module once
and for all (close it)?
OCP: opened for extensibility
It is agreed that usually it is better to achieve
extensibility and reuse by composition instead of
inheritance.
https://en.wikipedia.org/wiki/Composition_over_inheritance
GoF:
“Ideally you shouldn’t have to create new components to achieve reuse. You should be
able to get all the functionality you need just by assembling existing components through
object composition. But this is rarely the case, because the set of available components is
never quite rich enough in practice. Reuse by inheritance makes it easier to make new
components that can be composed with old ones. Inheritance and object composition thus
work together.
Nevertheless, our experience is that designers overuse inheritance as a reuse technique
and designs are often made more reusable (and simpler) by depending more on object
composition. You’ll see object composition applied again and again in the design patterns.”
OCP: cache store via decorator
LSP: conforming to semantics of
an abstraction
What can we assume about implementation of
abstraction?
• Command Query Separation;
• Strong typing enforces semantics;
• Maybe<T> instead of nulls;
• Strongly typed errors;
• Code Contracts;
• Checked exceptions in Java;
• Etc.
LSP: store logger
ISP: do not depend on things you
do not use
• The smallest interface has one method;
• You cannot violate ISP if all interfaces have
one method.
ISP: message store
DIP: high must not depend on low
• Both must depend on abstraction;
• Programming against interfaces.
DIP: message store
SOLID Message Store:
decorators everywhere!
https://www.pluralsight.com/courses/encapsulation-solid
Extreme SOLID results in
• A bunch of one-method interfaces;
Extreme SOLID results in
• A bunch of one-method interfaces;
• A lot of small one/two-method classes;
Extreme SOLID results in
• A bunch of one-method interfaces;
• A lot of small one/two-method classes;
• Decorators everywhere;
Extreme SOLID results in
• A bunch of one-method interfaces;
• A lot of small one/two-method classes;
• Decorators everywhere;
• Compositions of complex behaviors out of
simple classes;
Extreme SOLID results in
• A bunch of one-method interfaces;
• A lot of small one/two-method classes;
• Decorators everywhere;
• Compositions of complex behaviors out of
simple classes;
• Other developers don’t like to work with such
code base.
Extreme SOLID results in
Extreme SOLID results in
Extreme SOLID results in doing
this:
https://github.com/AlexSugak/concurrencysample
To implement this:
https://github.com/AlexSugak/concurrencysample
Doing SOLID in OO requires
experience and discipline:
• Such code is not idiomatic to C# or Java;
• Our tools (IDE) are not optimized for this;
• Majority of developers are not used to this;
• Requires deep knowledge and understanding
in majority of the team.
SOLID in FP
OOP FP
One-method interfaces
One-method classes
Decorators
Composition
SOLID in FP
OOP FP
One-method interfaces Functions
One-method classes Functions
Decorators Functions
Composition Function composition
Message Store in F#, types:
https://github.com/AlexSugak/message-store
Message Store in F#, types:
Message Store in F#, types:
Partial Application of functions:
Partial Application of functions:
Pipe operator in F#:
Message Store in F#, file store:
Message Store in F#, store
cache:
Message Store in F#, store
logger:
Message Store in F#,
composition:
Message Store in F#,
composition:
Message Store in F#,
composition:
Message Store in F#, simpler:
http://www.fssnip.net/h4
SOLID in FP, simpler, easier:
• Coming up with a good abstraction is hard;
• PL should help with that, not make it more
difficult;
• FP focuses on types, function signatures,
composition, making it easier to reason about
abstractions;
• The result artifact is usually simpler.
Thank you!
Questions?
F# in Kharkiv:
https://www.facebook.com/groups/kharkivfsharp/

Functional Solid, Aleksandr Sugak

  • 1.
    Functional SOLID (Can Iapply SOLID to FP?) Alexandr Sugak, Software Architect at Sigma Software, https://github.com/AlexSugak
  • 2.
    SOLID is aboutOOP OR IS IT?
  • 3.
    SOLID example https://www.pluralsight.com/courses/encapsulation-solid • Implementa message store; • Messages are stored as files on disk; • Messages are cached; • Access to messages is logged.
  • 4.
    SRP: one reasonto change • A module/class must encapsulate one thing; • How to find this one thing? • RCM’s answer: object must have one reason for change.
  • 5.
  • 6.
    OCP: closed formodification • Could it be that behavior of a class/module may be extended/changed in future? • How can we extract this reason for change as an abstraction? • How can we program that class/module once and for all (close it)?
  • 7.
    OCP: opened forextensibility It is agreed that usually it is better to achieve extensibility and reuse by composition instead of inheritance. https://en.wikipedia.org/wiki/Composition_over_inheritance GoF: “Ideally you shouldn’t have to create new components to achieve reuse. You should be able to get all the functionality you need just by assembling existing components through object composition. But this is rarely the case, because the set of available components is never quite rich enough in practice. Reuse by inheritance makes it easier to make new components that can be composed with old ones. Inheritance and object composition thus work together. Nevertheless, our experience is that designers overuse inheritance as a reuse technique and designs are often made more reusable (and simpler) by depending more on object composition. You’ll see object composition applied again and again in the design patterns.”
  • 8.
    OCP: cache storevia decorator
  • 9.
    LSP: conforming tosemantics of an abstraction What can we assume about implementation of abstraction? • Command Query Separation; • Strong typing enforces semantics; • Maybe<T> instead of nulls; • Strongly typed errors; • Code Contracts; • Checked exceptions in Java; • Etc.
  • 10.
  • 11.
    ISP: do notdepend on things you do not use • The smallest interface has one method; • You cannot violate ISP if all interfaces have one method.
  • 12.
  • 13.
    DIP: high mustnot depend on low • Both must depend on abstraction; • Programming against interfaces.
  • 14.
  • 15.
    SOLID Message Store: decoratorseverywhere! https://www.pluralsight.com/courses/encapsulation-solid
  • 16.
    Extreme SOLID resultsin • A bunch of one-method interfaces;
  • 17.
    Extreme SOLID resultsin • A bunch of one-method interfaces; • A lot of small one/two-method classes;
  • 18.
    Extreme SOLID resultsin • A bunch of one-method interfaces; • A lot of small one/two-method classes; • Decorators everywhere;
  • 19.
    Extreme SOLID resultsin • A bunch of one-method interfaces; • A lot of small one/two-method classes; • Decorators everywhere; • Compositions of complex behaviors out of simple classes;
  • 20.
    Extreme SOLID resultsin • A bunch of one-method interfaces; • A lot of small one/two-method classes; • Decorators everywhere; • Compositions of complex behaviors out of simple classes; • Other developers don’t like to work with such code base.
  • 21.
  • 22.
  • 23.
    Extreme SOLID resultsin doing this: https://github.com/AlexSugak/concurrencysample
  • 24.
  • 25.
    Doing SOLID inOO requires experience and discipline: • Such code is not idiomatic to C# or Java; • Our tools (IDE) are not optimized for this; • Majority of developers are not used to this; • Requires deep knowledge and understanding in majority of the team.
  • 26.
    SOLID in FP OOPFP One-method interfaces One-method classes Decorators Composition
  • 27.
    SOLID in FP OOPFP One-method interfaces Functions One-method classes Functions Decorators Functions Composition Function composition
  • 28.
    Message Store inF#, types: https://github.com/AlexSugak/message-store
  • 29.
    Message Store inF#, types:
  • 30.
    Message Store inF#, types:
  • 31.
  • 32.
  • 33.
  • 34.
    Message Store inF#, file store:
  • 35.
    Message Store inF#, store cache:
  • 36.
    Message Store inF#, store logger:
  • 37.
    Message Store inF#, composition:
  • 38.
    Message Store inF#, composition:
  • 39.
    Message Store inF#, composition:
  • 40.
    Message Store inF#, simpler: http://www.fssnip.net/h4
  • 41.
    SOLID in FP,simpler, easier: • Coming up with a good abstraction is hard; • PL should help with that, not make it more difficult; • FP focuses on types, function signatures, composition, making it easier to reason about abstractions; • The result artifact is usually simpler.
  • 42.
  • 43.

Editor's Notes

  • #2 How long do I work on this ? E.g. I am working in MS department and working with F# for 3 years, several projects are implement ted. Mentoring other teams on DDD, TDD and F#
  • #3 What was the fuse about at Lviv? Examples of hot questions: OCP is about classes and inheritance and cannot be applied to FP
  • #4 What is the task at hand? (describe the problem) You can compare Mark’s implementation with my F# alternative.
  • #5 SOLID helps with designing abstractions File system example: One message per file? All messages in one file? One file per hash bucket?
  • #6 One concern: the way messages are stored on disk
  • #8 (maybe phrase in Russian instead of reading in English)
  • #10 Example with collections in .Net
  • #11 logging is a side effect? No, still a query.
  • #24 Do not try to read it!
  • #27 Anybody works with/knows with F#? (Pick few people from audience to “work” with)
  • #43 Constantly learning using online resources Kharkov does not have F# community