June 2016

Reasons NOT to Refactor your code

 

Last week I wrote about the reasons to refactor code. Let us now look at some reasons why you shouldn’t refactor code. When dealing with legacy code there will always be a temptation to refactor the code to improve its understand-ability or performance. However, here are some reasons why it might be better to hold off:

1. You do not have the proper tests in place

Do not waste time refactoring your code when you do not have the proper tests in place
to make sure the code you are refactoring is still working correctly. A refactoring exercise pre-supposes a good engineering environment. And testing is one of the key components of that environment. If you don’t have a good way to test what you changed, it is better to hold off making that change until you can fully test it. Our developers tell us it is impossible to write good code without thorough testing. I believe them.

2. Allure of technology

Don’t make a refactoring change because a new exciting technology gets released. Given the fast pace of change there will always be something new and exciting. Today’s new and exciting technology will be legacy tomorrow. Instead, seek to understand the value of the new technology. If a Java backend is working fine, don’t jump to node.js unless you know that event handling is necessary for your application. Too many legacy applications are hard to maintain because they have a mish-mash of languages, frameworks, and technologies.

To learn more watch our webinar on reengineering legacy code.

3. The application doesn’t need to change

The primary purpose for changing an application is to satisfy new user requirements or usage conditions. So as long as the user of the application is content with the operation of the application there is less of a need to refactor the code. If there is no reason to change the application there is no reason to refactor it. Even if your company is swimming in money and you don’t have anything else to do, don’t do it.

Four Reasons to Refactor your Code

1. Maintenance is easier


Legacy code architecture erodes over time and becomes difficult to maintain. Legacy code bugs are harder to find and fix. Testing any changes in legacy code takes longer. Even small changes can inadvertently break the application because over time the design has been extended to accommodate new features and the code has become increasingly coupled. Refactoring code allows you to improve the architecture, reduce the coupling, and help the development team understand the intended design of the system. A clean architecture makes the design understandable and easier to manage and change.

Read our other blog on Reasons NOT to Refactor.

2. Make the Design Modular

Split up large applications into components. For instance, monolithic applications can be split up into microservices. In embedded systems, interfaces are created to allow drivers to be written to support a variety of hardware devices. These drivers serve to encapsulate the logic for interacting with different hardware devices. Also, most large applications can often be layered into separate layers such as the business logic and the user interface, which can itself be split up into various pages, forms, dialogs and other components. Modularity simplifies the design and is probably the most effective way to increase team productivity.

Check out our blog on a New Way to Think About Software Design.

3. Refactoring is often the cheaper option

When faced with new requirements that appear not to fit into the current design, it is often tempting to propose a complete rewrite. However, a rewrite can be expensive and highly risky. When a rewrite of a project fails it leaves in its wake a dispirited organization with no product to take to market. Before starting a rewrite, do a what-if exercise on the current application to see what would need to change to support the new requirements. Often large parts of an application can be salvaged while other parts are refactored, thereby reducing risk and saving considerable time and effort.

4. Your development team is happier

A design that is easy to understand reduces stress on the team. A modular design allows different team members to improve different components of the project at the same time without breaking each other’s code.

A new way to think about software design

This year’s Saturn Conference at San Diego reflected an evolving landscape as macro trends such as cloud based architectures, Internet of Things (IoT), and devOps in an Agile world, continue to reshape the industry. How do we think about design and architecture in this changing landscape?

Professor Daniel Jackson of MIT, in a keynote at the Saturn Conference, gave us a fresh look on how to think about design. The idea is simple and elegant and one wonders why it took so long for somebody to come up with it. Simply put, Professor Jackson describes an application as a collection of coherent concepts that fulfill the purposes of the application. The beauty of this formulation is that it eliminates the clutter of implementation artifacts.


When we describe the design of a program in UML, we struggle to create structural and behavioral diagrams that accurately reflect program implementation. Sadly (and, perhaps, mercifully) we rarely succeed in this endeavor and even if we did, those diagrams would likely be just as hard to understand as the code (think of creating interaction diagrams to represent various method call chains). And if our implementation language happens to be a non-object oriented language then we are plain out of luck. On the other hand, this new kind of thinking has the potential to transcend implementation language and, perhaps, even technology. It also has ramifications on the architect vs developer debates that rage in the world of software engineering today.

Conceptual Design vs Representational Design: Reducing the clutter

Professor Jackson provided several examples of applications and the concepts they embody. For instance, an email application embodies concepts such as Email Address, Message and Folder while a word processor embodies concepts such as Paragraph, Format and Style. A considerable part of the presentation delved into the details that illustrated the sophistication that underlies these concepts and the confusion that befalls when these concepts are poorly defined.

So, how do we select concepts? Professor Jackson defines purposes that a concept fulfills. In a clean design, he said, a concept fulfills a single purpose. This has ramifications that I have yet to fully get my head around. It reminds me of the Single Responsibility Principle which is also a difficult concept to understand. In any case, I suspect that defining a coherent set of concepts is difficult and takes repeated iterations of implementations to get it right. In fact, the user of that software is likely to be a critical part of the process as concepts are pruned, split up or even eliminated to make them coherent and understandable.

And, how do we implement concepts? Does a concept map to a single class or multiple classes if implemented in an object oriented language? I will eagerly wait to see further work on this approach.

Go look up the slides of this thought provoking presentation here: Rethinking Software Design.