The three most important attributes of a software engineer were identified by Larry Wall (author of Programming Perl) as "laziness, impatience, and hubris". I would suggest that a fourth great virtue would be "curiosity".
It is important to question why things are done in a particular way - whether that's the initial requirements from the customer, the architectural decisions, the implementation. However, I believe that this question is especially important in the context of debugging.
Applying the 5 Whys
When faced with a piece of code that does not work, it is important to identify the root cause of the problem. Failure to do so may result in a fix that appears to fix it, but is in fact masking deeper issues that will resurface later.
For example, given a piece of software where a form cannot be saved due to a validation error on an unused field, we could apply the "5 Whys" technique:
- Why can't the form be saved? The CustomerId field in the model class is not set, which causes a validation error.
- Why is the CustomerId field not set? It is not required on this screen, nor are several other fields from this model.
- Why is this field present in the model for this screen if it is not used or needed? The model has been recycled from a previous, more detailed screen.
- Why has this model been reused instead of creating a new one with only the required fields? The original engineer who created the screen did not consider the problems it may cause.
- Why was the original engineer not aware that they should not have reused this model? Inadequate training and/or documentation provided.
If the analysis stopped at the first "Why?", it may seem sensible to fix the problem by modifying or even removing the validation for the CustomerId field. However, by digging deeper, it becomes apparent that there are a number of unused fields and that a better solution would be to create a separate model for this screen that only contains the subset of fields required. Depending on the scenario, it may be possible to create a base class with the reduced field set and then inherit from this for the more detailed model - or to simply create two independent model classes.
The ultimate outcome of this analysis suggests that there is a defect in the original development process, which could be remedied by providing additional training or documentation for engineers working on this kind of system. Additionally, the outcome of step 4 begs the question "Why did nobody else spot this?" - which could indicate that there is inadequate code review being performed or that the review process itself is lacking.
If you do ask "Why?", never accept "That's just the way we do it".