Kill the Clones

Kill the Clones

By Adam Tornhill

Overload, 24(134):8-10, August 2016


Problems in code can hide in surprising places. Adam Tornhill demonstrates how to detect software clones and uncover hidden dependencies.

Your Code as a Crime Scene [ Tornhill15 ] presents around 15 different software analyses. Of all those analyses, Temporal Coupling is the most exciting one. In this article, we’ll put the analysis to work on a real-world system under heavy development: Microsoft’s ASP.NET MVC framework [ ASP ]. You’ll see why and how Temporal Coupling helps us design better software as we detect a number of possible quality issues in ASP.NET MVC. In addition, you get a preview of Empear Developer [ Empear ], a new tool to automate software analyses.

What’s temporal coupling?

Temporal Coupling means that two (or more) modules change together over time. In this version, Empear Developer (see Figure 1) considers two modules coupled in time if they are modified in the same commit (in future versions you’ll find other options too).

Figure 1

The fascinating thing with Temporal Coupling is that the more experience we get with the analysis, the more use cases there seem to be. For example, you can use Temporal Coupling results to:

  1. Detect software clones (aka copy-paste code).
  2. Evaluate the relevance of your unit tests.
  3. Detect architectural decay.
  4. Find hidden dependencies in your codebase.

In this article we focus on detecting software clones and uncovering hidden dependencies.

Explore your physical couples

Let’s fire-up Empear Developer and run an analysis of ASP.NET MVC. Since we’re interested in exploring Temporal Coupling, we click on the corresponding button. Figure 2 shows what the result looks like.

Figure 2

Empear Developer presents us with multiple views so that we can investigate different aspects of the results. The default view above is based on a visualization technique called Hierarchical Edge Bundling. You see the names of all involved files as nodes with links between the ones that are coupled. If we hover over a node, its temporal couples will light-up in red.

Empear Developer

Empear Developer is a desktop application for programmers and software architects that gives you unique insights into your codebase:

  • Use a Hotspot analysis to identify complicated code that you have to work with often.
  • Discover Temporal Coupling between modules in your code and get deep design insights.
  • Use Complexity Trends to supervise how your code evolves over time and react early to potential quality issues.

Empear Developer is a tool built on the ideas in the popular book Your Code as a Crime Scene. Empear Developer analyses data from your Git source code repository. This gives you a new perspective on your codebase and unique insights that you cannot get from the code alone. And it’s information that’s based on actual data from how you’ve worked with the code so far. You use that information to improve your software and make it easier to maintain.

So, why do two source code files change together over time? Well, the most common reason is that they have a dependency between them; One module is the client of the other.

You see a few examples on physical coupling in the picture above, a unit test tends to change together with the code under test. This is expected. In fact, we’d be surprised if the temporal coupling was absent – that would be a warning sign since it indicates that your tests aren’t being kept up to date or aren’t relevant.

A physical dependency like this is something you can detect from the code alone. But remember that Temporal Coupling isn’t measured from code; Temporal Coupling is measured from the evolution of the code. That means you’ll sometimes make unexpected findings.

What are the criteria for Temporal Coupling?

Empear Developer only looks for changes in the same commit. However, Empear’s Enterprise version [ Enterprise ] presents alternative metrics where two, or more, files are coupled if:

  • they are changed by the same programmer within a specific time frame, or
  • the commits refer to the same Ticket ID (Jira, GitHub, etc).

The first metric is a heuristic while the second one delivers more accurate results based on the ticket system on top. That means you’re able to find temporal coupling even if the files are changed by different programmers (e.g. front-end versus back-end teams) or when you have your code in multiple repositories.

You use this variant of temporal coupling to identify change patterns that ripple over repository boundaries. For example, I did a software analysis for one of our customers a while back. They used a microservices architecture and we identified some heavy temporal coupling between some of their services. That was a clear sign that their services weren’t as autonomous as they should be. Not only is it hard to reason about system behaviour in that case; It’s also expensive to maintain since you now need to deploy whole clusters of services at once.

Look for the unexpected

There’s one main heuristic to keep in mind as you analyze a software system: always look for the unexpected. Look for surprises, since a surprise in a software design is bound to be expensive from a cognitive perspective and therefore expensive to maintain.

As soon as you find a logical dependency that you cannot explain, make sure to investigate it. Let me clarify with an example from ASP.NET MVC (see Figure 3).

