Author Archives: Mike Swainston

Using Structure101 Build with SonarQube

When using Structure101 Build with SonarQube the detection of new structural issues can be delegated to SonarQube. This simplifies the configuration of Structure101 Build but requires an appropriate SonarQube Quality Gate to be defined. [Build 14507 and later of the … Read More

Using Structure101 Build with Jenkins and SonarQube

Structure101 Build and the Structure101 SonarQube plugin can be incorporated into your existing Jenkins CI process. This post describes the necessary configuration. [Build 14507 and later of the Structure101 SonarQube plugin] Structure101 Build performs architectural checks and can publish a snapshot … Read More

Using the Structure101 SonarQube Plugin with Maven

The Structure101 Key Measures can be reported via SonarQube. The configuration to do this is straight forward and can re-use an existing Structure101 Build configuration file. [Build 14385 of the Structure101 SonarQube plugin] It is assumed that SonarQube Scanner is already … Read More

Configuring Structure101 Build

Structure101 Build can be added to your existing CI processes to check for new structural violations and deteriorating key measures. Structure101 Build is delivered as a zip archive. Installation is simply unpacking to a suitable folder location. The core jar file is … Read More

Using the Structure101 SonarQube Plugin with Gradle

The Structure101 Key Measures can be reported via SonarQube. The configuration to do this is straight forward and can re-use an existing Structure101 Build configuration file. [Build 14385 of the Structure101 SonarQube plugin] It is assumed that SonarQube Scanner is already … Read More

Structure101 Build Configuration with Workspace based Studio Projects

Structural refactoring initiatives typically make use of the synchronisation that is possible between Studio and Workspace.  Careful configuration of Structure101 Build will ensure the Key Measures can be tracked consistently across Studio, Workspace, SonarQube and the Structure101 Web Application. Workspace … Read More

Merging Structure101 Studio Action Lists

The action lists created in Structure101 Studio are saved in the project .hsp file. Currently there is no ‘Merge Action List’ feature in Studio. But the lists can be merged by editing the .hsp XML file. To avoid overwriting your … Read More

Structure101 Workspace IntelliJ IDEA and Gradle

The IDEA gradle import creates module compile output paths that are different to the gradle build output paths. Structure101 Workspace uses the IDEA module compile output paths to find the bytecode. So, running a gradle build will not propagate changes to … Read More

Module extractions with many tens or hundreds of violations to resolve will benefit from preparatory planning and estimation.

This is the fourth post in a series that will explore the challenges of migrating a monolithic code base to a modular architecture

Series links:
Post 1 – Migrating from Monolith to Modular
Post 2 – Monolith to Modular – The Extract Module Use Case
Post 3 – Monolith to Modular – Managing Violations
Post 4 – Monolith to Modular – Sizing and Estimating Scope (this post)

 

In our previous post we described the use of Structure101 Studio and Workspace to identify, manage and resolve dependencies that violate a target architecture. In this post we describe use of Structure101 Studio’s Dependency Breakout to size and scope the refactoring effort.

In the example below, three packages have cyclic dependencies.

Attempts to move code responsible for remote communication into a new comms module resolves the feedback dependency from seaview to assemblies. But another is created from assemblies to comms which prevents creation of the new module (the dotted arrow).

In the following LSM, the feedback dependency is selected (highlighted in blue) and the details of the interfaces, classes and members that comprise the dependency are shown in the breakout beneath. (Note that in the Structure101 Project Properties dialog, Granularity is set to detail). In this example there are 40 code references contributing to the feedback dependency.

The breakout shows the size and scope of the refactoring needed to resolve the feedback dependency.

It might be tempting to bulk import a story per dependency into an agile planning tool. But careful grouping of the violations will yield fewer stories and a shorter time to deliver them. The number and nature of the stories is driven by the type of the dependencies and how they are to be fixed and tested, and by whom:

  • Will the fix be at the from or to end of the dependency – or both?
  • Which team is responsible for the code that will be refactored?
  • Will the refactoring be done by incorporating the stories into a team’s existing backlog?
  • Or is there a re-engineering team in place tasked with the dependency removal?
  • How will the changes be tested?

The detail list in the lower pane of the dependency breakout can be exported via the context menu (Copy | Copy All) and pasted into a spreadsheet.

Use this raw list as input to the backlog creation. Ordering by the from or to columns helps to identify dependencies that can be grouped together into a single story.

Structural refactoring should have no effect on application functionality. The only way to test the changes is through regression testing. If the application does not have an automated regression suite the cost of manual testing can far exceed the cost of changing the code. The worst case scenario is one in which the velocity of the team is determined not by the code changes but by the manual regression testing effort.

Example

As an example, consider the situation where a method in an implementation class is being called directly. The method isn’t suitable for inclusion in the interface because it exposes the module’s internal model in the return type. A new method with a suitable new class for the return type must be implemented which delegates to the existing method and converts the internal model to the new return type. The first violation probably appeared when a developer under pressure to deliver a change in functionality took the shortcut of referencing the implementation class, rather than implementing the delegating method. Once it exists, other calls to the method can appear across the code base. Another developer under pressure takes the same shortcut or worse,  blindly copies the call to the implementation class.

One option is to group all of these calls together in a single story. When playing the story the developer will implement the missing delegating method and then refactor all the offending code to use the interface and its new method. But if the calls are spread across the code base this one story could affect many different areas of functionality. Without an automated test suite such a change would result in a significant manual testing effort.

So another option is to group violations into stories for each functional area. A story to implement the delegating method must be played first. When sprints are planned the stories affecting the same functional area are played together such that many changes can be regression tested together.

Whichever way the work is partitioned up and assigned to developers, each story should be a discrete piece of work that can be completed and deployed independently. This allows the stories to be played at a pace to suit the team(s) involved. Should priorities change the refactoring can be halted without losing any stories already played.

 

Monolith to Modular, Part 3 – Managing Violations

Dependencies that violate your target module structure need to be resolved before code can be extracted from the monolith into the new module. This is the third post in a series that will explore the challenges of migrating a monolithic … Read More