Now that we have covered the basic building blocks in the first part of this article we can progress to more advanced aspects. In this post I will focus on how to factor out reusable parts of an architecture into separate files that can best be described as architectural aspects. We will also cover the restriction of dependencies by dependency types. Read More
Software architecture defines the different parts of a software system and how they relate to each other. Keeping a code base matching its architectural blueprint is crucial for keeping a complex piece of software maintainable over its lifetime. Sure, the architecture will evolve over time, but it is always better to have an architecture and enforce it than giving up on keeping your code organized. (See my recent blog post: Love your Architecture)
The problems start when it comes to describing your architecture in a formal and enforceable way. You could write a nice Wiki article to describe the architecture of your system, or describe it on a Powerpoint slide or with a set of UML diagrams; but that would be quite useless because it is not possible to check in an automated way whether or not your architecture is respected by the code. And everybody who ever worked on a non-trivial project with more than 2 developers knows that rules will be broken. That leads to an ever increasing accumulation of architectural debt with all kinds of undesirable side effects for the long term sustainability of a piece of software. You could also use Sonargraph 7 or similar tools to create a graphical representation of your architectural blueprint. That is already a lot better because you can actually enforce the rules in your automated builds or even directly in the IDE. But it also means that everybody who wants to understand the architecture will need the tool to see it. You also will not be able to modify the architecture without having access to the tool.
Wouldn’t it be nice if you could describe your architecture as code, if you had a DSL (domain specific language) that can be used by software architects to describe the architecture of a system and that is expressive and readable enough so that every developer is able to understand it? Well, it took us a while to come up with that idea, but now I believe that this is the missing puzzle piece to significantly boost the adoption of formalized and enforceable software architecture rules. The long term benefits of using them are just to good to be ignored.
The single best thing you can do for the long term health, quality and maintainability of a non-trivial software system is to carefully manage and control the dependencies between its different elements and components by defining and enforcing an architectural blueprint over its lifetime. Unfortunately this is something that is rarely done in real projects. From assessing hundreds of software systems on three continents I know that about 90% of software systems are suffering from severe architectural erosion, i.e. there is not a lot of the original architectural structure left in them, and coupling and dependencies are totally out of control. Read More
Research [Strei2014] and other sources (e.g. [Pizz2013]) have shown that typical software code bases contain 5-10% “dead code”, i.e. code that can be removed without reducing the functionality.
Streamlining the code base by identifying and removing dead code has several benefits:
- Less maintenance cost: Whilst dead code is less likely to be changed frequently, it still has to be understood and might be effected by refactorings.
- Smaller footprint: Less code makes the development environment faster, the build and deployment processes are more efficient, and the size of runtime artifacts are smaller.
- Better precision for calculated metrics: Dead code contributes to software metrics, e.g. “average test coverage” might be improved by tests for unused code and therefore creating false confidence.
Dead code grows in projects for the following reasons:
- Only few developers check in their IDE if some element is still in use, when they remove a reference to it.
- Identifying reliably that a public class or method is “dead code” is not a trivial task and requires deep knowledge about the code base.
- Removing seemingly dead code can easily lead to new bugs therefore developers are usually reluctant to remove them.
It is likely that more dead code exists in large and long running projects with a high fluctuation of developers.
Detecting dead code is a good use case to illustrate Sonargraph Explorer’s powerful scripting API and to demonstrate how it can be used to efficiently detect dead code within a Java project including public classes, methods and fields.
Dependency cycles in software systems have very negative impact on characteristics like testability, understandability and reuse (as explained here). Cycles with only a few nodes (say 5 to 10) might be resolveable quite simply by manually analyzing them. For bigger cycles it is helpful to have an automated analysis at hand based on an algorithm solving the minimum feedback arc set problem. A feedback arc set of a directed graph is a subset of its arcs that upon removal would transform a cyclic into an acyclic directed graph. Such an algorithm combined with user input about the domain (i.e. which dependencies are absolutely necessary and which absolutely violate design decisions) is able to deliver excellent results. Read More
The nicest thing you can say to a project manager or your boss is something like “I am done with my task / project“. Everybody loves people who are getting things done. If you do that consistently you will get rewarded and used as an example for those other slackers who are having a bit more trouble with getting things done. On the other hand people who write beautiful, elegant and maintainable code hardly ever get any recognition for that. Nobody really seems to care about the “internals” as long as the software somehow does what it is supposed to do. In a cultural environment like this technical quality, code maintainability and sustainability in general are easily thrown under the bus. Read More
Over time software systems tend to develop several negative symptoms: simple changes require a surprisingly big effort to be implemented, changes cause the system to break in unrelated areas, reuse of code in other systems is simply not feasible, the code is hard to read and understand even for the directly involved programmers. One of the main reasons of facing these symptoms is an unintended increase of the overall system coupling.
Except for very small systems the manual control of the overall coupling is a tedious task – a tool-based approach is needed. Sonargraph-Explorer is such a tool and among other things it helps the developer to assess and control coupling and work against its accidental increase. It is the first product built upon the new Sonargraph Next Generation platform supporting Java, C# and C/C++. It offers different visualizations of dependency structures and a powerful scripting engine based on Groovy which allows extending the built-in analysis capabilities.
The following content introduces the needed definitions and terms related to component coupling (one way to express the overall system coupling). It explains how to use Sonargraph Explorer to visualize the corresponding dependencies and determine components contributing significantly to the overall system coupling with a custom script automatically. Read More