SlideShare a Scribd company logo
1 of 63
Cleaner Code
How Clean Code is
Functional Code
Dave Fancher
Vibenomics
Lead Software Engineer
@davefancher
dave@davefancher.com
What is
Clean Code?
We know it when we see it…
“Code Sense”
Some of us are born with it.
Some of us have to fight to acquire it.
clean code is code that clearly
communicates with the reader
clean code lets us better
reason about the code
"Writing clean code requires the disciplined use of a
myriad of little techniques applied through a
painstakingly acquired sense of 'cleanliness'."
The Art of Clean Code?
Clean Code is a baseline series
of guidelines for writing
maintainable code
Subjective
Guidelines
• Naming conventions
• Comment style
• Additional documentation
• Etc…
The subjective guidelines are important.
We don’t care about them today.
Objective
Guidelines
• Data/Object Anti-Symmetry
• Single responsibility
• Don't have side effects
• Limit number of parameters
• Use of whitespace
• Don't pass/return null
• Etc…
Clean code is functional code
If it compiles, it’s correct.
Functional Programmers
Control Side
Effects
Favor
Expressions over
Statements
Treat Functions
as Data
3 Themes of
Functional Programming
Functions
(Chapter 3)
small!
"Functions should do one thing. They should do it
well. They should do it only."
Do One Thinghttp://bit.ly/UbqcZr
public static PersonModel SavePerson (PersonModel model)
{
// Validate the model
// …
// Transform the model to fit the database model
// …
// Write the change to the database
// …
// Audit the change
// …
// Return the updated model
// …
}
public static PersonModel ValidateModel(PersonModel model)
{ /* .. */ }
public static PersonModel StandardizeModel(PersonModel model)
{ /* .. */ }
public static PersonModel PersistModel(PersonModel model)
{ /* .. */ }
public static void AuditChange(PersonModel model)
{ /* .. */ }
public static PersonModel SavePerson(PersonModel model)
{
var validatedModel = ValidateModel(model);
var entity = StandardizeModel(validatedModel);
var storedEntity = PersistModel(entity);
AuditChange(storedEntity);
return storedEntity;
}
public static PersonModel ValidateModel(PersonModel model)
{ /* .. */ }
public static PersonModel CanoncalizeModel(PersonModel model)
{ /* .. */ }
public static PersonModel PersistModel(PersonModel model)
{ /* .. */ }
public static void AuditChange(PersonModel model)
{ /* .. */ }
public static PersonModel SavePerson(PersonModel model) =>
model
.Pipe(ValidateModel)
.Pipe(CanoncalizeModel)
.Pipe(PersistModel)
.Tee(AuditChange);
// Imperative Approach
public static PersonModel SavePerson(PersonModel model)
{
var validatedModel = ValidateModel(model);
var entity = CanoncalizeModel(validatedModel);
var storedEntity = PersistModel(entity);
AuditChange(storedEntity);
return storedEntity;
}
// Declarative/Functional Approach
public static PersonModel SavePerson(PersonModel model) =>
model
.Pipe(ValidateModel)
.Pipe(CanoncalizeModel)
.Pipe(PersistModel)
.Tee(AuditChange);
// JavaScript!
const { PIPE, TEE } = require("./pipeline");
const savePerson =
model =>
model
[PIPE](validateModel)
[PIPE](canoncalizeModel)
[PIPE](persistModel)
[TEE](auditChange);
”Arguments are hard"
Function Arguments
[DllImport(
"user32.dll",
EntryPoint = "CreateWindowExW",
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.StdCall)]
public extern static IntPtr CreateWindow(
int dwExStyle,
string lpClassName,
string lpWindowName,
int dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lParam);
Function Classification
Niladic 0 Arguments
Monadic 1 Argument
Dyadic 2 Arguments
Triadic 3 Arguments
Polyadic 4+ Arguments
.NET Generic Delegates
Non-returning Returning
Niladic Action Func<U>
Monadic Action<T> Func<T, U>
Dyadic Action<T1, T2> Func<T1, T2, U>
Triadic Action<T1, T2, T3> Func<T1, T2, T3, U>
Polyadic Action<T1, T2, T3, T4> Func<T1, T2, T3, T4, U>
+ 12 more…
More Functional Notation
Non-returning Returning
Niladic Unit  Unit Unit  U
Monadic T  Unit T  U
Dyadic (T1, T2)  Unit (T1, T2)  U
Triadic (T1, T2, T3)  Unit (T1, T2, T3)  U
Polyadic (T1, T2, T3, T4)  Unit (T1, T2, T3, T4)  U
…and so on
”Side effects are lies"
Have No Side Effects
public static void SaveInvoice (InvoiceModel model)
{
// Validate the model
// Transform the model to fit the database model
// Remove discounts
// Write the change to the database
}
public static void ApplyDiscounts (InvoiceModel model)
{
// Calculate invoice total
// Calculate total discount
// Deduct discount from total
// Update database again
}
public static void ChargeCustomer (InvoiceModel model)
{
// SaveInvoice(model);
// ApplyDiscounts(model);
}
When a function relies upon external state or changes
shared state the only valid answer to the question
“What does this function do?” is “I don’t know…”
Me
Functional Purity
The Power of One:
Functions should accept exactly one input and
return exactly one output
Function Classification
Niladic 0 Arguments
Monadic 1 Argument
Dyadic 2 Arguments
Triadic 3 Arguments
Polyadic 4+ Arguments
Function Classification
Niladic 0 Arguments
Monadic 1 Argument
Dyadic 2 Arguments
Triadic 3 Arguments
Polyadic 4+ Arguments
Functional Notation
Non-returning Returning
Niladic Unit  Unit Unit  U
Monadic T  Unit T  U
Dyadic (T1, T2)  Unit (T1, T2)  U
Triadic (T1, T2, T3)  Unit (T1, T2, T3)  U
Polyadic (T1, T2, T3, T4)  Unit (T1, T2, T3, T4)  U
…and so on
Functional Notation
(Revised)
Non-returning Returning
Niladic N/A N/A
Monadic N/A T  U
Dyadic N/A N/A
Triadic N/A N/A
Polyadic N/A N/A
…N/A
Functional Notation
(Simplified)
T  U
What about out parameters?
// C#
int value; // Ugh. Unintialized variable
if (Int32.TryParse(“124”, out value)) {
// Success
}
if (Int32.TryParse(“abc”, out value)) {
// Never going to run
}
// F# - wraps out and return values in tuple
match Int32.TryParse(”124”) with
| true, value -> // Success
| false, _ -> // Failure
Multiple Returns
• Dijkstra's Rules for Structured Programming
• A block should have only one entry and one exit
Formatting
(Format is Communication)
Vertical Formatting
(Newspaper Metaphor)
Indentation
(and Whitespace)
// Adapted from Clean Code: Page 86
private void measureLine(String line) {
lineCount++;
int lineSize =
line.length();
totalChars += lineSize;
lineWidthHistogram.addLine (lineSize, lineCount);
recordWidestline(
lineSize); }
private void recordWidestLine (int lineSize)
{
// Do something
}
“A source file is a hierarchy rather like
an outline”
Indentation
// Adapted from Clean Code: Page 86
private void measureLine(String line)
{
lineCount++;
int lineSize = line.length();
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount);
recordWidestline(lineSize);
}
private void recordWidestLine(int lineSize)
{
// Do something
}
Objects and
Data Structures
Data/Object Anti-Symmetry
Objects
• Hide their data behind
abstractions
• Expose functions to
operate on that data
Data Structures
• Expose their data
• Have no meaningful
functions
// Adapted from Figure 6-6
// Polymorphic Shape
Interface Shape {
double area();
}
public class Square implements Shape {
// fields
public double area() { /* … */ }
}
public class Rectangle implements Shape {
// fields
public double area() { /* … */ }
}
public class Circle implements Shape {
// fields
public double area() { /* … */ }
}
// Adapted from Figure 6-5
// Procedural Shape
public class Square { /* … */ }
public class Rectangle { /* … */ }
public class Circle { /* … */ }
public class Geometry {
public double area (Object shape) {
if (shape instanceof Square) { /* … */ }
else if (shape instanceof Rectangle) { /* … */ }
else if (shape instanceof Circle) { /* … */ }
throw new NotSupportedException();
}
}
In functional programming we typically favor data
structures to objects
// F# Example
// Discriminated Union and Pattern Match
type Shape =
| Square of topLeft: Point * side: double
| Rectangle of topLeft: Point * height: double * width: double
| Circle of center: Point * radius: double
let area shape =
match shape with
| Square(_, side) ->
side * side
| Rectangle(_, height, width) ->
height * width
| Circle(_, radius) ->
Math.PI * (radius * radius)
Dealing with Null
“I call it my billion-dollar mistake. It was the
invention of the null reference in 1965.”
Tony Hoare
Clean Code Guidance
Don’t Pass Null Don’t Return Null
Conclusion
No matter what language you work in, programming in a
functional style provides benefits. You should do it
whenever it is convenient, and you should think hard
about the decision when it isn't convenient.
John Carmack
THANK YOU!
Dave Fancher
Vibenomics
Lead Software Engineer
@davefancher
dave@davefancher.com

