superimposing application-specific functionality. The fourth tier was meant as a public interface,
decoupled from all the implementation below. This scheme was a bit too complicated, but the
layers were well defined and there was some tidiness to the separation of concerns. We could have
lived with mentally connecting all the physical objects making up one conceptual object. The
separation of aspects even helped at times. In particular, having the persistence code moved out
removed a lot of clutter.
But on top of all this, the framework required each tier to be in a separate set of packages, named
according to a convention that identified the tier. This took up all the mental room for partitioning.
As a result, domain developers tended to avoid making too many
MODULES
(each of which was
multiplied by four) and hardly ever changed one, because the effort of refactoring a
MODULE
was
prohibitive. Worse, hunting down all the data and behavior that defined a single conceptual class
was so difficult (combined with the indirectness of the layering) that developers didn't have much
mental space left to think about models. The application was delivered, but with an anemic domain
model that basically fulfilled the database access requirements of the application, with behavior
supplied by a few
SERVICES
. The leverage that should have derived from
MODEL-DRIVEN DESIGN
was
limited because the code did not transparently reveal the model and allow a developer to work
with it.
This kind of framework design is attempting to address two legitimate issues. One is the logical
division of concerns: One object has responsibility for database access, another for business logic,
and so on. Such divisions make it easier to understand the functioning of each tier (on a technical
level) and make it easier to switch out layers. The trouble is that the cost to application
development is not recognized. This is not a book on framework design, so I won't go into
alternative solutions to that problem, but they do exist. And even if there were no options, it would
be better to trade off these benefits for a more cohesive domain layer.
The other motivation for these packaging schemes is the distribution of tiers. This could be a
strong argument if the code actually got deployed on different servers. Usually it does not. The
flexibility is sought just in case it is needed. On a project that hopes to get leverage from
MODEL-
DRIVEN DESIGN
, this sacrifice is too great unless it solves an immediate and pressing problem.
Elaborate technically driven packaging schemes impose two costs.
If the framework's partitioning conventions pull apart the elements implementing the
conceptual objects, the code no longer reveals the model.
There is only so much partitioning a mind can stitch back together, and if the framework uses
it all up, the domain developers lose their ability to chunk the model into meaningful pieces.
It is best to keep things simple. Choose a minimum of technical partitioning rules that are essential
to the technical environment or actually aid development. For example, decoupling complicated
data persistence code from the behavioral aspects of the objects may make refactoring easier.
Do'stlaringiz bilan baham: