Forensic Programming – Implementing a Fix

"#53/366 Let Me Borrow" by Robert McGoldrick

“#53/366 Let Me Borrow” by Robert McGoldrick

After you have communicated with the client and understood the code, the last stage in the forensic programming process is implementing a fix. There are two important aspects to implementing a fix:

  1. Ensuring that the bug is squashed, and the client is happy
  2. Managing the risk of the fix

Making sure that the bug is squashed, is the self evident part of implementing a fix. You want to ensure that the code changes that you make fix the clients issue. The issue could be that the code doesn’t work as intended, or it could be that the code does work, but it doesn’t work the way the client wants. Either way the change that you make must solve the clients issue. 

What you don’t want is to implement what you believe is a fix, and then report back to the client. Only to have them test the code change to find that it doesn’t work. That just leads to embarrassment for you, and frustration for all.

The second element of implementing a fix isn’t as obvious. It’s all about managing the risk of the code change. There are a number of different types of risk. What you can’t do is yell something like ‘You’re doing it wrong!’ and then make a large number of code changes. This is because doing so creates too much risk. It also annoys the other software engineers in your vicinity who are quietly working away.

The more code changes that you make, the higher the risk that you’re introducing new bugs. The goal is implementing a fix for a bug or issue, not introducing new ones.

A high number of code changes also increases the risk of conflicts later. I don’t mean conflicts between developers, although this can happen, I mean conflicts reported by your version control software. You are running some sort of version control on your source code aren’t you?

Each change that you make has the potential to introduce code conflicts. For example if the upstream developers have fixed the bug in a different way. Or they may have made such significant changes to the code that your version control software can’t work out where in the file to make your change.

Solving conflicts in source code is not fun for anyone. Except perhaps if you’re one of those rare individuals that enjoy looking at diffs of source code and enjoy that sort of thing.

In summary, the key is to implement a fix which solves the clients issue with the minimum number of code changes. Adding code comments to indicate why you’re making the change can also be useful. Especially if you’re the person who is trying to solve a code conflict.

Forensic Programming – Understanding the Code

"Minifig Characters #5: Sherlock Holmes and Dr. Watson" by thom

“Minifig Characters #5: Sherlock Holmes and Dr. Watson” by thom

This is the third in a series of posts about forensic programming that started with the first post on my newly restarted blog. This post will focus on the task of understanding the code.

There are three aspects to understanding the code in any forensic programming task, and they are understanding:

  1. What the code is supposed to do
  2. What it actually does
  3. Where and how it is going wrong

This is arguably the hardest aspect of a forensic programming task, for two main reasons:

  1. You need to understand what the user is doing, so you can replicate the problem
  2. You need to understand the code

Using your communication skills it is possible to work with the user to understand the problem. Once the problem is understood you can develop a series of steps that can replicate the problem. If you can’t reliably replicate the problem, you have no idea if any fixes that you put in place, actually fix the root of the problem. Or if it just solves a symptom which may further mask the root cause.

The last thing that you want to happen is for you to develop a fix, have it tested by the client, and then have them report that it doesn’t work. That just leads to frustration for everyone.

Understanding the code is made more difficult by the actions of the people who have gone before you. One of my pet hates is code that isn’t sufficiently documented. It’s much easier to read and understand a series of comments, than to keep a series of function calls, variables and values straight in your head. If there was one phrase I’d ban from the vocabulary of people who write software it would be this:

The code is self documenting, so it doesn’t need comments

In my mind that’s an excuse uttered by a lazy programmer. Moreover, it is disrespectful to those that have to maintain their code after they’ve moved on to other things.

When writing code I like to include comments that:

  1. Describe what a function does
  2. The type and purpose of parameters
  3. The return type of a function, and what it means
  4. Any exceptions that I know may be thrown
  5. Decision points within the code

Basically the goal is to write enough comments to give someone coming after me an idea of what is going on, without having to read each line of code. Other developers may feel that I write too many comments. However I like to err on the side of too many comments, rather than not enough.

Adding debug statements can also be helpful when understanding how code works. They can be used to provide an insight into the contents of variables, as well as program flow. For example by dumping the contents of a variable or object. Or by having two debug statements, one after an if statement and another after the else.

Once you understand how the code works and where it is going wrong, you can implement a fix.

Two new Utility Scripts

This evening I’ve uploaded two new utility scripts to my techxplorer-utils repository in GitHub.

