One of the young engineers in my team asked me tips to be a good software developer. I am still learning myself, but here are my thoughts.
Understand what problem you are solving: Before you start working on a feature, no matter how small it is, take a moment to understand what is the actual problem you are solving. How will this feature address the requirements efficiently. Who is going to use this feature, know you customers. Wear their hat, and understand how and why your customers will use your software. How can you make their life easy. Suddenly, you will realize that you are not just implementing code but you have a purpose to help your customers to do their job well. This approach has always helped me in understanding the big picture and writing efficient code.
Pay attention to the For loops: For loops are well known to any coder. When you start writing a for loop, pay attention to that count variable. In today’s world, everything is big data. So, try to figure out, what can that count value be. Is the counter coming from a static list or are you fetching data from database. Most often, very big production issues happen, when developers ignorantly write code which iterates through all the records fetched from a database query. In production this list can easily become too big to fit in memory, bringing the production down with difficult OutOfMemory errors. Off course, the performance will be impacted if memory consumption goes high.These problems are easy to avoid but almost impossible to catch during quality process. Out of memory errors are difficult to debug in production, These lead to numerous hours spent in technical support. Remember with 99.99% availability, you can not afford to have production down scenarios. It is real money which is lost.
Keep you legacy behind: Always remember that the code you are writing is going to live there for a very long time if not forever. You may know the logic by heart now, but very soon you are going to work on another fancy feature. There will be team members who will enhance this code or fix bugs in it. When other people start working on it and find it difficult to understand, not well structured, they are not only going to curse you, they are also going to add more mess to this. Remember the broken window theory. Soon your legacy will become the legacy code which no one wants to touch but have to live with.
For any defect raised against the code, either you have to fix it yourself or other people will spend hours understanding it before they can fix one line to fix the actual issue. That one line of easy fix might break all hell loose.
Make it readable: This is my favorite part of the code. Coding is as much of art as math. If your code is not pretty (readable) then this code is not maintainable (read previous point). When another developer works on this piece of code, S/he should be able to read it like a design document. Small well named methods are your friends. Methods help avoid duplicate code as well as methods provide readability to the code. A method name should provide enough information about the purpose of the code and should do no more than that purpose. Such code is readable, easy to maintain and easier to enhance with less risk of additional mistakes. Comments are nice, but those get obsolete very soon if not maintained properly. While writing APIs, adding java docs is good practice.
Yes, int i and int j for variable names will do the same work as int numberOfPeopleInOrg. But soon your code will fill up with many many i,j,k…..and it will confuse you as much as anyone else while reading that document (code).
Keep it simple: I know the kick we get when we use a fancy new feature like anonymous static classes or lambda functions in the code. You do not need to overly complicate the code until you are actually leveraging the true power of such features or you are writing JVM level code ;). Most of the application development can be easily solved by simple, readable and clear code. Simple code is powerful. Simple code fulfills the three points mentioned earlier (Readable, Maintainable and Easy to debug)
Logging: I have seen many developers relying on debugger more than logs. Remember that when production issues happen, you don’t have the luxury of attaching a debugger. All you are given is dump of logs without actual source code in front of you. Appropriate and detailed log messages help you identify the problem easily. A log message like: “Number of objects: 10,000” does not provide any useful information. While a detailed message like: “Number of people fetched from db for project ‘abc’ are 10,000”, is much more informative in production. So make sure that log messages can tell you which part of the step is getting executed when failures occur. Please, do not try to print the entire lists in the log messages. Not only 10,000 objects printed in logs is useless it also makes the code run slow. I have seen this mistake specially while handling corner cases or failures in the code. A huge list of names does not help you analyze the failures by any means.
Exceptions: That part of the code which you thought will never happen, that corner case where you suppressed the exception thinking that’s a corner case which will never occur, that does happen in production. I have actually seen, “This should never happen!” messages in logs. When there are no stack traces in the logs, and exceptions are silently ignored, that’s when it takes the longest to solve the problem. So, handle the exceptions properly and remember those notorious Null pointer exceptions. Those are trivial to avoid in the code but it is embarrassing when you see those in the production logs.
This is not a list of one size fits all. I myself make some of these mistakes at times. Still, these guideline surely help me when I write or review code. There are ton of other coding practices you can read online. These are few tips which are easy to adopt but easier to ignore. Let’s start coding….