More Related Content

What's hot

Elements of Java Language - Continued
Elements of Java Language - Continued Elements of Java Language - Continued
Elements of Java Language - Continued Hitesh-Java
 
Java Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and PitfallsJava Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and PitfallsRakesh Waghela
 
Java Persistence API
Java Persistence APIJava Persistence API
Java Persistence APIIlio Catallo
 
Beyond PITS, Functional Principles for Software Architecture
Beyond PITS, Functional Principles for Software ArchitectureBeyond PITS, Functional Principles for Software Architecture
Beyond PITS, Functional Principles for Software ArchitectureJayaram Sankaranarayanan
 
Static program analysis tools
Static program analysis toolsStatic program analysis tools
Static program analysis toolsKamil Jezek
 
Unit I Advanced Java Programming Course
Unit I   Advanced Java Programming CourseUnit I   Advanced Java Programming Course
Unit I Advanced Java Programming Courseparveen837153
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015senejug
 
Finding bugs that matter with Findbugs
Finding bugs that matter with FindbugsFinding bugs that matter with Findbugs
Finding bugs that matter with FindbugsCarol McDonald
 
Session 08 - OOP with Java - continued
Session 08 - OOP with Java - continuedSession 08 - OOP with Java - continued
Session 08 - OOP with Java - continuedPawanMM
 
Interfaces and abstract classes
Interfaces and abstract classesInterfaces and abstract classes
Interfaces and abstract classesAKANSH SINGHAL
 