The first script is called JiraGitBridge and is designed to act as a bridge between JIRA and a Git. It automates Git related tasks using information in JIRA. At the moment the only action it undertakes is to create a list of commits in a Git repository based on the issues associated with a JIRA project and version. I intend to add additional actions as necessary.

The second script is called JiraListIssues and is designed to generate a list of issues, including their status, in JIRA associated with a project and version.

More documentation on these scripts, and the other scripts in the repository, is available in the repository wiki.

Forensic Programming – Communication is Key

"Communication Breakdown" by Stéfan

“Communication Breakdown” by Stéfan

Communication, I believe, is one of the things that separates software engineers from programmers / developers. It is also one of the defining characteristics of the best software engineers.

Communication is a key factor in the success of a forensic programming task. Without good communication skills, a software engineer can not achieve a positive outcome.

The first step is gaining an understanding of the issue that the client needs addressed. As I mentioned in the first post in this series the issue report usually goes something like this:

It doesn’t work! It is super critical, urgent, nay imperative, that this issue is fixed right now! In fact do you have a time machine? Because it should have been fixed ages ago! If you don’t fix it right now, I’m coming over and will rock your roof! 1

The use of your communication skills helps in asking questions of the client to determine exactly what the problem is. Often asking for a screen capture can be helpful. When asking for a screen capture be sure to be specific and ask for the entire browser window.

This can be helpful for two reasons. The first, is that the screen capture includes the URL of the page, which could provide vital information. The second, is that it gives you a clue about the browser and operating system that the client is using. Which may be something that they wouldn’t otherwise be able to tell you.

If necessary ask for steps to replicate the problem, and ask for as much detail as possible. It is important to remember, especially in the case of large enterprise systems, that your users may know more about an aspect of the system than you.

Keeping the client informed about your progress is very important. There is nothing more distressing to a client than having an issue that is affecting their users, which they don’t have any information from you about.

Remember that the person, or people, that your working with are a buffer between you and their users. A lack of communication puts them in a very awkward position.

Above all remain professional in your manner and use clear, concise and plain language. Limit the use of abbreviations and technical jargon as much as possible.

Good communication can go a long way to fostering a positive relationship between you and the client, which can only be a good thing.

Yes, I’m paraphrasing and taking dramatic liberties but you get the idea.

Thoughts about Forensic Programming

"Forensic Photographer" by James

“Forensic Photographer” by James

I’ve been a Senior Software Engineer at NetSpot now for a little over 9 months. During that time, I’ve not had the opportunity to do much original programming. Original programming in this context, is the development of software that has not existed before.

Original programming means you have control over the design, development and implementation of the software. The largest task that involved original programming to date was my development of the Local Cohort Automation plugin for Moodle.

The majority of my time is spent on activities that I’ve come to think of as forensic programming. I don’t mean that I’m undertaking programming for the purposes of law enforcement. Or that I’m working on an episode of CSI.

Rather, as a software engineer that works on predominantly client funded projects, I work on those issues which are of interest to NetSpot clients. What interests our clients the most are software bugs. They come in two main varieties:

  1. Code that is broken in some way and results in an error or errors
  2. Functionality that doesn’t align with the clients workflow and needs to be changed in some way

Applying a structured approach to understanding the existing code, and more importantly the clients problem, is what I mean by forensic programming.

Often when you start investigating an issue you have very little information to go on, other than the client saying:

X doesn’t work. I need it fixed immediately as a matter of the highest priority. If it isn’t fixed the world will come to an end and I will haunt you for the rest of eternity.1

Hopefully you get a screen capture and, even more importantly, the steps to replicate the issue.

Using this as a starting point you need to understand:

  1. What the clients issue actually is – communication is key
  2. The code that is going wrong – comments are key
  3. How to implement a fix - manage the risk

This is very different from original programming because you’re constrained by the code that already exists. I plan on exploring these topics further in upcoming posts.

I started wondering about original vs forensic programming the other day, when I was thinking about my career.

Before starting at NetSpot I spent the previous 10 years in the higher education sector. In my various roles I undertook a lot of original programming. Making the switch to forensic programming has taken some adjustment. The most frustrating parts of forensic programming are items 2 and 3 in the above list. But more on that later.

I then started thinking about the way programming is taught to students. In my experience the focus when teaching students is on original programming.

I wonder if the students expectations of what a software engineer does is skewed because of this. Even though I’m not actively in the higher education sector any more I still think about it.

Forensic programming, its something I’m thinking about and more posts will follow.

1 Yes, I’m paraphrasing and taking dramatic liberties but you get the idea.