How to Evaluate Your Code Solution

What I found myself looking for when reviewing code


Preface

I ran across a post from a junior developer on the web. He was having disagreements with a senior developer about the validity of his proposed solutions. The junior developer’s essential ask in his post was how to tell if a solution is the right one for the situation. Most of the replies centered around “listen to the senior dev, he knows what’s best.” As a senior dev myself, I can assure you, we do not always know what’s best. I was frustrated that nobody gave him a real answer short of sit down, shut up and listen to big dev. We should be teaching new developers to think and evaluate for themselves. He was asking for those tools and that forum failed him.

So, I wrote the below in the hopes that a developer that needs it, finds it and adds it to their toolbox.

How to Evaluate

You were given a problem. You analyzed it. You distilled it down to just what the end user needs to have done. You then plopped down in front of the keyboard and punched out some code that you think just might do the trick. After some preliminary testing you think this might just work.

So, what happens next?

What happens next is very important in the development process. That period of time after you feel like you’ve solved this particular issue but before you’ve actually pushed the code up into the repository is a great time to evaluate what you’ve done. It is at this point that you have to ask yourself, did I do it right? Is my approach correct? Will my code contribute to a better, healthier product?

So, is your solution correct? If you’re lucky enough to work on a development team you may be thinking that it is time for some code reviews and peer feedback. But, before you get your team involved it would be good to go over your own checklist of whether your solution is the right one so that you respect their time.

The order in which these questions are answered and valued is certainly up for debate. The nature of your application will have a lot of influence on your evaluation process. Take these as a guideline and not hard and fast rules.

Does it work?

The first and most important question is: Does it work? When you run the code does it provide the desired output every time for every expected (and even unexpected) input? Does it work under strain or under load? Does it fail gracefully? And better yet, can you prove that it works?

If the answer is a resounding yes then proceed on. Because at the end of the day when the product ships, the most important aspect of the code is that it works. End users will tolerate a number of things, but software that just errors out or worse yet, produces unpredictable output is unacceptable.

Is it maintainable?

I believe this is the next most important question to ask. Unless you are launching a satellite into space with your software on it, there’s a very strong chance that you or another member of your team will be digging through this code in the future.

Software maintenance can be a very expensive proposition for companies. A quick fix may save a few minutes now, but down the road when a developer has to untangle your mess, the time saved is quickly lost.

What does maintainable code mean? Maintainable code means that your code is well organized and documented. It means that you’ve followed the paradigms of your product’s software philosophy and you’ve written the software with your team’s code styles firmly adhered to. Your doodads are with the other doodads. Your watchamacallits all inherit the same thingamajiggy interface. And so on.

If at all possible, your code should be as self documenting as possible. Organization trumps cleverness. From the names of your objects to the way you’ve grouped your methods, how you’ve actually written and organized your code is important. You are not just writing code, you are communicating with a future developer. You are letting him or her know how (and even why) you’ve solved the problem.

Maybe you’ve even left that future developer some tools to play with as a result. After all, that input sanitizer could be useful later on! So, taking that extra second to abstract it out might save a future developer some time when they augment the code.

Following concepts like DRY (Do not Repeat Yourself) and balancing composition vs inheritance fall under this evaluation.

Is it Secure?

For some software this may place significantly higher in the order of evaluations. In most situations this won’t register until the first two hurdles are passed. After all, who cares if it is insecure if it isn’t going to be pushed because it doesn’t work to begin with? As for the maintainability hurdle, poor coding practices almost always result in security vulnerabilities. And while good coding practices don’t necessarily mean strong security, frameworks and paradigms exist for a reason. Cleaner, more organized code also means problems are easier to find and correct.

Security is one of the more difficult checks to pass. It takes an extra effort to take another look at your methods and objects and try to see ways that they can used to expose the critical bits of information in your code base. You have to ask yourself, if I were trying to get to the important data, how would I exploit my code?

Walk through your user roles and examine the situation based on each of their permission sets. What data will they see and what will not see? Are those acceptable for each of those user’s roles?

Confer with your colleagues if possible. Much like proofreading your own writing, you can skip over and miss mistakes when evaluating for security.

Is it easy to use?

Does the user experience have direction and was that direction properly executed?

This is an often overlooked aspect of development. New features always feel like they are setting a new precedent and can be difficult to classify and deliver to a user. Often times the team around the developers are so happy to have the new feature that not much planning goes into how to present it to the end user. It could also be that the original concepts on how it should look and feel don’t pan out when actually implemented due to changes in layout by dynamic content or interface differences (tablet vs desktop).

The truth of the matter is that UX matters. A feature can function perfectly on the back end but if the user base doesn’t feel comfortable with the interface enough to use it (or even notice it), the feature may as well not exist.

The difficulty with UX for the average programmer is that it is hard to quantify a working design without getting it in front of the customer. With code you can plug in some inputs and examine the outputs and declare victory or defeat. Design is a lot less science and a lot more art, which can often lead developers to struggle in finding the right UX solution.

While in the end the developer is the one who puts the code into practice, the development of the end user experience should be bigger than his/her role. The process should have been started before bytes were committed to the hard drive. It is up to the developer to throw out the red flag and cry foul when a proper working model has not been achieved or agreed upon. It is then time to consult the other business units about the look and feel and intent of the software. It is very, very tempting to just push the issue under the rug, let whatever is cobbled together go into the repo and move on. Indeed, some corporate cultures make such discussions an uncomfortable experience for the developer.

Do not let it get swept under the rug. This issue, if present, is too important to dismiss.

Is it Performant?

Performance is last on the list for a reason. When pressed for time, the above goals need to happen for a successful feature launch. If a feature is merely a little slow, the show can go on. A patch may be needed later to correct glaring issues, but you can still make it to market. If worst comes to worst, hardware can be thrown at the issue. These are not ideal positions to be in, but they are manageable.

If your code is performing too slow for the end user to accomplish their task, then you haven’t passed the “Does it Work?” check. With this evaluation you are looking for problem areas and slowness that could be improved. Small updates to speed can have huge impacts in the aggregate. So, take a look around and see what you can trim down.

At this stage, you need to ask: Are you leaving some low hanging performance gains on the table? Are you requesting just the data that you need from the database and other outside systems? Are you looping through information you don’t need? Are you unnecessarily hitting functionality that requires more resources than you think? Is your code suffering from memory leaks?

Having a strong grasp of your chosen language will really help you develop an eye for performance problems. However, no amount of mastery beats solid debugging and performance analysis tools.

Recap

Does it work? Is it Maintainable? Is it Secure? Is it easy to use? Is it Performant?

If all of the above questions are able to be answered adequately then now is a good time to commit your code and allow it to move onto the next step in the process. A code review is the ideal next step. It is preferable for this change set to pass all of the above. If for some reason the process needs to be cut short, evaluate as many of these questions as you can in order of importance.

Refinement

After a while the questions will become second nature. As they become more familiar try to incorporate them earlier in the development process. Experienced developers will plan out a solution and run through these questions before even opening a file.

Look for new tools to help you answer these questions. Consider comparing notes with other developers or researching standard techniques for a particular problem space. Never stop learning.

Email me when Cris Bettis publishes or recommends stories