|
This webpage discusses the vague concepts "delegation" and "coordination" of "the work" and "business rules", and in particular in the context of the definition and guidelines for the GRASP Controller. Here are some example quotes illustrating how these phrases are used in GRASP Controller discussions:
I think that, whenever you invoke a method, you can consider that invocation as delegating part of the work to the invoked method. I mean, when you implement a method in an object-oriented system, you almost always delegate part of the work to other classes/methods, usually to a method in the same layer or one layer below. Even in the lower layers, when using built in classes which you delegate to, such as the method "int Transformer.toInt(String)", used from Larman's Controller example [AUAP, page 310-311], I would assume that the method is simply implemented by "delegating" to a framework class, such as Java's method "int Integer.parseInt(String s)". It is a nice default object-oriented approach to try to implement the behavior in an "Information Expert" class (using GRASP terminology), and to use/reuse the implemented behavior from other classes through "delegation". In the domain layer, an Information Expert can e.g. be implemented by the DDD (Domain-Driven Design) building block concepts Entities or Value objects. The DDD "Service" in the domain layer can be used for example when you want to implement a behavior which uses two Entities or Value objects, but when the behavior does not natural fit into any one of them or you do not want to create a coupling between them in the sense that one of them should not have a dependency to the other. Such a DDD Service is, as far I see it, an example of the GRASP Pure Fabrication concept which is defined as a GRASP pattern, roughly like this: "What object is responsible when you are desperate ?" or more precisely defined like this: "What object should have the responsibility when you do not want to violate high cohesion and low coupling, or other goals, but solutions offered by Information Expert (for example) are not appropriate ?" [AUAP, page 421] When you implement a GRASP Pure Fabrication object, you will likely delegate parts of the work to other domain objects, and probably also add some code that can be considered as coordination work, as opposed to only doing pure delegation. From within a GRASP controller, you can also do "some work", but Larman writes [GRASP Controller guideline] that it should not do "much work itself" but should rather "delegate to other objects the work that needs to be done". Such an object might be a Pure Fabrication object, which in turn might delegate to other information expert objects (Entities/Value objects or delegate to other pure fabrication objects or DDD Services). If you would look at some existing GRASP controller, you might think that it contains "too much work" for deserving to be called a GRASP controller, and then you can solve that by refactoring some of the implementation into some other object, e.g. you can move some of the code into a Pure Fabrication object (GRASP). However, how will you determine when you are able to look at your controller code and consider it as having been refactored enough to only be containing very "little work", and "only coordinating" tasks, and "only delegating" work? I am skeptic to whether there really exists a useful answer to this question, since the GRASP Controller guideline phrases "coordinate", "delegate" and "not much work" are too vague to be very useful, since these things are something you frequently do in most methods, and not only in GRASP Controller methods. Example: Let us say you have a class like this: Now, to create a "real" GRASP controller, i.e. a controller without "too much work", I can create an artificial object (DDD Service or GRASP Pure Fabrication object) into which I will refactor all code: The above example is extreme, since all implementation were moved into another class, making the GRASP controller into a pure delegation implementation, without any additional coordinating implementation (work of its own) at all. However, you can imagine that parts of the "coordination work" could have been left to remain in the GRASP controller, which then still would be doing "some work". My point is that it is too vague to refer to phrases such as "some work" and "only coordinate", since such things are usually done from most kind of objects. Regarding the GRASP Controller definition, I think that the most vague part is the part that says it should "coordinate" a system operation (while a more well-defined part is the phrase "first object beyond the UI layer"), since it is unclear how much coordination/delegation code can be implemented directly in the controller and how much code that rather might be implemented elsewhere, e.g. in some domain service class. It just is not enough to try to "explain" the content of a controller by saying that it should "only delegate and coordinate", since such a vague statement does not define the difference between the coordination/delegation code that can be in the controller and what kind of coordination/delegation code that instead can be located in a Pure Fabrication (such as a DDD Service) but being invoked from the controller. Some people (e.g. see the "above quotation about business rules") try to define the appropriate kind of content for the GRASP controller by saying that it should not contain any "business rules". If that really would be true, I think that the concept of "business rule" also would be a vague concept. For example, consider these parts of Larman's Register class [AUAP, page 378] which is a GRASP controller: As you can see in the above code, the client will need to invoke "makeNewSale" before "enterItem" is invoked the first time, since otherwise there will be a NullPointer/NullReferenceException. So, the client will need to know that before he can start entering items, he first needs to register a new sale. After having done that, he will then be able to add additional different kind of items to the same sale. In my opinion, this knowledge can be seen as a "business rule". Another (indeed more unusual/worse/unflexible, but still possible) kind of business rule could be to only allow a certain number of the same items within one sale. This kind of business rule could be implemented like this instead: So, my point is that the implementation of the GRASP controller example (the Register class at [AUAP, page 378]) is implemented with a "business rule" constraint, which is enforcing the client to know that a sale needs to be separately created first through a separate system operation ("makeNewSale") to the "Register" (GRASP Controller), before multiple different kind of items can be added.
According to my interpretation of this GRASP Controller example, the Controller can indeed contain some "business rules". In other words I believe that the quoted statement that the GRASP Controller should not contain any business rules is incorrect.
I think so because of the following:
Now we can use some substitution logic of the above three things, to conclude a sentence like this: "The GRASP controller can contain implementation of business rules". Another example of business rules in the GRASP Controller is the Monopoly Game example. As illustrated in a diagram at page 352, the Monopoly Game class is the controller in the Domain layer, and is being invoked directly from the UI layer (i.e. there is no Application layer between these two layers). The controller method playGame looks like this in the code at page 383-384: Looking at the above system operation "playGame()" you can see that when a game is started then each player will take a turn. I consider that as a "business rule". For example, another "business rule" might be that only every second player will take a turn. Obviously this "business rule" is located within the controller. However, I do not think it is obvious why this should be considered as an appropriate level of work that should be done by the controller itself. For example, you might instead want to use another kind of collection object (implemented by yourself) to which you might delegate the behavior, as illustrated below: In the modified "version 2" above, I created a "PlayerCollection" class, which can be seen as an "Information Expert" since I put all the players into that class. Then I could delegate more work from the Controller. The original Larman implementation "delegated" part of "the work" to a private method "playRound" from the public system operation "playGame". If we change that implementation with some more inline code instead of the private method, we can get a third version looking like this: My point is not to claim that any particular of the above three versions of "MonopolyGame" is the best one. My point here is rather that it is difficult to use the GRASP Controller guideline to determine which of these classes can be considered as good controllers satisfying the conditions of delegating and coordinating to other objects rather than doing too much work itself. For example, when I look at my modified "version 3", I might think it contains too much work, iterating two nested loops. On the other hand, that code is essentially the same as the original Larman implementation with the only difference being that the inner loop of my version 3, has been extracted into a method of its own ("playRound") in the Larman implementation. In my opinion, it should be possible to consider all the three above versions as GRASP Controllers. The reason (IMHO) is that they do the same thing, and all of them implement a high-level system operation as the first object beyond the UI layer, which is the essential part of the definition, making it possible to reuse the class from different GUI's. In other words, I do not care too much about the other vague statements about coordinating and controlling the activity and not doing too much work itself. I hope that Larman will agree with me, and that he tries to improve the next edition of the book (if there will be a fourth edition) by clarifying the definition of the GRASP Controller and be more emphazising on the thing about "first object beyond the UI layer". There is obviously a need for such a clarification, since some people try to use the implementation guideline as some kind of definition about what kind of content that should be located in the controller, claiming that a certain class can not be considered as a GRASP Controller since it does too little delegation and coordinating and is implementing too much business rules itself. As already mentioned, I think the most vague part of the GRASP controller definition and guideline is the part that says it should "coordinate". On the other hand, a more well-defined part of the definition of GRASP controller, is that it should be the first object beyond the UI layer, since all applications with a decent layering should have some object that can be considered as the first object beyond the UI layer.
However, I think that the diagram at
[AUAP, page 203]
can actually be in conflict with the "first object beyond the UI layer" statement, in the
GRASP Controller definition.
For those of you who does not have the book, I can tell you that it illustrates six common layers in an information system logical architecture. For this discussion, only the three topmost layers are relevant:
|
Definitions and Guidelines
GRASP Controller definition
GRASP Controller guideline
References
[AUAP]
[GPSC]
|