Even though we write lot of functions daily we hardly pay attention how to improve our functions.
FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY.
Before giving attention to write an effective function you need to know what are the main points you need to take into considerations.
- Small!
- Blocks and Indenting
- Do One Thing
- Reading Code from Top to Bottom: The Stepdown Rule
- Use Descriptive Names
- Function Arguments
- Duplication
Small!
Function should be small. If you are thinking how small they can be, then I would say 2 lines or 3 lines or 4 lines long but these number of lines are not fixed though. You may consider these line numbers as a checkpoint like if your function has many lines make sure your function is not doing so many things.
Below example is from clean code book can be taken as reference:
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) { includeSetupAndTeardownPages(pageData, isSuite); } return pageData . getHtml(); }
Blocks and Indenting
Blocks within if statements, else statements, while statements, and so on should be one line long. Probably that line should be a function call. Not only does this keep the enclosing function small, but it also adds documentary value because the function called within the block can be a nicely descriptive name.
This also implies that function should not be large enough to hold nested structures. Therefore, the indent level of a function should not be greater than one or two. This, of course makes the functions easier to read and understand.
Do One Thing
Your function may have one line of code but doing many things at that line is not a efficient and optimised function.
For Ex:
return level4 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3) && (r.Level4 == (int)level4)).ToList() : level3 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3)).ToList() : level2 != null ? GetResources().Where(r => (r.Level2 == (int)level2)).ToList() : GetAllResourceList();
Similarly another example:
function build_address_list_for_zip($zip) { $query = "SELECT * FROM ADDRESS WHERE zip = $zip"; $results = perform_query($query); $addresses = array(); while ($address = fetch_query_result($results)) { $addresses[] = $address; } // now create a nice looking list of // addresses for the user return $html_content; }
In this function you are fetching record from database and generating html content and rendering it. So it can be split into two functions:
function fetch_addresses_for_zip($zip) { $query = "SELECT * FROM ADDRESS WHERE zip = $zip"; $results = perform_query($query); $addresses = array(); while ($address = fetch_query_result($results)) { $addresses[] = $address; } return $addresses; } function build_address_list_for_zip($zip) { $addresses = fetch_addresses_for_zip($zip); // now create a nice looking list of // addresses for the user return $html_content; }
Reading Code from Top to Bottom: The Stepdown Rule
We normally read like a top-down narrative. So when you are calling function inside another function definition then make sure to define the calling function below the function where it is called instead on top of that function:
Ex:
function getStudentInformation() { $this->getName($studentId); $this->getAge($studentId); } function getName($studentId){ // return student name } function getAge($studentId){ // return student age }
It should not be like this:
function getName($studentId){ // return student name } function getAge($studentId){ // return student age } function getStudentInformation() { $this->getName($studentId); $this->getAge($studentId); }
Use Descriptive Names
Don’t be afraid to make a name long. A long descriptive name is better than a short name which is difficult to understand.
A long descriptive name is better than a long descriptive comment.
Use a naming convention that allows multiple words to be easily read in the function names, and then make use of those multiple words to give the function name that says what it does.
Don’t be afraid to spend time choosing a name. Indeed, you should try several different names and read the code with each in place. As modern IDEs like Visual Studio, PhpStorm, JetStorm makes it trivial to change function names easily.
Function Arguments
The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification—and then shouldn’t be used anyway.
If your function is having more number of arguments then your function is doing one thing at a time. So check your code and split the functions doing one thing at a time.
Duplication
Duplication may be the root of all evil in software. Many principles and practices have been created for the purpose of controlling or eliminating it.
If you are writing large functions doing many things then there is more chance of having code duplication in different functions doing same thing which can be refactored by creating small functions. That small function can be invoked in different functions.
Conclusion:-
So check the above points to write an effective and efficient function which is easy for maintenance and can be tested well.
Hope you enjoy reading the blog and please like and share if you like it and what can be improved don’t hesitate to comment 🙂
Stay tune for more on clean and quality code writing.
References:-
Robert C.Martin Series: Clean Code Book
https://stackoverflow.com/questions/475675/when-is-a-function-too-long
Robert Martin also discuss when to use comments. He say’s “A comment is just an excuse for not writing a function”. Comments must be used sparsely. Instead of comments, write functions with descriptive names.
LikeLiked by 2 people
You are absolute right 🙂 Thanks!
LikeLike
Wow! Very useful post. Thanks for sharing 🙂
LikeLiked by 2 people
Thanks Brother for motivation 🙂
LikeLike