Clean code is code that is easy to read, understand and maintain. It has certain objective characteristics like having single responsibility, avoiding side effects and limiting parameters. Clean code favors small, pure functions over statements with side effects. Functional programming principles like immutability and avoiding null also contribute to clean code. Data structures should expose just data while objects encapsulate data and expose functions to operate on it. Overall clean code follows conventions that make the intent of the code clear.
Cleaner Code: How Clean Code is Functional CodeDave Fancher
Since 2008 Bob Martin's seminal work "Clean Code" has been teaching developers a series of guidelines for writing maintainable code and improving software quality. While several of the guidelines such as naming conventions and comment style are highly subjective, the astute reader will notice that the remaining guidelines are actually quite objective. All too often, following the Clean Code guidelines is mostly a matter of developer discipline. Let's discuss how those objective guidelines improve code quality, how they often naturally arise when programming in a functional style, and how many functional languages actively enforce them thus eliminating the need to rely on discipline and naturally eliminate the complexities they address.
Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters.
Generics are a facility of generic programming that were added to the Java programming language in 2004 within version J2SE 5.0. They were designed to extend Java's type system to allow “a type or method to operate on objects of various types while providing compile-time type safety”
The Java collections framework supports generics to specify the type of objects stored in a collection instance.
In this core java training session, you will learn Exception Handling. Topics covered in this session are:
• Exception Handling
• Exception Class hierarchy
• Types of Exception
• Keywords for Exception Handling
For more information about this course visit on this link: https://www.mindsmapped.com/courses/software-development/learn-java-fundamentals-hands-on-training-on-core-java-concepts/
Die SOLID Prinzipien gehören heutzutage zum festen Handwerkszeug eines jeden Clean Code Developers. Java 8 enthält großartige Neuerungen und Sprach-Features, die aus der Sicht der SOLID-Prinzipien beleuchtet werden. Sie werden erfahren, in welchen Bereichen die Sprache uns Entwickler noch besser unterstützt und wie die JDK-Designer ihrerseits die SOLID-Prinzipien berücksichtigt haben.
Gehen Sie mit mir auf einen Streifzug durch die Java 8 Welt und lernen Sie die neuen Sprachfeatures SOLIDe kennen.
Cleaner Code: How Clean Code is Functional CodeDave Fancher
Since 2008 Bob Martin's seminal work "Clean Code" has been teaching developers a series of guidelines for writing maintainable code and improving software quality. While several of the guidelines such as naming conventions and comment style are highly subjective, the astute reader will notice that the remaining guidelines are actually quite objective. All too often, following the Clean Code guidelines is mostly a matter of developer discipline. Let's discuss how those objective guidelines improve code quality, how they often naturally arise when programming in a functional style, and how many functional languages actively enforce them thus eliminating the need to rely on discipline and naturally eliminate the complexities they address.
Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters.
Generics are a facility of generic programming that were added to the Java programming language in 2004 within version J2SE 5.0. They were designed to extend Java's type system to allow “a type or method to operate on objects of various types while providing compile-time type safety”
The Java collections framework supports generics to specify the type of objects stored in a collection instance.
In this core java training session, you will learn Exception Handling. Topics covered in this session are:
• Exception Handling
• Exception Class hierarchy
• Types of Exception
• Keywords for Exception Handling
For more information about this course visit on this link: https://www.mindsmapped.com/courses/software-development/learn-java-fundamentals-hands-on-training-on-core-java-concepts/
Die SOLID Prinzipien gehören heutzutage zum festen Handwerkszeug eines jeden Clean Code Developers. Java 8 enthält großartige Neuerungen und Sprach-Features, die aus der Sicht der SOLID-Prinzipien beleuchtet werden. Sie werden erfahren, in welchen Bereichen die Sprache uns Entwickler noch besser unterstützt und wie die JDK-Designer ihrerseits die SOLID-Prinzipien berücksichtigt haben.
Gehen Sie mit mir auf einen Streifzug durch die Java 8 Welt und lernen Sie die neuen Sprachfeatures SOLIDe kennen.
In this core java training session, you will learn Elements of Java programming. Topics covered in this session are:
• Elements of Java programming language
• Conditional Statements
• Loops
For more information about this course visit on this link: https://www.mindsmapped.com/courses/software-development/learn-java-fundamentals-hands-on-training-on-core-java-concepts/
An introduction to the Java Persistence API 2.x (JPA). Namely, this set of slides first introduces the problem of impedance mismatch between the object model and the relation model. Then, the EntityManager's public interface is discussed, together with the parallelism between a persistence context and a L1 cache. The issue of encapsulating the different application's use cases (which are exposed by the service objects) is solved by means of the @Transactional annotation, which provides a declarative way of demarcating the application's transactional boundaries. It follows an in-depth explanation on how to integrate a local, container-managed EntityManager within an existing Spring MVC application, so as to correctly support the propagation of the persistence context throughout the different beans involved in the same transaction. We then turn our attention to the problem of mapping relationships, thus introducing the @OneToMany, @ManyToMany and @OneToOne annotations. The additional topics of how to cascade operations and how to support lazy loading are covered as well. The presentation concludes with a discussion on how to use both the Criteria and Query API (and JPQL) to query the underlying database.
This talk introduces the core concepts of functional programming, why it matters now and how these principles are adopted for programming.
Beyond the usage of the functional principles for programming in the small, their applicability to the design of components and further on to the architecture of software systems is also explored along with relevant examples.
The code samples used in the talk are in Haskell / Java 8 / Scala / Elm and JavaScript, but deep understanding of any of these languages are not a pre-requisite.
Tools for automatic detection of static errors. While common tools work with source-code, this approach analyses Java byte-code. It discovers possible Java Linkage Errors such as NoSuchMethodError.
In this session, you will learn:
1. Deep dive into coding OOP with Java… with practical examples.
2. How to create a class
3. How to create objects
4. How to create instance variables
5. How to create class variables
6. Constructors
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)Ovidiu Farauanu
Discussing Design Patterns and OOP popularity,
Multithreading and OOP,
Functional Design for Multithreaded programming
and how Multithreading does not mean always concurency but multicore paralelism.
In this core java training session, you will learn Elements of Java programming. Topics covered in this session are:
• Elements of Java programming language
• Conditional Statements
• Loops
For more information about this course visit on this link: https://www.mindsmapped.com/courses/software-development/learn-java-fundamentals-hands-on-training-on-core-java-concepts/
An introduction to the Java Persistence API 2.x (JPA). Namely, this set of slides first introduces the problem of impedance mismatch between the object model and the relation model. Then, the EntityManager's public interface is discussed, together with the parallelism between a persistence context and a L1 cache. The issue of encapsulating the different application's use cases (which are exposed by the service objects) is solved by means of the @Transactional annotation, which provides a declarative way of demarcating the application's transactional boundaries. It follows an in-depth explanation on how to integrate a local, container-managed EntityManager within an existing Spring MVC application, so as to correctly support the propagation of the persistence context throughout the different beans involved in the same transaction. We then turn our attention to the problem of mapping relationships, thus introducing the @OneToMany, @ManyToMany and @OneToOne annotations. The additional topics of how to cascade operations and how to support lazy loading are covered as well. The presentation concludes with a discussion on how to use both the Criteria and Query API (and JPQL) to query the underlying database.
This talk introduces the core concepts of functional programming, why it matters now and how these principles are adopted for programming.
Beyond the usage of the functional principles for programming in the small, their applicability to the design of components and further on to the architecture of software systems is also explored along with relevant examples.
The code samples used in the talk are in Haskell / Java 8 / Scala / Elm and JavaScript, but deep understanding of any of these languages are not a pre-requisite.
Tools for automatic detection of static errors. While common tools work with source-code, this approach analyses Java byte-code. It discovers possible Java Linkage Errors such as NoSuchMethodError.
In this session, you will learn:
1. Deep dive into coding OOP with Java… with practical examples.
2. How to create a class
3. How to create objects
4. How to create instance variables
5. How to create class variables
6. Constructors
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)Ovidiu Farauanu
Discussing Design Patterns and OOP popularity,
Multithreading and OOP,
Functional Design for Multithreaded programming
and how Multithreading does not mean always concurency but multicore paralelism.
Esta charla comprende las lecciones aprendidas convirtiendo la app de Android de Teambox (una app repleta de deuda técnica y con un alto nivel de acoplamiento entre clases), en la versión actual de Redbooth, que intenta cumplir la arquitectura Hexagonal y los principios SOLID. Durante la exposición explicaremos como fuimos desenredando el código paso a paso; como aplicamos por partes los conceptos de la arquitectura hexagonal; como dejamos de lado componentes del framework de Android que dificultaban el mantenimiento de la app; y que errores cometimos, como los solucionamos y como se podrían haber evitado.
This is a toy compiler for the course Compiler 2016 at ACM Class, SJTU. The source language is Mx*. The target is MIPS assembly (in SPIM format).
You can refer to my presentation slides to know something about this compiler and also what I've learnt during the course.
Github: https://github.com/abcdabcd987/compiler2016
When debugging this compiler, I wrote another project LLIRInterpreter(https://github.com/abcdabcd987/LLIRInterpreter) which reads text IR and does interpretation.
Since these presentations were spare time hobby - I've decided to share them :)
Hopefully someone will find them useful.
This part continues 1. part with more design patterns like Command, State, NullObject.
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Andrzej Jóźwiak
Functional programming returned to the main stream after long years of hiatus. Languages like Haskell, Coq, Agda promise us better code just by using their advanced type systems. Although the dreaded null hides around every corner in Java is it possible to structure our code in a way that illegal states are not representable? Can the type system alone be enough for us to be sure that the code is correct? Do types mean that no tests are required?
During this talk, we will look at examples of code where the types control what code can be written (and there is no other way to do it). We will explore the possibilities to lower the number of unit tests or avoid some of them completely just by using the type system alone.
We will try to find an answer what stronger type systems can give us, what are dependent types and how could they look in Java.
Adding a modern twist to legacy web applicationsJeff Durta
Avoid misery of working with legacy code
We will see how you can add independent and isolated components to existing pages; pages that may be difficult to change
React and Flux allow you to make self-contained additions that handle their own data access/persistence
A seminar in advanced Software Engineering concerning using models to guide the development process, and QVT to transfer a model into another model automatically
Structured Languages- Need and Characteristics of OOP, Data Types and Modifiers, Arrays, Classes, Objects, Pointers, References, Difference between Pointers and References, Inheritance, Constructors, Destructors, and Polymorphism.
Similar to Cleaner Code - CodeStock 2019 Edition (20)
Listen to the keynote address and hear about the latest developments from Rachana Ananthakrishnan and Ian Foster who review the updates to the Globus Platform and Service, and the relevance of Globus to the scientific community as an automation platform to accelerate scientific discovery.
Check out the webinar slides to learn more about how XfilesPro transforms Salesforce document management by leveraging its world-class applications. For more details, please connect with sales@xfilespro.com
If you want to watch the on-demand webinar, please click here: https://www.xfilespro.com/webinars/salesforce-document-management-2-0-smarter-faster-better/
Innovating Inference - Remote Triggering of Large Language Models on HPC Clus...Globus
Large Language Models (LLMs) are currently the center of attention in the tech world, particularly for their potential to advance research. In this presentation, we'll explore a straightforward and effective method for quickly initiating inference runs on supercomputers using the vLLM tool with Globus Compute, specifically on the Polaris system at ALCF. We'll begin by briefly discussing the popularity and applications of LLMs in various fields. Following this, we will introduce the vLLM tool, and explain how it integrates with Globus Compute to efficiently manage LLM operations on Polaris. Attendees will learn the practical aspects of setting up and remotely triggering LLMs from local machines, focusing on ease of use and efficiency. This talk is ideal for researchers and practitioners looking to leverage the power of LLMs in their work, offering a clear guide to harnessing supercomputing resources for quick and effective LLM inference.
How Recreation Management Software Can Streamline Your Operations.pptxwottaspaceseo
Recreation management software streamlines operations by automating key tasks such as scheduling, registration, and payment processing, reducing manual workload and errors. It provides centralized management of facilities, classes, and events, ensuring efficient resource allocation and facility usage. The software offers user-friendly online portals for easy access to bookings and program information, enhancing customer experience. Real-time reporting and data analytics deliver insights into attendance and preferences, aiding in strategic decision-making. Additionally, effective communication tools keep participants and staff informed with timely updates. Overall, recreation management software enhances efficiency, improves service delivery, and boosts customer satisfaction.
Unleash Unlimited Potential with One-Time Purchase
BoxLang is more than just a language; it's a community. By choosing a Visionary License, you're not just investing in your success, you're actively contributing to the ongoing development and support of BoxLang.
Software Engineering, Software Consulting, Tech Lead, Spring Boot, Spring Cloud, Spring Core, Spring JDBC, Spring Transaction, Spring MVC, OpenShift Cloud Platform, Kafka, REST, SOAP, LLD & HLD.
OpenMetadata Community Meeting - 5th June 2024OpenMetadata
The OpenMetadata Community Meeting was held on June 5th, 2024. In this meeting, we discussed about the data quality capabilities that are integrated with the Incident Manager, providing a complete solution to handle your data observability needs. Watch the end-to-end demo of the data quality features.
* How to run your own data quality framework
* What is the performance impact of running data quality frameworks
* How to run the test cases in your own ETL pipelines
* How the Incident Manager is integrated
* Get notified with alerts when test cases fail
Watch the meeting recording here - https://www.youtube.com/watch?v=UbNOje0kf6E
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisGlobus
JASMIN is the UK’s high-performance data analysis platform for environmental science, operated by STFC on behalf of the UK Natural Environment Research Council (NERC). In addition to its role in hosting the CEDA Archive (NERC’s long-term repository for climate, atmospheric science & Earth observation data in the UK), JASMIN provides a collaborative platform to a community of around 2,000 scientists in the UK and beyond, providing nearly 400 environmental science projects with working space, compute resources and tools to facilitate their work. High-performance data transfer into and out of JASMIN has always been a key feature, with many scientists bringing model outputs from supercomputers elsewhere in the UK, to analyse against observational or other model data in the CEDA Archive. A growing number of JASMIN users are now realising the benefits of using the Globus service to provide reliable and efficient data movement and other tasks in this and other contexts. Further use cases involve long-distance (intercontinental) transfers to and from JASMIN, and collecting results from a mobile atmospheric radar system, pushing data to JASMIN via a lightweight Globus deployment. We provide details of how Globus fits into our current infrastructure, our experience of the recent migration to GCSv5.4, and of our interest in developing use of the wider ecosystem of Globus services for the benefit of our user community.
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...Juraj Vysvader
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I didn't get rich from it but it did have 63K downloads (powered possible tens of thousands of websites).
Enterprise Resource Planning System includes various modules that reduce any business's workload. Additionally, it organizes the workflows, which drives towards enhancing productivity. Here are a detailed explanation of the ERP modules. Going through the points will help you understand how the software is changing the work dynamics.
To know more details here: https://blogs.nyggs.com/nyggs/enterprise-resource-planning-erp-system-modules/
Quarkus Hidden and Forbidden ExtensionsMax Andersen
Quarkus has a vast extension ecosystem and is known for its subsonic and subatomic feature set. Some of these features are not as well known, and some extensions are less talked about, but that does not make them less interesting - quite the opposite.
Come join this talk to see some tips and tricks for using Quarkus and some of the lesser known features, extensions and development techniques.
Developing Distributed High-performance Computing Capabilities of an Open Sci...Globus
COVID-19 had an unprecedented impact on scientific collaboration. The pandemic and its broad response from the scientific community has forged new relationships among public health practitioners, mathematical modelers, and scientific computing specialists, while revealing critical gaps in exploiting advanced computing systems to support urgent decision making. Informed by our team’s work in applying high-performance computing in support of public health decision makers during the COVID-19 pandemic, we present how Globus technologies are enabling the development of an open science platform for robust epidemic analysis, with the goal of collaborative, secure, distributed, on-demand, and fast time-to-solution analyses to support public health.
First Steps with Globus Compute Multi-User EndpointsGlobus
In this presentation we will share our experiences around getting started with the Globus Compute multi-user endpoint. Working with the Pharmacology group at the University of Auckland, we have previously written an application using Globus Compute that can offload computationally expensive steps in the researcher's workflows, which they wish to manage from their familiar Windows environments, onto the NeSI (New Zealand eScience Infrastructure) cluster. Some of the challenges we have encountered were that each researcher had to set up and manage their own single-user globus compute endpoint and that the workloads had varying resource requirements (CPUs, memory and wall time) between different runs. We hope that the multi-user endpoint will help to address these challenges and share an update on our progress here.
GraphSummit Paris - The art of the possible with Graph TechnologyNeo4j
Sudhir Hasbe, Chief Product Officer, Neo4j
Join us as we explore breakthrough innovations enabled by interconnected data and AI. Discover firsthand how organizations use relationships in data to uncover contextual insights and solve our most pressing challenges – from optimizing supply chains, detecting fraud, and improving customer experiences to accelerating drug discoveries.
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
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);
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
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
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
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
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();
}
}
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)
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
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
Before we start discussing how clean code is functional code it’s useful to reflect upon what the phrase “clean code” means
Bob calls our ability to recognize clean code our “Code Sense”
Martin says…
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?
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?
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.
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.
Igal Tabachnik’s tweet from Christmas of 2018 captures some of my thoughts on that nicely.
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.
Most of the subjective guidelines are about being consistent or providing additional information that is not expressed directly in the code
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.
Individually these guidelines help us write clean code but when we examine them together a theme emerges…
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.
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?
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
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…
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?
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
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.
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?
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
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.
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…
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.
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.
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.
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.
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.
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.
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.
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.
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.
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?
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?
Remember our function classifications that I said we’d return to?
Most of them no longer apply when we follow the one input/one output guideline. That leaves us with only monadic functions!
Which means that most of the signatures we looked at before are now irrelevant…
…and those monadic functions all return something…
…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!
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!
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
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
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.
Indentation? Really?
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
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.
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.
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.
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.
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.
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…
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.
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.