Normal
0
21
false
false
false
FR
X-NONE
X-NONE
Recently, Jeremy D.
Miller
wrote on twitter:
I still think NDepend is more important in strange codebases. I know
where the coupling pain points are in my own code.
I
read Jeremy’s blog and think it is an excellent point to improve developer
skills. I was
very concerned to read: I know where the coupling pain points are in my own code. I put a
lot of energy in evangelizing about the efficiency of good componentization to
fight again spaghetti code. Anyone
that worked on a real-world large project (a project with many
developers, with turn-over, lack of education and years of legacy) knows that
dealing with wrong coupling is a major problem. Actually I think it is THE major problem for large organization.
I tried to summarize this situation + solution in my post: Getting
rid of spaghetti code in the real-world: a Case Study
We
all agree that software development is an incredibly difficult engineering task,
and I get skeptical when I hear too confident things like I know where the coupling pain points are in my own code. The
reasons are twoflod :
- First, without the help of
appropriate tooling, nobody can master the structure of a program.
- Second, from what I saw, unmanageable
monster code structure is the primary technical reason of project failure.
By
curiosity I analyzed StructureMap (an OSS
project developed by Jeremy) with NDepend.
Below
is
a graph of dependencies between namespaces: the code structure is
entangled, there is no care for componentization nor any identifiable
layer:
Here is the same
entangled structure viewed this time with the dependency matrix + the
exhibition of a particular cycle of length 5:
Don’t take me wrong, I
don’t put the blame on StructureMap nor its author. I present concrete and
verifiable facts, not opinion. Even, I estimate that lack of componentization
is something acceptable taking account the fact that StructureMap is a small
project developed by a single person (around 3.100 Lines of Code LoC). My concern is that, Jeremy being a
leader in the .NET community, if a programmer takes the words (tooling is for someone else) I know where the
coupling pain points are in my own code for granted, he will end up
with a similar spaghetti code structure but this time, on a large scale
professional project.
Actually while starting
NDepend 5 years ago I didn’t put much care in componentization and layering. Inevitably
I ended up dealing with spaghetti. At a point in 2006, the project was on its
way to become something professional and at the same time, was released the
dependency matrix feature. The first thing to do was to eat my own dog food by layering
the code. For those interested find the whole story detailed in this article: Control
component dependencies to gain clean architecture
(section Getting rid of dependency cycles
: a case-study).
The dependency matrix
below shows the current NDepend code base structure. To read the matrix: a blue
cell means that the namespace represented by the column is using directly the namespace
represented by the row. The structure is made of 66 components mapped to 66 layered
namespaces: the matrix is triangular meaning that high level and low level layers
are well identified or in other words, there are no dependency cycles. The blue
triangle in the middle is the consequence of the UI code cohesion. The blue
ribbon at the bottom is the consequence of the low-level internal framework that
itself relies on some helpers.
With 78K LoC NDepend is
25 times bigger than StructureMap. This is illustrated by the metric view
below. Every day it is a blessing for the whole team to work on a clean
structured code. Also every new design decision is driven by the respect of this
clear, simple and elegant concept.
With 78K LoC NDepend is still
a medium-sized code base. It is itself small compare to a real large code base
such as the whole .NET Framework v3.5 with millions of LoC. The point here is
to show how big a code base can become, to give an idea of the damage that spaghetti code could do.
An entire post in
response to a twitter sentence is maybe a bit disproportioned. But I feel
concerned when someone trusted says that he doesn’t need tooling to care for
dependencies/layering/componentization. To me, it is as chocking as hearing
that code correctness can be achieved without automatic testing and contract. I
saw too many projects failing because of the spaghetti paradigm, and I am sure you saw it too (I just hope you
don’t deal with it every day [:)]). The return on investment for structuring the code is just too high to not do it. Alternatively, the pain you got for not structuring code is also just too high to not structure it.
I had an email discussion with Jeremy about this post:
Jeremy: By I know where my coupling pain points are I meant that I know
exactly which classes are dangerous to touch and which ones aren’t that
risky (…) At no point in the post do you make any kind of concrete proof that the particular namespace coupling made any kind of real impact on development. I watch CC#’s religiously (it’s crept up in some places by natural accretion), but the namespace coupling? I’d judge that to be relatively unimportant in terms of real impact.
Me: The problem comes from which artifact you use to represent components. Microsoft advocates implicitly for assemblies to represent components, which IMHO is a very poor choices:
By implicitly I mean mainly:
- the internal visibility level which scope is assembly
- the one-to-one association between VS project and assembly
- the way project gets referenced each other in VS
I qualify it as a poor choice because assembly is a physical concept (file) while component is a logical concept. I wrote a lot about the problems provoked by physical components (VS slow down, C#/VB.NET compilation time, CLR loading time, deployment issues with plenty of files to deal with, unit of re-use spawned on many files…)
Advices on partitioning code through .NET Assemblies
Control
component dependencies to gain clean architecture
(section .NET Components)
And Jeremy also advocated against using assembly to master coupling in its post: Separate Assemblies != Loose Coupling
If you don’t choose assembly to represent component, the natural artifact candidate is then namespace. And if so, namespaces cycles is bad because components cycles is bad. If components A and B are mutually dependent, you get one super component made of A & B, because A and B cannot be tested, reused, refactored etc, (all these things that characterize a component),…independently from each other.
A third choice to modelize components, apart assembly and namespace, is a group of types, as the .NET Base Class Library team is doing. They used namespaces to hierarchize the framework set of public types which is not a bad thing from a user point of view. They are now stuck to group their type (like lower level is primitive CLR types int, bool.. then comes a component with more evoluated primitive types string, StringBuilder, array… then comes threading and other low level stuff… etc). Types are then grouped, independently from their namespaces (and maybe their assemblies, this I don’t know). The problem here is that this third artifact (group of types) is made concrete by some proprietary tools and has no real existence in the source code itself. It is hard for programmer to get a concrete picture of componentization and this certainly increases the complexity for refactoring any portion of code.




