Introduction
We have been reading articles about how to architect / design a system, microservices etc. However, I still find that there are developers that require some details on how to write / create a method.
These are valid for statically typed languages like C# , Java which I have worked. though some of them apply to Javascript as a good practice.
Below are some of the points that I consider worth noting
- The method should have a descriptive verb of the action that it is performing.
- ReadFromConfigurationFile
- SaveUserData
- CheckInOrderPriorToPayment
2. The arguments if any to the method should be validated prior to consumption. There are some built-in types in Java that helps in checking for nulls like requireNonNull
from java.util
Note: The below given method is one that i had built which checks for null and empty value and if so, throws suitable exceptions. We have been using similar built-in functionality in Microsoft Enterprise Library
for .Net as Guard.Null
or Guard.NullOrEmpty
The validations ensure that the data is sane before consumption.
public String readFromFile(@NotNull @NotEmpty @NotBlank String fileName) throws IOException {
requireNonNullOrEmptyString(fileName, "The file name should not be null or empty");
}
3. If a method throws an exception, it should be documented in its signature as shown above for Java and in case of C#, they can be included in the comments so that the consumer of the method know possible exceptions and can plan accordingly.
4. When the method invokes another method, it is important to check the status of the result before consuming the data. Example
public User SaveUser(User userData) throws UserDataException {
String ssn = generateSSN(userData);
//Instead of using the ssn directly, we have to validate the value and then use as given below.
if(isNullOrEmptyString(ssn)){
throw new UserDataException(format("SSN Generation failed for the user:%s ",userData.Name));
}
userData.setSSN(ssn);
}
5. Any internal errors should be wrapped and thrown so as not to send out the internal details to the caller. Example
public User SaveUser(User userData) throws UserDataException {
try {
} catch(ConnectionTimedoutException connectionTimedoutException) {
log.error("Timeout exception occurred while saving the user data for :"+userData.getName(), connectionTimedoutException);
throw new UserDataException(....)
}
}
This will ensure that the internal error and sensitive details like the DB connection string, URL, etc are not exposed outside of the particular method.
6. Also note that, where ever, we are logging the messages, we are also trying to include the context of the call to the method, this ensures that there is some trace data that can be found so that the developer can identify what went wrong. In a very large system, the logs will have to include additional data like the requestId / correlation id etc to help the support team diagnose the details from the logs gathered.
Further, if required, the method marked as final indicating the object mutability to the caller.
I will try to write a blog on logging which can outline some of the best practices
Comments
Post a Comment