Sql Patterns
Sql PatternsSql Patterns
Sql Patternsphanleson
 
Lecture - 5 Control Statement
Lecture - 5 Control StatementLecture - 5 Control Statement
Lecture - 5 Control Statementmanish kumar
 
9781111530532 ppt ch10
9781111530532 ppt ch109781111530532 ppt ch10
9781111530532 ppt ch10Terry Yoast
 
Effective Java - Generics
Effective Java - GenericsEffective Java - Generics
Effective Java - GenericsRoshan Deniyage
 

What's hot (20)

SOLID Java Code
SOLID Java CodeSOLID Java Code
SOLID Java Code
 
Elements of Java Language - Continued
Elements of Java Language - Continued Elements of Java Language - Continued
Elements of Java Language - Continued
 
Control statements
Control statementsControl statements
Control statements
 
Java Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and PitfallsJava Generics Introduction - Syntax Advantages and Pitfalls
Java Generics Introduction - Syntax Advantages and Pitfalls
 
Java Persistence API
Java Persistence APIJava Persistence API
Java Persistence API
 
Beyond PITS, Functional Principles for Software Architecture
Beyond PITS, Functional Principles for Software ArchitectureBeyond PITS, Functional Principles for Software Architecture
Beyond PITS, Functional Principles for Software Architecture
 
Static program analysis tools
Static program analysis toolsStatic program analysis tools
Static program analysis tools
 
ORM JPA
ORM JPAORM JPA
ORM JPA
 
Java generics final
Java generics finalJava generics final
Java generics final
 
Unit I Advanced Java Programming Course
Unit I   Advanced Java Programming CourseUnit I   Advanced Java Programming Course
Unit I Advanced Java Programming Course
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015
 
Finding bugs that matter with Findbugs
Finding bugs that matter with FindbugsFinding bugs that matter with Findbugs
Finding bugs that matter with Findbugs
 
Session 08 - OOP with Java - continued
Session 08 - OOP with Java - continuedSession 08 - OOP with Java - continued
Session 08 - OOP with Java - continued
 
Oop objects_classes
Oop objects_classesOop objects_classes
Oop objects_classes
 
Interfaces and abstract classes
Interfaces and abstract classesInterfaces and abstract classes
Interfaces and abstract classes
 
Sql Patterns
Sql PatternsSql Patterns
Sql Patterns
 
Lecture - 5 Control Statement
Lecture - 5 Control StatementLecture - 5 Control Statement
Lecture - 5 Control Statement
 
Java Programming - 03 java control flow
Java Programming - 03 java control flowJava Programming - 03 java control flow
Java Programming - 03 java control flow
 
9781111530532 ppt ch10
9781111530532 ppt ch109781111530532 ppt ch10
9781111530532 ppt ch10
 
Effective Java - Generics
Effective Java - GenericsEffective Java - Generics
Effective Java - Generics
 

Similar to Cleaner Code - CodeStock 2019 Edition

Refactoring - improving the smell of your code
Refactoring - improving the smell of your codeRefactoring - improving the smell of your code
Refactoring - improving the smell of your codevmandrychenko
 
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)Ovidiu Farauanu
 
Functions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupFunctions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupSyedHaroonShah4
 
Introduction to design_patterns
Introduction to design_patternsIntroduction to design_patterns
Introduction to design_patternsamitarcade
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)Jose Manuel Pereira Garcia
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987乐群 陈
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2Leonid Maslov
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Andrzej Jóźwiak
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Programming in java basics
Programming in java  basicsProgramming in java  basics
Programming in java basicsLovelitJose
 
Design patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjsDesign patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjsRavi Bhadauria
 
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdfbreaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdfVishalKumarJha10
 
Intro to object oriented programming
Intro to object oriented programmingIntro to object oriented programming
Intro to object oriented programmingDavid Giard
 

Similar to Cleaner Code - CodeStock 2019 Edition (20)

Refactoring - improving the smell of your code
Refactoring - improving the smell of your codeRefactoring - improving the smell of your code
Refactoring - improving the smell of your code
 
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
 
Functions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupFunctions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrup
 
Introduction to design_patterns
Introduction to design_patternsIntroduction to design_patterns
Introduction to design_patterns
 
02basics
02basics02basics
02basics
 
Oops concept
Oops conceptOops concept
Oops concept
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
Programming in java basics
Programming in java  basicsProgramming in java  basics
Programming in java basics
 
Design patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjsDesign patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjs
 
Classes1
Classes1Classes1
Classes1
 
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdfbreaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
 
Intro to object oriented programming
Intro to object oriented programmingIntro to object oriented programming
Intro to object oriented programming
 
DS Unit 6.ppt
DS Unit 6.pptDS Unit 6.ppt
DS Unit 6.ppt
 
MDE in Practice
MDE in PracticeMDE in Practice
MDE in Practice
 
Structured Languages
Structured LanguagesStructured Languages
Structured Languages
 

Recently uploaded

BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxalwaysnagaraju26
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfryanfarris8
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfayushiqss
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456KiaraTiradoMicha
 

Recently uploaded (20)

BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide Deck
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 

