KEMBAR78
Functional Programming with C# | PPTX
Functional Programming in C#
What is Functional Programming?
• Side-effect free programming?
• Higher order functions?
• Use of a functional language like F# / Haskell / Scala?
Functional programming is
programming with mathematical
functions.
Problem solved!
What is Functional Programming?
Mathematical
function
Class
method=
What is Functional Programming?
f
Referential transparency:
same input – same result
Information about possible
inputs and outcomes
What is Functional Programming?
public double Calculate(double x, double y)
{
return x * x + y * y;
}
public long TicksElapsedFrom(int year)
{
DateTime now = DateTime.Now;
DateTime then = new DateTime(year, 1, 1);
return (now - then).Ticks;
}
Same input – same result Result is always different
What is Functional Programming?
public static int Divide(int x, int y)
{
return x / y;
}
f
Integer
Integer
Integer
1
0
?
DivideByZeroException
Method Signature Honesty
Method
signature
All possible
inputs
All possible
outcomes
Method Signature Honesty
Honest signatureDishonest signature
public static int Divide(int x, int y)
{
return x / y;
}
public static int Divide(int x, NonZeroInteger y)
{
return x / y.Value;
}
public static int? Divide(int x, int y)
{
if (y == 0)
return null;
return x / y;
}
Mathematical Function
• Honest
• Has precisely defined input and output
• Referentially transparent
• Doesn’t affect or refer to the global state
Why Functional Programming?
Composable
Easy to reason about
Easier to unit test
Reducing
complexity
Immutability
• Immutability
• Inability to change data
• State
• Data that changes over time
• Side effect
• A change that is made to some state
Immutability
Mutable
operations
Dishonest
code=
Immutability
fInput Output
Side effect
Method
signature
Hidden part
Immutability
fInput
Output
Side effect
Method
signature
Hidden part
Output 2
Why Does Immutability Matter?
• Increased readability
• A single place for validating invariants
• Automatic thread safety
How to Deal with Side Effects
Command–query separation principle
Command Query
Produces side effects Side-effect free
Returns void Returns non-void
How to Deal with Side Effects
public class CustomerService {
public void Process(string customerName, string addressString) {
Address address = CreateAddress(addressString);
Customer customer = CreateCustomer(customerName, address);
SaveCustomer(customer);
}
private Address CreateAddress(string addressString) {
return new Address(addressString);
}
private Customer CreateCustomer(string name, Address address) {
return new Customer(name, address);
}
private void SaveCustomer(Customer customer) {
var repository = new Repository();
repository.Save(customer);
}
}
Command
Query
Command
Query
How to Deal with Side Effects
var stack = new Stack<string>();
stack.Push("value"); // Command
string value = stack.Pop(); // Both query and command
How to Deal with Side Effects
Application
Domain logic Mutating state
Generates artifacts
Uses artifacts to change
the system’s state
How to Deal with Side Effects
Immutable CoreInput Artifacts
Mutable Shell
Exceptions and Readability
public ActionResult CreateEmployee(string name) {
try {
ValidateName(name);
// Rest of the method
return View("Success");
}
catch (ValidationException ex) {
return View("Error", ex.Message);
}
}
private void ValidateName(string name) {
if (string.IsNullOrWhiteSpace(name))
throw new ValidationException("Name cannot be empty");
if (name.Length > 100)
throw new ValidationException("Name is too long");
}
Exceptions and Readability
public Employee CreateEmployee(string name)
{
ValidateName(name);
// Rest of the method
}
Exceptions and Readability
Exceptions for
flow control
Goto
statements=
Exceptions and Readability
Method with
exceptions
Mathematical
function=
Exceptions and Readability
fInput Output
Exceptions
Method
signature
Hidden part
Always prefer return values
over exceptions.
Use Cases for Exceptions
• Exceptions are for exceptional situations
• Exceptions should signalize a bug
• Don’t use exceptions in situations you expect to happen
Use Cases for Exceptions
Validations
Exceptional
situation=
Primitive Obsession
Primitive obsession stands for
using primitive types for
domain modeling.
Drawbacks of Primitive Obsession
public class User
{
public string Email { get; }
public User(string email)
{
Email = email;
}
}
public class User
{
public string Email { get; }
public User(string email)
{
if (string.IsNullOrWhiteSpace(email))
throw new ArgumentException("Email should not be empty");
email = email.Trim();
if (email.Length > 256)
throw new ArgumentException("Email is too long");
if (!email.Contains("@"))
throw new ArgumentException("Email is invalid");
Email = email;
}
}
Drawbacks of Primitive Obsession
Drawbacks of Primitive Obsession
public class Organization
{
public string PrimaryEmail { get; }
public Organization(string primaryEmail)
{
PrimaryEmail = primaryEmail;
}
}
public class Organization
{
public string PrimaryEmail { get; }
public Organization(string primaryEmail)
{
if (string.IsNullOrWhiteSpace(primaryEmail))
throw new ArgumentException("Email should not be empty");
primaryEmail = primaryEmail.Trim();
if (primaryEmail.Length > 256)
throw new ArgumentException("Email is too long");
if (!primaryEmail.Contains("@"))
throw new ArgumentException("Email is invalid");
PrimaryEmail = primaryEmail;
}
}
Drawbacks of Primitive Obsession
Drawbacks of Primitive Obsession
Dishonest signature
public class UserFactory
{
public User CreateUser(string email)
{
return new User(email);
}
}
public int Divide(int x, int y)
{
return x / y;
}
fstring user
Dishonest signature
Drawbacks of Primitive Obsession
Makes code
dishonest
Violates the
DRY principle
Wrap primitive types with
separate classes
Drawbacks of Primitive Obsession
public class UserFactory
{
public User CreateUser(Email email)
{
return new User(email);
}
}
public int Divide(int x, NonZeroInteger y)
{
return x / y;
}
femail user
Honest signature Honest signature
Getting Rid of Primitive Obsession
• Removing duplications
• Method signature honesty
• Stronger type system
The Billion-dollar Mistake
string someString = null;
Customer customer = null;
Employee employee = null;
The Billion-dollar Mistake
“I call it my billion-dollar mistake. It has caused
a billion dollars of pain and damage in the last
forty years.”
Tony Hoare
The Billion-dollar Mistake
public class Organization
{
public Employee GetEmployee(string name)
{
/* ... */
}
}
public class OrganizationRepository
{
public Organization GetById(int id)
{
/* ... */
}
}
The Billion-dollar Mistake
public class MyClassOrNull
{
// either null
public readonly Null Null;
// or actually a MyClass instance
public readonly MyClass MyClass;
}
public class MyClass
{
}
The Billion-dollar Mistake
fInteger MyClass
MyClassOrNull
Dishonest
Mitigating the Billion-dollar Mistake
Maybe<T>
Mitigating the Billion-dollar Mistake
public class OrganizationRepository
{
public Organization GetById(int id)
{
/* ... */
}
}
Maybe<Organization>
Mitigating the Billion-dollar Mistake
public class OrganizationRepository
{
public Maybe<Organization> GetById(int id)
{
/* ... */
}
}
public class Organization
{
public Employee GetEmployee(string name)
{
/* ... */
}
}
Mitigating the Billion-dollar Mistake
public class OrganizationRepository
{
public Maybe<Organization> GetById(int id)
{
/* ... */
}
}
public static int? Divide(int x, int y)
{
if (y == 0)
return null;
return x / y;
}
Honest
Honest
Functional C#
Demo time
Summary
• Functional programming is programming with mathematical functions
• Method signature honesty
• Referential transparency
• Side effects and exceptions make your code dishonest about the
outcome it may produce
• Primitive obsession makes your code dishonest about its input parts
• Nulls make your code dishonest about both its inputs and outputs
• Applying Functional Principles in C# Pluralsight course:
https://app.pluralsight.com/courses/csharp-applying-functional-
principles
THANK YOU
Vladimir Khorikov
@vkhorikov
vkhorikov@eastbanctech.com
202-295-3000
eastbanctech.com

