๐Ÿง  The Purpose of the What Class

๐Ÿง  Writing Functions That Read Like Thought — The Purpose of the What Class

At first glance, the purpose of the What class may not be immediately obvious. Why should we express a function declaratively by chaining .if(), .then(), .else() methods, rather than simply writing a sequence of if/else statements in plain JavaScript?

The answer lies in the ability to decouple the order of declaration from the order of execution. This subtle shift allows the business logic of a function to stand out, while pushing secondary concerns — preparation, validation, error handling — into a separate, orthogonal layer.


๐ŸŽฏ Business logic, front and center

Consider the following chain:

business
  .if(condA).else(escapeA)
  .if(condB).else(escapeB)
  .else(escapeC, errorC)
  .else(escapeError)

Here, the business logic is prominent. Error handling and early exits are expressed laterally, rather than cluttering the “happy path.”

The business logic itself can be written under the assumption that both condA and condB hold true, and that no error has been thrown. Yet this code remains at the top level, without being nested in layers of if statements or try/catch blocks. Even though the resulting function is computationally equivalent to a vanilla implementation, it becomes more readable and maintainable.

function businessVanilla(arg) {

  try {
    try {
      // Check condB
      if (condB(arg)) {
        // Check condA
        if (condA(arg)) {
          return business(arg);
        } else {
          return escapeA(arg);
        }
      } else {
        return escapeB(arg);
      }
    } catch (err) {
      if (err.message === errorC) {
        return escapeC(arg, err);
      }
      
      throw err;
    }
  } catch (err) {
    return escapeError(arg, err);
  }
}

We naturally think first about the simplest scenario — the happy path — and only afterwards about exceptions. What allows us to express code in the same order we form our thoughts.


Declaration ๐Ÿ†š Computation

It’s also worth noting that predicates like condA and condB may have side effects on the input object — preparing it for the main calculation.

Computationally, this preparation happens before the core logic. Conceptually, however, it is secondary. Functional programming makes it possible to align the order of declaration with the conceptual order, rather than the raw computational order.


๐ŸŒฑ Specialization through derived classes

The benefits of this declarative style become even more apparent when deriving specific classes from What. In many contexts, neither the preparation logic nor the escape functions need to be hard-coded. Derived classes can provide ready-made methods for both.

⚙️ Example: handling object properties

In a common scenario, a business function takes an object as input. Preparations may involve validating or setting property paths:


const h = new Handler(business)        
  .checking('user.password', escape)  // if 'user.password' is missing → escape

⚙️ Example: handling HTTP requests

Further specializations can even free the developer from writing escape functions.

In HTTP request handling, for example, a lateral escape can be defined with nothing more than an error code and a message. The handler can automatically send the response:


const h = new HttpHandler(business)
  .checking('req.user', 401, 'Unauthorized') // enough to implicitely define the escape function
  .preparingBody();                         // even code (422) and msg ("malformed request") can be omitted

Conclusion

By adopting a declarative approach, we can focus squarely on the business logic of the computation, while delegating preparation and error handling to a clean, orthogonal dimension.

This style not only makes functions easier to read and maintain, but also aligns code with the way we think: start from the straightforward case, then layer in exceptions.

Let’s write code that feels like thought.
— @fizzwiz ✨

Comments

Popular posts from this blog

✨ Bridging Natural Language and Code

๐Ÿงฑ v0.0.0-dev.1

⚡ Early vs. Late Restriction