Cleaner Code - CodeStock 2019 Edition

  • 1. Cleaner Code How Clean Code is Functional Code Dave Fancher Vibenomics Lead Software Engineer @davefancher dave@davefancher.com
  • 2.
  • 4. We know it when we see it…
  • 6. Some of us are born with it. Some of us have to fight to acquire it.
  • 7. clean code is code that clearly communicates with the reader
  • 8. clean code lets us better reason about the code
  • 9. "Writing clean code requires the disciplined use of a myriad of little techniques applied through a painstakingly acquired sense of 'cleanliness'." The Art of Clean Code?
  • 10.
  • 11. Clean Code is a baseline series of guidelines for writing maintainable code
  • 12. Subjective Guidelines • Naming conventions • Comment style • Additional documentation • Etc…
  • 13. The subjective guidelines are important. We don’t care about them today.
  • 14. Objective Guidelines • Data/Object Anti-Symmetry • Single responsibility • Don't have side effects • Limit number of parameters • Use of whitespace • Don't pass/return null • Etc…
  • 15. Clean code is functional code
  • 16. If it compiles, it’s correct. Functional Programmers
  • 17. Control Side Effects Favor Expressions over Statements Treat Functions as Data 3 Themes of Functional Programming
  • 20. "Functions should do one thing. They should do it well. They should do it only." Do One Thinghttp://bit.ly/UbqcZr
  • 21. public static PersonModel SavePerson (PersonModel model) { // Validate the model // … // Transform the model to fit the database model // … // Write the change to the database // … // Audit the change // … // Return the updated model // … }
  • 22. public static PersonModel ValidateModel(PersonModel model) { /* .. */ } public static PersonModel StandardizeModel(PersonModel model) { /* .. */ } public static PersonModel PersistModel(PersonModel model) { /* .. */ } public static void AuditChange(PersonModel model) { /* .. */ } public static PersonModel SavePerson(PersonModel model) { var validatedModel = ValidateModel(model); var entity = StandardizeModel(validatedModel); var storedEntity = PersistModel(entity); AuditChange(storedEntity); return storedEntity; }
  • 23. public static PersonModel ValidateModel(PersonModel model) { /* .. */ } public static PersonModel CanoncalizeModel(PersonModel model) { /* .. */ } public static PersonModel PersistModel(PersonModel model) { /* .. */ } public static void AuditChange(PersonModel model) { /* .. */ } public static PersonModel SavePerson(PersonModel model) => model .Pipe(ValidateModel) .Pipe(CanoncalizeModel) .Pipe(PersistModel) .Tee(AuditChange);
  • 24. // Imperative Approach public static PersonModel SavePerson(PersonModel model) { var validatedModel = ValidateModel(model); var entity = CanoncalizeModel(validatedModel); var storedEntity = PersistModel(entity); AuditChange(storedEntity); return storedEntity; } // Declarative/Functional Approach public static PersonModel SavePerson(PersonModel model) => model .Pipe(ValidateModel) .Pipe(CanoncalizeModel) .Pipe(PersistModel) .Tee(AuditChange);
  • 25. // JavaScript! const { PIPE, TEE } = require("./pipeline"); const savePerson = model => model [PIPE](validateModel) [PIPE](canoncalizeModel) [PIPE](persistModel) [TEE](auditChange);
  • 27. [DllImport( "user32.dll", EntryPoint = "CreateWindowExW", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] public extern static IntPtr CreateWindow( int dwExStyle, string lpClassName, string lpWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lParam);
  • 28. Function Classification Niladic 0 Arguments Monadic 1 Argument Dyadic 2 Arguments Triadic 3 Arguments Polyadic 4+ Arguments
  • 29. .NET Generic Delegates Non-returning Returning Niladic Action Func<U> Monadic Action<T> Func<T, U> Dyadic Action<T1, T2> Func<T1, T2, U> Triadic Action<T1, T2, T3> Func<T1, T2, T3, U> Polyadic Action<T1, T2, T3, T4> Func<T1, T2, T3, T4, U> + 12 more…
  • 30. More Functional Notation Non-returning Returning Niladic Unit  Unit Unit  U Monadic T  Unit T  U Dyadic (T1, T2)  Unit (T1, T2)  U Triadic (T1, T2, T3)  Unit (T1, T2, T3)  U Polyadic (T1, T2, T3, T4)  Unit (T1, T2, T3, T4)  U …and so on
  • 31.
  • 32. ”Side effects are lies" Have No Side Effects
  • 33. public static void SaveInvoice (InvoiceModel model) { // Validate the model // Transform the model to fit the database model // Remove discounts // Write the change to the database } public static void ApplyDiscounts (InvoiceModel model) { // Calculate invoice total // Calculate total discount // Deduct discount from total // Update database again } public static void ChargeCustomer (InvoiceModel model) { // SaveInvoice(model); // ApplyDiscounts(model); }
  • 34. When a function relies upon external state or changes shared state the only valid answer to the question “What does this function do?” is “I don’t know…” Me
  • 36. The Power of One: Functions should accept exactly one input and return exactly one output
  • 37. Function Classification Niladic 0 Arguments Monadic 1 Argument Dyadic 2 Arguments Triadic 3 Arguments Polyadic 4+ Arguments
  • 38. Function Classification Niladic 0 Arguments Monadic 1 Argument Dyadic 2 Arguments Triadic 3 Arguments Polyadic 4+ Arguments
  • 39. Functional Notation Non-returning Returning Niladic Unit  Unit Unit  U Monadic T  Unit T  U Dyadic (T1, T2)  Unit (T1, T2)  U Triadic (T1, T2, T3)  Unit (T1, T2, T3)  U Polyadic (T1, T2, T3, T4)  Unit (T1, T2, T3, T4)  U …and so on
  • 40. Functional Notation (Revised) Non-returning Returning Niladic N/A N/A Monadic N/A T  U Dyadic N/A N/A Triadic N/A N/A Polyadic N/A N/A …N/A
  • 42. What about out parameters?
  • 43. // C# int value; // Ugh. Unintialized variable if (Int32.TryParse(“124”, out value)) { // Success } if (Int32.TryParse(“abc”, out value)) { // Never going to run } // F# - wraps out and return values in tuple match Int32.TryParse(”124”) with | true, value -> // Success | false, _ -> // Failure
  • 44. Multiple Returns • Dijkstra's Rules for Structured Programming • A block should have only one entry and one exit
  • 48. // Adapted from Clean Code: Page 86 private void measureLine(String line) { lineCount++; int lineSize = line.length(); totalChars += lineSize; lineWidthHistogram.addLine (lineSize, lineCount); recordWidestline( lineSize); } private void recordWidestLine (int lineSize) { // Do something }
  • 49. “A source file is a hierarchy rather like an outline” Indentation
  • 50. // Adapted from Clean Code: Page 86 private void measureLine(String line) { lineCount++; int lineSize = line.length(); totalChars += lineSize; lineWidthHistogram.addLine(lineSize, lineCount); recordWidestline(lineSize); } private void recordWidestLine(int lineSize) { // Do something }
  • 52. Data/Object Anti-Symmetry Objects • Hide their data behind abstractions • Expose functions to operate on that data Data Structures • Expose their data • Have no meaningful functions
  • 53. // Adapted from Figure 6-6 // Polymorphic Shape Interface Shape { double area(); } public class Square implements Shape { // fields public double area() { /* … */ } } public class Rectangle implements Shape { // fields public double area() { /* … */ } } public class Circle implements Shape { // fields public double area() { /* … */ } }
  • 54. // Adapted from Figure 6-5 // Procedural Shape public class Square { /* … */ } public class Rectangle { /* … */ } public class Circle { /* … */ } public class Geometry { public double area (Object shape) { if (shape instanceof Square) { /* … */ } else if (shape instanceof Rectangle) { /* … */ } else if (shape instanceof Circle) { /* … */ } throw new NotSupportedException(); } }
  • 55. In functional programming we typically favor data structures to objects
  • 56. // F# Example // Discriminated Union and Pattern Match type Shape = | Square of topLeft: Point * side: double | Rectangle of topLeft: Point * height: double * width: double | Circle of center: Point * radius: double let area shape = match shape with | Square(_, side) -> side * side | Rectangle(_, height, width) -> height * width | Circle(_, radius) -> Math.PI * (radius * radius)
  • 58. “I call it my billion-dollar mistake. It was the invention of the null reference in 1965.” Tony Hoare
  • 59. Clean Code Guidance Don’t Pass Null Don’t Return Null
  • 60.
  • 62. No matter what language you work in, programming in a functional style provides benefits. You should do it whenever it is convenient, and you should think hard about the decision when it isn't convenient. John Carmack
  • 63. THANK YOU! Dave Fancher Vibenomics Lead Software Engineer @davefancher dave@davefancher.com

Editor's Notes

  1. Clean Code is a collection of guidelines for writing maintainable code Focused on Java but applicable anywhere I’ve read several times at different points of my career Thought about it differently at each point but the guidelines always made sense/resonated with me I often found I was already following many of the guidelines My reasons for why they made sense and my understanding of them often evolved with each read Today we’ll talk about what I’ve realized about the guidelines and how they affect the code I write today
  2. Before we start discussing how clean code is functional code it’s useful to reflect upon what the phrase “clean code” means
  3. Bob calls our ability to recognize clean code our “Code Sense”
  4. Martin says…
  5. Overall definition is subjective but to me it ultimately boils down to code that clearly communicates its intent as much as it solves problems. Why write clean code? Why is clean code important?
  6. When we write clean code we can better reason about what the code is doing and be assured that it is doing only what it says it’s doing To help develop your code sense ask: can I reliably predict the code’s output?
  7. The ability to recognize clean code is important but knowing how to write clean code is even more important. When I studied foreign languages in school I never seemed to have a problem reading the languages. I built up my vocabulary but I constantly struggled with conjugations and sentence composition. I knew the meaning behind the words I was looking at. I could understand but I couldn’t converse in those languages. Grunting and pointing only gets us so far! Code is the same way. What good is reading clean code if we can’t also write it and keep our overall systems maintainable over time? “Dirty” code is a lot like grunting and pointing. It can work but it’s error prone.
  8. We are authors. It is our job to ensure that what we write communicates effectively to both the machine and the future maintainers. Just as traditional authors develop their story telling techniques we develop our own “code sense”. We learn to inherently distinguish between clean and dirty code. We pick up a series of techniques which we employ to better achieve our goal of clearly communicating about the problem the code is attempting to solve. Sometimes we formalize those techniques into patterns but ultimately, particularly in the OO world those patterns exist to address fundamental issues with the technology.
  9. Igal Tabachnik’s tweet from Christmas of 2018 captures some of my thoughts on that nicely.
  10. The Book Clean Code gives us a solid foundation for writing maintainable code by defining a number of guidelines that have proven useful over time.  It accelerates developing our code sense by leveraging the lessons others have learned the hard way. Like any group of guidelines those provided in the book are either subjective or objective.
  11. Most of the subjective guidelines are about being consistent or providing additional information that is not expressed directly in the code
  12. The subjective guidelines definitely help make our code more understandable but they’re not things our tooling can do much about. We care about the objective things that our tools can reliably enforce.
  13. Individually these guidelines help us write clean code but when we examine them together a theme emerges…
  14. That is, by following the various objective guidelines we’ll naturally find ourselves programming in a functional style. I came to understand this when I started exploring and using functional languages about 5 years ago. Programming in a functional style is something we can do in virtually any language. My Functional journey started with LINQ and then F# but I’ve successfully applied the style to C# and JavaScript! Where things get interesting is that functional languages often take these guidelines to the next level by actively enforcing them with their structure and syntax. In fact, by their very nature, code written in a functional language is generally more correct in the mathematical sense.
  15. When I began working with functional languages I came across variations of the phrase “if it compiles, it’s correct” This is a bit of an exaggeration but because functional languages often include mechanisms to make representing illegal states impossible this eliminates all sorts of error categories. We don’t necessarily gain these benefits in non-functional languages but we can certainly guide ourselves there. By writing in a functional style we can more naturally reap many of the rewards offered by functional languages. But when we say “Clean Code is functional code,” what do we mean?
  16. The definition of functional programming is rather nebulous but to me it boils down to three central themes Clean Code’s objective guidelines are typically enforced naturally by the functional style. Default or even required immutability controls side effects Treating flow-control statements as expressions and forcing return values makes us favor expressions Curried and higher-order functions make us think of functions as data Let’s dive in to how the various guidelines discussed in Clean Code naturally guide us to programming in a functional style and ultimately to functional languages
  17. What better place to start discussing how clean code is functional code than with functions? Martin devotes Chapter 3 to the subject Functions are foundational to nearly all programming. When I teach new programmers I tend to spend more time on functions than most other concepts. I stress their importance because they’re so fundamentally critical. If one does not understand the nature of functions then one cannot effectively compose solutions from them. The quality and composability of our functions dramatically affects the quality of the overall solution. From here on I’m going to use the term ”function” generically and apply it to anything function-like. I was once in a curriculum planning meeting for a C# course and used the term “function” instead of “method”. One of the other committee members proceeded to lecture me that C# doesn’t have functions. Bullshit. Methods are simply functions with external context so I’ll be using that term. Anyway…
  18. Literally the first sub-heading in the chapter and is the foundation of virtually everything else regarding functions. Functional programming doesn’t necessarily enforce small functions but it certainly encourages them. Why?
  19. Single-responsibility. The “S” in ”SOLID”. Another of Bob Martin’s insights. Mark Seemann has an excellent article on this titled “SOLID: The Next Step is Functional” This theme permeates the book. When functions do only one thing we naturally have a better, more reliable understanding of what those functions do. And by focusing on one thing, our functions naturally tend to be small Let’s consider an example
  20. I’m sure we’ve all seen code like this. I’ve omitted the details beyond some comments but is this a good function? There’s a lot going on in here. Validations, transformations, persistence, and auditing all seem like separate concerns yet they’re all contained within the same function. This function is definitely responsible for more than one thing. It’s also difficult to devise abstractions or reuse the logic with it all locked away within this one function. [Guideline] Avoid #regions or sections If you can name a region you can name a function This encourages us to keep functions small and composable – a theme that recurs in functional programming. Smaller functions that do one and only one thing promote reuse through composition.
  21. How about this? Now each “named” section is moved to its own function and SavePerson now orchestrates the process without needing to be concerned with any of the details When functions are small and focused there’s less chance for them to do more than one thing. It’s also easier to identify points of failure through stack traces or other mechanisms. Notice how we no longer need the comments to identify what each part is doing? The code itself describes what’s going on. I like this better but there’s still quite a bit of noise in here. There’s redundancy between the function calls and the associated variables. What meaning or relevance does `validatedModel` have outside of the call to StandardizeModel?
  22. This is where composability comes into play. This version removes the duplicate information by using some higher-order functions (C# extension methods) to allow us to chain the calls into a single expression where the model flows through the series of operations. We can do this because the individual functions follow a particular pattern. Some languages like F# allow this naturally through pipeline operators but we can do this in any language that supports functions as data. Even JavaScript can do this with extended prototypes. Let’s look at these approaches together because there’s another important aspect here
  23. Notice how the code semantics have changed. In the top (imperative) version we emphasize syntax, variable declarations, and operations over the data. We’re essentially saying that the syntactic, programmatic constructs are more important than the problem the code is solving. The declarative/function version is significantly different. Now we’re emphasizing the input data by listing it first. This is typical in FP where we’re primarily concerned with inputs and outputs rather than individual operations. This is a major aspect of the Data/Object Anti-Symmetry that Martin discusses. Also, in the declarative/functional approach there’s less to mentally parse. The intent of the code is clear. We start with a model and watch each respective function’s return value “fall” through the operations until we get the desired result. This approach leaves much less opportunity to introduce lies when we rename one side of the assignment but not the other. All of the intermediate data is still represented but it’s tucked neatly away as return values flowing directly into parameters One final interesting aspect of this approach is that I can often show it to a non-technical person and not have them overwhelmed with technical details. Instead, the code clearly describes what’s happening.
  24. We can even do this in JavaScript! Here we import some Symbols from a module called pipeline. These symbols represent functions that have been attached to Object.prototype. Since Symbols are guaranteed to be unique we can safely extend the Object prototype without risking a collision. From there, the pattern seen previously in C# naturally emerges. We get the benefits of pipelining with minimal tradeoff. This pipeline pattern leads to another major Clean Code point…
  25. Yes, they are. They’re so hard that the terminology is confusing even in Clean Code. We’re really talking about “Parameters” here so I’ll use that term despite the book’s terminology. Parameters are a major contributor to software complexity.
  26. Just look at the signature of a Windows API function. Good luck remembering which parameter any given argument maps to! The problem is deeper than just this, however.
  27. Functions are classified by the number of parameters they accept. Martin asserts that 0 arguments is ideal. As a functional programmer I vehemently disagree with this because 0 arguments requires awareness of state external to the function. In OO terms, the external state is often referred to as ‘this’ but it often requires shared global state which is arguably even worse. Methods may be defined within the scope of a class but object state is still external to the method. As a side note, in JavaScript `this` is in fact an illusion. It’s actually an implicit parameter passed to the function which is why we can so easily change its context! Where Bob and I agree is with Clean Code’s guideline which states that there needs to be good reason to have more than 2 arguments and more than 3 requires “very special justification” and ”shouldn’t be used anyway” The rationale here is that more arguments makes functions more difficult to reason about. Let’s look at just how much complexity multiple parameters add to software.
  28. Consider the .NET generic delegates which allow us to represent functions as data in .NET. (See – functions as data; more functional programming!) In all there are 34 separate, incompatible data types. They’re each necessary because the primary .NET languages allow functions to be defined that way.
  29. From a more typical functional notation they’re still pretty ugly! Note that Unit indicates a function that has no particular return value. We’ll come back to that shortly.
  30. How do we as programmers reason about all these “things” passed into a function? Are all of them required? What is the result when all values are supplied? Is there a result? Let’s consider another related guideline then come back to this.
  31. Again, yes, they are. This is a core functional principle. Side effects often violate single responsibility The function signature promises one thing but does something else How can we tell that a function has a side effect? One easy way is that its return type is void. If a function doesn’t return anything then it must do something else. Why would you invoke a function that doesn’t do anything? Any function can hide side effects regardless of its return type.
  32. I once worked for a company that violated this guideline Consider this code which simplifies but still demonstrates the problem A colleague and I were tasked with identifying why some customer discounts weren’t being applied We verified that the discounts were on the invoice at the beginning of the process We verified that the discounts weren’t applied at the end We traced the code line-by-line looking for the problem An innocuous function named “SaveInvoice” or something like that was actually removing the data from the invoice prior to calculating the discount! “SaveInvoice” lied about what it did. Yes, it saved the invoice but it changed the invoice in a manner that broke a downstream process. This would have been MUCH easier to identify if the function did only the job it said it did and didn’t change the input in unexpected ways.
  33. Would you expect a function named “SaveInvoice” to change the invoice in any way? Should saving an invoice cause discounts to not be applied? I would hope the answer to both of these questions is ”No” because side effects cause unpredictability. Side effects make the code lie to us.
  34. In functional programming we refer to the presence or absence of side effects as functional purity. This has a lot in common with determinism and non-determinism. Pure functions are not dependent upon external state whereas impure functions are We should strive to remove as many impurities from our code as we can by giving our functions only the data they need and returning new data to the caller So how do the guidelines of limiting the number of parameters for our functions and requiring our functions to return something relate to functional programming?
  35. We see this pattern enforced in Haskell and the ML languages (ML, OCaml, F#, etc…) It may seem odd at first but it’s easy to achieve by wrapping related values into data structures that we pass as a whole. This allows composing functions such that the result of one function can be directly fed into the next. When we truly need additional parameters, we employ a technique called “currying” where functions are actually a series of closures. This has some profound effects on our code. We already saw one such effect with pipelining, but this idea is what makes that possible! How?
  36. Remember our function classifications that I said we’d return to?
  37. Most of them no longer apply when we follow the one input/one output guideline. That leaves us with only monadic functions!
  38. Which means that most of the signatures we looked at before are now irrelevant…
  39. …and those monadic functions all return something…
  40. …which leaves us with one function signature. This is MUCH easier to reason about. It also lets us make a variety of assumptions about the code that we couldn’t before. 1.) All functions accept “something” 2.) All functions return ”something” 3.) Single parameter encourages small, focused functions that do only one thing. 4.) Return values should be used for something. The compiler can generate a warning if a return value isn’t used 5.) Functions can easily be composed because they all follow the same pattern. This facilitates reuse. 6.) That consistency also allows for currying and partial function application (which we’re not talking about today) 7.) When functions are pure we get referential transparency When the language offers only single-parameter functions, the clean code rule is actively enforced! The “functional way” also allows us to be explicit about side effects while following the same pattern as everything else because the compiler can tell us when we forget to use a return value other than Unit!
  41. Out arguments should be avoided Arguments imply input to a function but an out argument violates that trust. Again, the code is lying to us!
  42. C# uses out parameters with common things like parsing integers from strings This causes “beautiful” things like uninitialized variables and scoping issues to creep into our code (yes, I know we have inline declarations now. Much code has already been written without them so we still have to deal with it) In the functional world, F# has no concept of out parameters even though the underlying runtime supports them. Functions like TryParse even require it. As a workaround the F# compiler wraps the TryParse call and returns both values as a tuple which we can pattern match against. This prevents the uninitialized variable and keeps values scoped appropriately. This is yet another case of the functional tooling enforcing a clean code guideline
  43. Martin argues that the rule offers little benefit in small functions True. But the pattern often naturally emerges with expression-based languages to the extent that the result of the last evaluated expression is automatically returned! Forces small, focused functions ML family of languages actively enforces this rule Predictable pattern I don’t require but I do encourage it
  44. Files == Articles File name == Headline High-level details at top More granular detail at the bottom I like this but ML languages flip the order such that things must be declared before they’re used. The clean code rule makes sense but the ML model is equally predictable, just upside down.
  45. Indentation? Really?
  46. Have you ever seen code that looks like this? I have I call it “Tim Code” because I worked with a guy who wrote code like this. It drove me crazy Which things belong together? Is the lineSize declaration subordinate to incrementing lineCount? How many functions are in here? This is not “glanceable” This is just two functions. Imagine file after file like this. My code sense tells me this is not clean code
  47. There is information contained within a file’s whitespace. The whitespace itself conveys information that’s lost when code isn’t indented consistently. We can see this idea in the three images. Each is a screen shot of the VS Code minimap for some files in my current project. Neither the language nor the content matters, only that the structure implies relationships. There are distinct blocks in each minimap and indentation is a critical part of that. We’re able to discern that structure without obvious syntactic elements like curly braces or BEGIN/END pairs. Whitespace is important and curly braces are redundant. Most editors can apply this formatting automatically for us with configurable rules but some languages, particularly functional languages, take it a step further and apply significance to whitespace. Scoping rules are enforced not by curly braces or other redundant characters but by indentation level. I’ve heard arguments that it gets confusing with several levels of nesting but I have a few issues with that: If we’re following the Clean Code guideline we’re already indenting so our practice isn’t changing How is it any more confusing than a chain of curly braces? If it’s confusing, separate the confusing bits into a new function By adding significance to whitespace, functional languages once again remove the need to rely on programmer discipline or other formatting tools and just naturally make us do it.
  48. And to close the loop, here’s the previous example formatted to be readable so we can make some sense of it. What a difference consistency makes. We can now clearly see two functions. We can even see related things near one another Much like the newspaper metaphor applies to the structure of our solutions, I like to think that code is prose-like where we group related lines in close proximity and separate concepts with additional whitespace.
  49. To be clear, Clean Code doesn’t promote one way over the other but I like to encourage data structures over objects This promotes decoupling data from behavior such that they can vary independently as needed. It also forces us to think of computation in terms of inputs and outputs rather than states and behaviors.
  50. This F# code corresponds directly with the procedural/data structure example except that the code is presented in its entirety using a discriminated union and pattern matching DUs are better than OO class hierarchies because as an algebraic data type we’re defining every possible value of type shape. I haven’t defined a Polygon type so if I defined a separate Polygon type it wouldn’t be valid input to the area function. Similarly, pattern matching is better than if or switch statements because if I ever add a case to Shape, the compiler will warn me about every place I forget to handle that new type because it knows what all of the valid values for Shape are. If I add a new Polygon case to Shape I’d have to add the pattern to the match expression to handle it otherwise I get a compiler warning. There’s no programmer discipline here, just the compiler doing its job and warning us of likely problems in the code.
  51. So much time goes into dealing with null We need to check for it virtually everywhere these days When we’re checking for null we’re writing plumbing code that’s not actively helping solve any real problem When we forget to check we risk introducing NullReferenceExceptions into our system Our customers are great testers, right? So much lost productivity Pan NREs Clean code gives us phenomenal guidance on this subject.
  52. We don’t return null because by doing so we introduce a potential NRE every time the function is evaluated. Favor a default value here. What harm is an empty list? Passing null essentially making us guess at default values to avoid NREs Just don’t use them or isolate them to the boundaries of your software. Better yet, use languages that don’t support them. F# supports null only because it has to work with the rest of .NET and we have to jump through hoops to circumvent its built-in protections. If the language doesn’t support the concept there’s no need to rely on discipline to prevent NREs from occurring. This is best summarized with my license plate…
  53. Clean code offers a series of guidelines to help us write code which in maintainable over a long period of time. Although many of the guidelines are subjective a great number of the objective guidelines actively guide us toward programming in a functional style regardless of which language we’re working with. When we’re disciplined about programming in a functional style in traditional OO or imperative languages we find that we naturally follow the clean code guidelines. What’s even better than that though is that when we program with many functional languages, discipline is replaced with active enforcement by the tools which naturally results in cleaner code.
  54. I’ll leave you with this thought from John Carmack who was addressing an audience of C++ programmers when he made this comment. John says: [Read the comment] His reasoning is that numerous flaws in software exist because we often don’t fully understand all the possible states that may exist in our systems. Managing state is incredibly complex so if we avoid state by applying functional principles, our code will be easier to reason about, easier to predict, and less prone to failure. Indeed, Functional code is clean code.