SLAP Your Functions!
Arun Sasidharan
May 13 '17
No-Brainer Functions
I’ll admit it, for the longest time I had no idea that a lot of thought goes into writing functions. For me, creating a function meant writing a block of code that is reusable. It’s a simple idea and it stuck with me, function == reusable code.
I had no notion of structure or length or meaning. With time, as the project grew, things started to look like long scripts. There was almost a pattern to these long functions with code and comments interleaving with each other.
Long Functions
Long functions are very costly:
- Hard to read and remember
- Hard to test and debug
- Conceal business rules
- Hard to reuse and lead to duplication
- Have a higher probability to change
- Can’t be optimized
- Obsolete comments
Long functions by design have very low cohesion and know too much about the system, high coupling. This is orthogonal to the fundamentals of software design which say components should have high cohesion and how coupling.
Single Level of Abstraction Principle(SLAP)
It’s difficult to judge if a function is long by counting the number of lines. Is 50 too long? What about 25 or 10? How small is small enough? This is where SLAP comes into play.
Code within a given segment/block should be at the same level of abstraction.
So the question is not how long a function is, it’s what is the level of abstraction of a function? A function should not mix different levels of abstraction. For ex. a function doing form validation should not make I/O calls.
As a thumb rule:
Functions should do just one thing, and they should do it well. — Robert Martin
Functions that do more than one thing face the same drawbacks as long functions. This rule becomes even more obvious when you start testing your code. It is so much simpler to test functions that do one thing as you don’t have to worry about all the complex permutations and combinations.
Compose Method Pattern
Often times when you have comments explaining blocks of code, they are candidates for function extractions.
When you use ExtractMethod a bunch of times on a method the original method becomes a ComposedMethod. It is composed of logical steps that read like the way we communicate and hide the implementation details.
Extract till you just can’t extract any more. Extract till you drop. — Robert C Martin
TL;DR
As Kent Beck said, divide your program into functions that perform one identifiable task. Keep all of the operations in a function at the same level of abstraction. This will naturally result in programs with many small functions, each a few lines long.
Originally posted on Hackernoon
Domain Driven Design for Android Developers
Android Gotchas: Mystic Debounce
Trending on dev.to
What are the hardest programming languages you have ever learned?
Which browsers should I try to support when creating a portfolio?
OOP 201: Design Concepts
What do you do in your two hours out of home?
What Components would be a most for microservice architecture?
Where do Software Architects, CTOs, and other Senior+ developers hang out?
Good keyboards matter.
I think I will leave my job, give me a advice.



137
9
Hi, nice article! While single level of abstraction is a useful concept, you are mixing it up with another concept here. The form validation vs. I/O example is about Separation of Concerns, as is the Bob Martin quote.
Having said that, long functions usually violate both principles and more.
Just extracting a commented part of a function into another one does not help to make it more readable, because now, to understand what it does, you have to jump around in your code. This mental contrxt switch makes it harder to read actually.
Of course you should avoid long functions. But do this by abstracting the problem, not the implementation!
Maybe, maybe not ...
Consider:
versus:
I find the second version much easier to understand :)
the first could be written:
Here the function is nothing more than specifying a name, you can do this in a comment
If you just add a comment, you still have to skim past all the implementation details to figure out what the function is intending to do. With this example this, since it's such a small function this isn't too burdensome but if the implementation is more complex, then that's a lot of noise to sift through to determine what the function does.
A primary component of properly breaking things up is to name the functions appropriately. Function names of "Block1" and "Block2" should have you hung outside for paintball practise!
I also like to remember that depending on the language in use the compiler may decide to put the code back into a single monolithic block for performance reasons. And sometimes that's important to remember.
Hey there, we see you aren't signed in. (Yes you, the reader. This is a fake comment.)
Please consider creating an account on dev.to. It literally takes a few seconds and we'd appreciate the support so much. ❤️
Plus, no fake comments when you're signed in. 🙃
One big advantage of this approach predictably is also writing more straight forward unit tests.