Clean Code Series- How to write Functions / Methods
Oct 20, 2021
Make sure to subscribe to our newsletter and be the first to know the news.
Oct 20, 2021
Make sure to subscribe to our newsletter and be the first to know the news.
Functions / Methods are the building block of any application. Without any doubt as per the programming language rule, you can understand that all the business logic goes directly inside the function. If you are very new to the programming, think of it in this way that every single piece of statement we write except for declaration actually goes inside the function / method
"Function / Method are the block of statements which are meant to perform a particular task and are grouped under a single name."
Want to know more about functions / methods, check out my article here.
While writing the methods, there are certain clean code factor which you should always follow
When it comes to methods Size does matter. The smaller the method it is better for readability and understanding. This is something I am talking with experience, while coding for one of the leading beverages company in spur of moment I thought I can complete a complex task in 2-3 hours and wrote everything inside a method which at the end measured for not less than 1543 lines and believe me, till this day I regret on not breaking up the codes into smaller blocks and as the block I had written was working fine but when we got error we use to break some sweat while debugging it then.
Ideally method size should be around 20 to 30 lines and should not exceed that. Try this and you will see how things turn out for you.
"Don't speak while you eat or Don't watch TV while you eat" I can bet that your parents atleast once in your life must have said this to you and there is a simple logic behind it. They want you to concentrate fully on eating and not disturbing your body pattern while eating as it is in a way harmful for you. Same way when you write a method it is always better to perform only a single task inside a method and avoid adding multiple tasks inside a single method, for example
public void loadFromFileAndAddInDB(String file)
{
try
{
File f=new File(file);
BufferedReader br=new BufferedReader(new FileReafer(f));
String data = br.readLine();
while (data != null)
{
data = br.readLine();
}
Connection con=DriverManager.getConnection(url,user,password);
String query="Insert into data values (?);";
PreparedStatement pstmt=con.prepareStatement(query);
pstmt.setString(1,data);
int result=pstmt.executeUpdate();
if(result==1)
{
System.out.println("Inserted");
}
else
{
System.out.println("Some issue");
}
}
catch(Exception e)
{
e.printStackTrace();
}
In the example above you can see that two task are performed inside a single method and which can create a lot of confusion. Hence better solution would have been to break into two methods of loadFromFile() and addToDB() like
// Method to load the data from file
public void loadFromFile(String file)
{
try
{
File f=new File(file);
BufferedReader br=new BufferedReader(new FileReafer(f));
String data = br.readLine();
while (data != null)
{
data = br.readLine();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
//Method to insert data in file.
public void addToDB(String data)
{
try
{
Connection con=DriverManager.getConnection(url,user,password);
String query="Insert into data values (?);";
PreparedStatement pstmt=con.prepareStatement(query);
pstmt.setString(1,data);
int result=pstmt.executeUpdate();
if(result==1)
{
System.out.println("Inserted");
}
else
{
System.out.println("Some issue");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
One of the biggest challenge faced while applying the Clean Code practices is choosing an appropriate and meaningful name. Same challenge arise when naming a method, simple rule is give a name with proper description which clarifies the intent of the method. Although we have seen that the size of the methods should be same but same doesn't apply on name of the methods. Write names descriptive enough that you don't need to write long comments just to explain. For example I am using a descriptive name for the method we have already declared in point 2
public void addToDataTable(String data)
{
try
{
Connection con=DriverManager.getConnection(url,user,password);
String query="Insert into data values (?);";
PreparedStatement pstmt=con.prepareStatement(query);
pstmt.setString(1,data);
int result=pstmt.executeUpdate();
if(result==1)
{
System.out.println("Inserted");
}
else
{
System.out.println("Some issue");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
As the method's only work is to add the data in the table by name Data , hence giving it a descriptive name actually make sense.
Arguments consume a lot of conceptual power while reading the code, it is always a smart way to keep the number of arguments lesser as number of arguments increases the complexity of code understand-ability. In fact method with no arguments is trivial as you basically make use of the local variables (one declared inside that very method) or instance variables (one declared inside the class we have been working) and they both are actually very much in familiarity with the developer.
Also in context to the testing, arguments are HEADACHES!! As it can make a code uncertain based upon the incoming arguments and it's effects on the whole module. So in short
Zero arguments are best
One argument is OK
Two arguments are still manageable
More than two arguments, needs a justification and shouldn't be allowed even after that.
Flag arguments are basically one which are marked as Boolean and are indicator of some event based on which action should be taken. In fact using a flag argument is an indicator that the function is actually doing more than one job. Better solution would be to break the method into parts to achieve that. For example
public void processTicket(boolean isDiplomat)
{
if(isDiplomat)
{
/*
statement for processing diplomats ticket
*/
}
else
{
/*
statement for processing regular traveller ticket
*/
}
}
Now you can see based on the incoming flag value we are integrating the work of two different methods into one. It would be preferable to split it into two
public void processTicketForRegularTraveler()
{
/*
statement for processing regular traveler ticket
*/
}
public void processTicketForDiplomat()
{
/*
statement for processing diplomat
}
Having side effects is worst. You take a tablet thinking it is going to cure your headache, it actually does but now your eyes are swollen as a result of side effect. Same can sometime happen with your function that you might include some piece of code which was not supposed to be the part of the actual job and end up getting side effects and it is tough to detect it in the debug mode.
For example
public void checkPassword(String username, String password)
{
if(username.equals(someValue) && password.equals(someValue))
{
System.out.println("Password is correct");
session.initialize();
}
}
Now here in the checkPassword() method session.initialize() is the code which can cause side effect, for example this method will work fine while logging in but let say based upon the name of the method a developer cal the same method during the change password process and unknowingly will clean up all the session data. So it is better to make sure that the method only perfoms those tasks which are described and nothing else.
So these were some basic rules which you need to follow while working with functions / methods.