Figure 3

The visualization above shows temporal coupling between a LinkTagHelper.cs and a ScriptTagHelper.cs . You also see that their unit tests tend to be changed together.

While those two classes seem to solve related aspects of the same problem, there’s no good reason why a change to one of them should imply that the other one has to be changed as well. Let’s get more information on this potential problem by switching to the detailed view in Figure 4.

Figure 4

The data above confirms that there’s a strong degree of coupling between the LinkTagHelper.cs and ScriptTagHelper.cs , but also between their unit tests. 9 out of 10 changes we do to one of the classes will result in a predictable change to its coupled peer.

When you find an unexpected change pattern like this you need to dig into the code and understand why. It’s particularly interesting in this case since there is not any direct physical dependency between the logically coupled classes! Let’s have a look at the LinkTagHelper.cs and the ScriptTagHelper.cs to see if we can spot any patterns (see Figure 5).

Figure 5

So you have the ScriptTagHelper.cs to the left and the LinkTagHelper.cs to your right. Do you see any pattern? Indeed, and this is what I tend to find on a regular basis as I inspect logical coupling – a dear old friend – copy-paste.

If you take a detailed look, you’ll note something rare. The variable names and, even more rare, the comments have been updated so this is more like copy-paste with a gold plating (see Figure 6).

Figure 6

Break the logical dependencies

When you have an unexpected temporal dependency, you’ll often find that there’s some duplication of both code and knowledge. Extracting that common knowledge into a module of its own breaks the temporal coupling and makes your code a bit easier to maintain. You see, temporal coupling often suggests refactoring candidates.

At this point it’s important to note that duplicated code in itself isn’t always a problem; just because two pieces of code look the same, that doesn’t mean they have to be refactored to use a shared abstraction. Instead we want to focus on what the code expresses.

In the case of ASP.NET MVC, it’s clear that the two classes model the same process. So it is indeed a duplication of knowledge and it’s likely that the code would benefit from a refactoring. This is even more important since, as the temporal coupling results indicate, we have the same amount of duplication between their corresponding unit tests. Avoiding expensive change patterns makes software maintenance much easier. Duplication of knowledge makes change much more expensive: it is easy to forget to update one of the copies when the business rules change or when a bug gets fixed.

Complement your intuition

If you’re an experienced developer who has contributed a lot of code to a particular project then you probably have a good feeling for where the most significant maintenance problems will show-up. You may still get surprised when you run an analysis, but in general several code analysis findings will match your intuitive guess. Temporal Coupling is different. We developers seem to completely lack all kind of intuitive sense when it comes to Temporal Coupling.

Conclusion

Exploring Temporal Coupling in our codebases often gives us deep and unexpected insights into how well our designs stand the test of time.

In this article we explored how Temporal Coupling detects a DRY violation in ASP.NET MVC. We ran an analysis with Empear Developer and looked for unexpected temporal dependencies to identify expensive change patterns in our code. Used that way, Temporal Coupling suggests both refactoring candidates and the need for new modular boundaries.

The same analysis principle also helps you catch architectural decay. All you have to do is to lookout for temporal dependencies that span architectural boundaries. Temporal Coupling is like bad weather – it gets worse with the distance you have to travel – and it makes a big difference if we need to modify two files located in the same package versus modifying files in different parts of the system. So make it a habit to investigate the temporal dependencies in your repository on a regular basis. Your code will thank you for it.

References

[ASP] https://github.com/aspnet/Mvc

[Empear] http://empear.com/offerings/developer-edition/

[Enterprise] http://empear.com/offerings/enterprise-edition/

[Tornhill15] Tornhill, Adam (2015) Your Code as a Crime Scene , Pragmatic Bookshelf, ISBN: 978-1-68050-038-7






Your Privacy

By clicking "Accept Non-Essential Cookies" you agree ACCU can store non-essential cookies on your device and disclose information in accordance with our Privacy Policy and Cookie Policy.

Current Setting: Non-Essential Cookies REJECTED


By clicking "Include Third Party Content" you agree ACCU can forward your IP address to third-party sites (such as YouTube) to enhance the information presented on this site, and that third-party sites may store cookies on your device.

Current Setting: Third Party Content EXCLUDED



Settings can be changed at any time from the Cookie Policy page.