Functional Programming with C#

  • 1.
  • 2.
    What is FunctionalProgramming? • Side-effect free programming? • Higher order functions? • Use of a functional language like F# / Haskell / Scala?
  • 3.
    Functional programming is programmingwith mathematical functions.
  • 4.
  • 5.
    What is FunctionalProgramming? Mathematical function Class method=
  • 6.
    What is FunctionalProgramming? f Referential transparency: same input – same result Information about possible inputs and outcomes
  • 7.
    What is FunctionalProgramming? public double Calculate(double x, double y) { return x * x + y * y; } public long TicksElapsedFrom(int year) { DateTime now = DateTime.Now; DateTime then = new DateTime(year, 1, 1); return (now - then).Ticks; } Same input – same result Result is always different
  • 8.
    What is FunctionalProgramming? public static int Divide(int x, int y) { return x / y; } f Integer Integer Integer 1 0 ? DivideByZeroException
  • 9.
    Method Signature Honesty Method signature Allpossible inputs All possible outcomes
  • 10.
    Method Signature Honesty HonestsignatureDishonest signature public static int Divide(int x, int y) { return x / y; } public static int Divide(int x, NonZeroInteger y) { return x / y.Value; } public static int? Divide(int x, int y) { if (y == 0) return null; return x / y; }
  • 11.
    Mathematical Function • Honest •Has precisely defined input and output • Referentially transparent • Doesn’t affect or refer to the global state
  • 12.
    Why Functional Programming? Composable Easyto reason about Easier to unit test Reducing complexity
  • 13.
    Immutability • Immutability • Inabilityto change data • State • Data that changes over time • Side effect • A change that is made to some state
  • 14.
  • 15.
  • 16.
  • 17.
    Why Does ImmutabilityMatter? • Increased readability • A single place for validating invariants • Automatic thread safety
  • 18.
    How to Dealwith Side Effects Command–query separation principle Command Query Produces side effects Side-effect free Returns void Returns non-void
  • 19.
    How to Dealwith Side Effects public class CustomerService { public void Process(string customerName, string addressString) { Address address = CreateAddress(addressString); Customer customer = CreateCustomer(customerName, address); SaveCustomer(customer); } private Address CreateAddress(string addressString) { return new Address(addressString); } private Customer CreateCustomer(string name, Address address) { return new Customer(name, address); } private void SaveCustomer(Customer customer) { var repository = new Repository(); repository.Save(customer); } } Command Query Command Query
  • 20.
    How to Dealwith Side Effects var stack = new Stack<string>(); stack.Push("value"); // Command string value = stack.Pop(); // Both query and command
  • 21.
    How to Dealwith Side Effects Application Domain logic Mutating state Generates artifacts Uses artifacts to change the system’s state
  • 22.
    How to Dealwith Side Effects Immutable CoreInput Artifacts Mutable Shell
  • 23.
    Exceptions and Readability publicActionResult CreateEmployee(string name) { try { ValidateName(name); // Rest of the method return View("Success"); } catch (ValidationException ex) { return View("Error", ex.Message); } } private void ValidateName(string name) { if (string.IsNullOrWhiteSpace(name)) throw new ValidationException("Name cannot be empty"); if (name.Length > 100) throw new ValidationException("Name is too long"); }
  • 24.
    Exceptions and Readability publicEmployee CreateEmployee(string name) { ValidateName(name); // Rest of the method }
  • 25.
    Exceptions and Readability Exceptionsfor flow control Goto statements=
  • 26.
    Exceptions and Readability Methodwith exceptions Mathematical function=
  • 27.
    Exceptions and Readability fInputOutput Exceptions Method signature Hidden part
  • 28.
    Always prefer returnvalues over exceptions.
  • 29.
    Use Cases forExceptions • Exceptions are for exceptional situations • Exceptions should signalize a bug • Don’t use exceptions in situations you expect to happen
  • 30.
    Use Cases forExceptions Validations Exceptional situation=
  • 31.
    Primitive Obsession Primitive obsessionstands for using primitive types for domain modeling.
  • 32.
    Drawbacks of PrimitiveObsession public class User { public string Email { get; } public User(string email) { Email = email; } }
  • 33.
    public class User { publicstring Email { get; } public User(string email) { if (string.IsNullOrWhiteSpace(email)) throw new ArgumentException("Email should not be empty"); email = email.Trim(); if (email.Length > 256) throw new ArgumentException("Email is too long"); if (!email.Contains("@")) throw new ArgumentException("Email is invalid"); Email = email; } } Drawbacks of Primitive Obsession
  • 34.
    Drawbacks of PrimitiveObsession public class Organization { public string PrimaryEmail { get; } public Organization(string primaryEmail) { PrimaryEmail = primaryEmail; } }
  • 35.
    public class Organization { publicstring PrimaryEmail { get; } public Organization(string primaryEmail) { if (string.IsNullOrWhiteSpace(primaryEmail)) throw new ArgumentException("Email should not be empty"); primaryEmail = primaryEmail.Trim(); if (primaryEmail.Length > 256) throw new ArgumentException("Email is too long"); if (!primaryEmail.Contains("@")) throw new ArgumentException("Email is invalid"); PrimaryEmail = primaryEmail; } } Drawbacks of Primitive Obsession
  • 36.
    Drawbacks of PrimitiveObsession Dishonest signature public class UserFactory { public User CreateUser(string email) { return new User(email); } } public int Divide(int x, int y) { return x / y; } fstring user Dishonest signature
  • 37.
    Drawbacks of PrimitiveObsession Makes code dishonest Violates the DRY principle
  • 38.
    Wrap primitive typeswith separate classes
  • 39.
    Drawbacks of PrimitiveObsession public class UserFactory { public User CreateUser(Email email) { return new User(email); } } public int Divide(int x, NonZeroInteger y) { return x / y; } femail user Honest signature Honest signature
  • 40.
    Getting Rid ofPrimitive Obsession • Removing duplications • Method signature honesty • Stronger type system
  • 41.
    The Billion-dollar Mistake stringsomeString = null; Customer customer = null; Employee employee = null;
  • 42.
    The Billion-dollar Mistake “Icall it my billion-dollar mistake. It has caused a billion dollars of pain and damage in the last forty years.” Tony Hoare
  • 43.
    The Billion-dollar Mistake publicclass Organization { public Employee GetEmployee(string name) { /* ... */ } } public class OrganizationRepository { public Organization GetById(int id) { /* ... */ } }
  • 44.
    The Billion-dollar Mistake publicclass MyClassOrNull { // either null public readonly Null Null; // or actually a MyClass instance public readonly MyClass MyClass; } public class MyClass { }
  • 45.
    The Billion-dollar Mistake fIntegerMyClass MyClassOrNull Dishonest
  • 46.
  • 47.
    Mitigating the Billion-dollarMistake public class OrganizationRepository { public Organization GetById(int id) { /* ... */ } } Maybe<Organization>
  • 48.
    Mitigating the Billion-dollarMistake public class OrganizationRepository { public Maybe<Organization> GetById(int id) { /* ... */ } } public class Organization { public Employee GetEmployee(string name) { /* ... */ } }
  • 49.
    Mitigating the Billion-dollarMistake public class OrganizationRepository { public Maybe<Organization> GetById(int id) { /* ... */ } } public static int? Divide(int x, int y) { if (y == 0) return null; return x / y; } Honest Honest
  • 50.
  • 51.
    Summary • Functional programmingis programming with mathematical functions • Method signature honesty • Referential transparency • Side effects and exceptions make your code dishonest about the outcome it may produce • Primitive obsession makes your code dishonest about its input parts • Nulls make your code dishonest about both its inputs and outputs • Applying Functional Principles in C# Pluralsight course: https://app.pluralsight.com/courses/csharp-applying-functional- principles
  • 52.

Editor's Notes

  • #13 Composable: can be treated in isolation Easier to reason about, no need to fall down to implementation details Easier to unit test, just provide input and verify output, no mocks Reducing complexity: fewer bugs, better maintainability The principles – referential transparency and method signature honesty - look quite simple, but if applied in practice, have interesting consequences. Let’s see what those consequences are.
  • #15 When we talked about the concept of method signature honesty in the previous module, we discussed that whenever you define a method, you should try to put into its signature the information about all its possible outcomes. By defining a method with a side-effect, we loose this information. The signature of such a method no longer tells us what the actual result of the operation is. Hinders our ability to reason about the code.
  • #16 So, how to fix that? Lift all possible outcomes to a signature level.
  • #17 - Immutability does exactly this: it forces you to be honest about what the method does.
  • #19 Cannot avoid dealing with side effects
  • #23 Make shell as dumb as possible