Functional Programming with C#
-
Upload
eastbanc-tachnologies -
Category
Software
-
view
107 -
download
2
Transcript of Functional Programming with C#
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?
Mathematicalfunction
Class method=
What is Functional Programming?
fReferential 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;}
fInteger
IntegerInteger
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
fInputOutput
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"); // Commandstring 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 @[email protected]