Please Use The Cascade Rule

Amongst all the hype of shiny new technologies, fashionable working practices and clever design patterns, sometimes I think the absolute basics of writing readable code are ignored or discarded as boring. I can’t think of a more saddening example than the unloved cascade rule.

Please can we use the cascade ruuuule?

We write code from left-to-right because we read left-to-right. Our eyes go from the left of the screen to the right, and then down to the start of the next line. It’s easy and comfortable because that’s how we read books and articles.

Logically, then, we should write code that reads from top-to-bottom since our brains are trained to read that way. That’s all there is to the boring-but-effective cascade rule. It makes code easier to read and I love it.

Surprisingly, though, when consulting with dev teams or pairing at meetups, I find there are a lot of programmers who don’t use the cascade rule. So in this brief post I’ll have a cheeky attempt at convincing you to use the cascade rule for the benefit of yourself and everyone else who has to read your code.

The Cascade Rule in Pictures

Let’s say we have a public method that calls three private methods. When thinking technically, it’s intuitive to put the private methods above the public method because we can’t call a method that hasn’t been defined (in the file) yet….

private List findBookRecommendationsFor(User user) {
...
}
private List findTvRecommendationsFor(User user) {
...
}
private List findMovieRecommendationsFor(User user) {
...
}

public Recommendations findRecommendationsFor(User user) {
List movieRecs = findMovieRecommendationsFor(user);
List tvRecs = findTvRecommendationsFor(user);
List bookRecs = findBookRecommendationsFor(user);
return new Recommendations(movieRecs, tvRecs, bookRecs);
}

Except, in most programming languages we can call methods before they are defined. And if we stop thinking technically and start thinking in terms of comprehensibility, it feels logical to call methods before they are defined. Our eyes can move down the page to view the implementation after they have seen the method being called.

I may think differently to you, but in addition to reading from top-to-bottom I feel more comfortable reading code from high-level to specifics. I want to understand why the code is doing something - what is the intent behind it (storing configuration settings) - before I see how it does that (e.g. pumping some text into a file). And this is why I think it's better to see invocations of a method before the implementation - the why before the how.

public Recommendations findRecommendationsFor(User user) {
List movieRecs = findMovieRecommendationsFor(user);
List tvRecs = findTvRecommendationsFor(user);
List bookRecs = findBookRecommendationsFor(user);
return new Recommendations(movieRecs, tvRecs, bookRecs);
}
private List findMovieRecommendationsFor(User user) {
...
}
private List findTvRecommendationsFor(User user) {
...
}
private List findBookRecommendationsFor(User user) {
...
}

Admittedly, you can train yourself to read up. And you’ll always have to move your eyes up the screen anyway even if you use the cascade rule. So in fairness, you could invert the cascade rule. However, I’d recommend to just standardise on top-to-bottom since it’s so natural.

Not a Fan of Nested-functions

I think nested functions - functions defined inside functions - are a hindrance to comprehensibility because they don't follow the cascade rule.def regularFunction() = {
def fiveLineNestedFunction(x: String) = {
...
}
def tenLineNestedFunction(y: Int) = {
...
}
// utilise nested functions
}

Nested functions are another example of putting the how before the what. When a function (or method) contains nested functions, I have to understand how the nested functions work before I understand what the parent function is doing. I find that makes it harder to mentally piece concepts together.

Admittedly I can jump over the nested functions if they’re all declared at the top of a function, but then why bother putting them there?

Nested functions in Scala are used liberally in some codebases. It's not uncommon to see 100+ line Scala functions with nested functions scattered around. But whichever language you use, why not just create a class with private methods and take advantage of the cascade rule?

Disagree?

I propose that we make the cascade rule the standard way of writing code. I think if programmers wrote code from top-to-bottom, where possible and sensible, code would overall be easier to read.

However, please tell me if my thinking does not align with yours. I’d love to know if different programmers have different preferences for laying out and reading their code.

Everyone I have recommended the cascade rule to has immediately begun to use it liberally. No-one has said they don’t like it or it’s a bad idea. But if you’re different I’d love to know in case I am making incorrect assumptions about other programmers.

--

--

Nick Tune
Strategy, Architecture, Continuous Delivery, and DDD

Principal Consultant @ Empathy Software and author of Architecture Modernization (Manning)