I came across a thread in the refactoring group in which Mikael Freidlitz had tentatively asked the following:
> I know that some would say that I’m way off since ‘The Code is the Design’
> and all, but I still insist that there has to be a way to apply
> refactoring on design level.
And it seemed that generally there was agreement that since only code really exists, only code can be changed, not design or architecture! It seems me that some in the agile community tend to focus on the class-level “design” to the exclusion of the “emergent” (their term, and a good one) package design. (Robert C. Martin is a notable exception.)
Packaging is one example of design (often the only kind of “design” since the white-board got erased ;-). Classes (the “code”) can be arranged in a package hierarchy so that the dependencies between packages (and recursively, meta-packages) form an orderly acyclic graph at any level. Or, they can be grouped into packages so that the package-level dependencies form a tangled mess. The latter is a smell that warrants refactoring.
The actual refactoring that you undertake depends on the cause of the tangled dependencies. For example, the undesirable dependency may be caused by one (or a few) mis-placed class and the required refactoring a simple matter of moving the class to the correct package. Or, if the package-level tangle is caused by a large class-level tangle that spans multiple packages, the refactoring may require some more serious refactoring to break or reverse the class-level dependencies (e.g. by using interfaces) until the class-level tangles are at least confined to single packages.
I guess that one end of the scale can come under the heading of refactoring – code changes that improve the code-base without changing the functionality in small steps that can be easily verified by testing. No doubt the work required to fix some tangled messes would be judged as “rework”.
The package-level structure is often forgotten about, perhaps because it’s generally invisible, but can have a big and expensive impact on the “agility” of a code-base (especially very large ones). The symptoms are things like changes rippling around uncontrollably, developers continuously clashing at the version control system, “everything needs everything” slowing down testing and ruling out reuse. (Martin Fowler makes a good case for acyclic package dependencies in his book). The sort of problems that could make a big project ( e.g. an operating system 😉 ) ship late.