Code Style Terror III — How deep is your code?

Nuno Grilo Pinheiro
Code Style Terror
Published in
3 min readJun 27, 2016

Best feature of Java 8? Lamdas!

Worst Feature of Java 8? Lambdas!

Best feature of ES6? Arrow functions!

Worst Feature of ES6? Ok, you guessed it, arrow functions!

Small code is good code!?

I really love lambdas, not because of their tiny little shiny syntax, but because of what they represent: They are pieces of code that can be assigned to variables, passed as arguments to functions, etc. Although this was already possible in Java (before 8) using the strategy pattern, the lambda syntax and the method references really favor this style of programming due to the simplicity of the syntax.

What makes lambdas the worst feature of Java 8 is not the lambdas per se, but the usage given by the community. Writing all the logic in the same line is so easy, that this programming style is turning into a trend, but just because you can put everything in the same line, it does not mean you should!

People usually use small LOC (Lines of Code) as a programming language quality measure, but measuring the quality of a code block based on LOC makes as much sense as measuring productivity based on LOCs.

Only if it was a lambda problem

As I said, it is not a lambda problem. Other scenario were code gets really complex, is in fluent interfaces.

Fluent interfaces are methods which can be chained in the same line to provide better readability. And they do make code easier to read! Until the programmer decides to put complex logic or structures inside of the method calls.

Fluent interfaces usually go hand in hand with lambdas, turning it easier to create bad code. An example in several languages (e.g Java and Scala) are the map reduce operations over collections.

Real Cases

As a rule of thumb, if you have a lamda inside a lambda, it is not easy to read!

Other big issue I see here is the fact that there is a big block in the middle of a fluent interface chaining. When you arrive at the 10th line, you don’t remember that you were in a map call, so you will probably need to re-start reading from line 2. Unless your lambda block is defined inside the last method call in the chain, your probably should not use it.

Just a side note, although I changed some parts of the code to present it in this post, the name “x” was used for the variables...

db.collection(request.query.type).find({ “$text”: { “$search”: textToSearch }}, {“name” : 1}).skip(PAGE*PAGE_SIZE).limit(PAGE_SIZE)

One case where it is really easy to break readability with no lambdas involved is in MongoDB queries. The call to the find method, which first argument corresponds to the WHERE clause in the SQL world, usually brings a big-depth query object, and you either write everything in the same line, and can’t read the line, or you end up breaking the expression in multiple lines, losing the purpose of the fluent interface.

How to fix this?!

Solving this issue is really simple: Simply refactor your noisy parts into variables.

For instance, refactor your lambdas to a variable if they are complex and are in a filter clause. If you start the name of that variable with the “by” word, your code can be read as “filter(byComplexLogic)”.

The same happens to the MongoDB queries. Just refactor your find block into a variable and you will end up with the following line most of the time

db.collectionName.find(query, fieldsToReturn).skip(PAGE*PAGE_SIZE).limit(PAGE_SIZE)

If you are a Java developer, and you use Eclipse Java IDE, you can use the automatic refactoring commands. Personally, I am a addicted to “ctrl + 1” which, besides allowing me to automatically fix some errors, allows me to choose “extract to local variable/field/method/constant”.

What About You?

Have you ever been pursued by a Minotaur while you were lost in a maze of lambdas?

people.filter(person -> person.isYou()).map(you => you.pleaseComment(this.story).heart(this.story));

(Please comment or heart this story) :)

--

--