Nested Ternaries Patternmore_vert

Jonathan Martin's Explanation

Nested Ternaries Patternclose

Typically, if-else statements could be described with switch statements, except for the cases where test conditions could not be described with strict equality.

Ternary operator is essentially an if-else "expression". While "if-else statement" runs statements but doesn't return anything, a "ternary expression" evaluates and returns a value of one of the two expressions.

Syntax of "ternary expression" is just a side benefit. The real benefit:
- "if-else statements" are popular in imperative programming which is build on conrol flow. Such code tends to have several entry and exit points.
- "ternary expressions" help us think about data flow and produce more declarative code. Such code tends to flow in the same way for any inputs.

Router Patternmore_vert

Jonathan Martin's Explanation

Router Patternclose

Router pattern helps us turn a giant if-else/switch statement inside out by decoupling the responsibility of routing logic from the business logic of the individual cases.

With "Router pattern" the control flow is replaced with a data structure - many problems that traditionally solved algorithmically can be described much more elegantly with a data structure. In backend terminology, "responses" are "routes" and "responder" is "router".

"Router pattern" helps us discover common needs across if-else/switch cases and provides a flexible interface to DRY them up. With each case extracted into a function, we could unit test each response without going through routing logic first.

"Router pattern" helps solve the same problems in FP that polymorphism does in OOP.

Enforcer Patternmore_vert

Jonathan Martin's Explanation

Enforcer Patternclose

Terse, non-cascading if-else statements that get copy-pasted across functions, often appear at the beginning of a function as a guard clause.

Enforcer Pattern is Higher-Order Function with a guard clause that enforces some authorization rule, like requiring the word “sudo” or checking if the current user is an admin.

It’s as though we’re writing immutable code, and like immutable data structures, this style of coding has great design benefits and prevents regressions. None of our existing unit tests will change, and the new code already follows the single responsibility principle.

Error Handling Patternmore_vert

Jonathan Martin's Explanation

Error Handling Patternclose

If we take advantage of currying, we can eliminate a lot of the extra function calls and argument gathering.

This style of creating functions without first gathering and passing around all their arguments is called Point-free style (or Tacit Programming).

The best way to combine behaviors is through composition. Rather than cascading if-else statements, complex multiple error handling logic, or try-catch syntax, we handled two kinds of errors through composition.

Null Object Patternmore_vert

Jonathan Martin's Explanation

Null Object Patternclose

Each line of code could be defensive because it can’t safely trust the results of lines before it. With the variation of the Null Object Pattern, we can replace edge cases with benign values. Once we did that, the boundaries became detangled.

By substituting a benign value as early as possible, we don’t have to be defensive later on. In OOP, this benign value is called a Null Object. It’s often a subclass of the expected object type, and should respond to the same messages.

In FP we won’t create a Null Object class, but we can still lift this Null Object into a variable called nullPayload to better communicate intent.