Re: Enforcing domain rules
- From: "H. S. Lahman" <h.lahman@xxxxxxxxxxx>
- Date: Mon, 05 Feb 2007 18:19:16 GMT
Responding to Mikeon...
Suppose there is a system where you can create accounts. After
creation account is added to a repostory.
I want to ensure that there are no duplicates so I create a
specfication DuplicateAccountSpecification which I can use to check if
account is a duplicate of an existing account.
Where should I put the logic to make this verification?
sample architecture
UI
----
Services
----
Model
----
Infrastructure
I assume this is somebody's layered model but the nomenclature is different than those I've seen before so I am not sure of the semantics of the layers. Does Infrastructure represent direct access to the repository or is it simply a layer of disparate low-level services that can be accessed from any of the other layers?
In Services layer I have a method to create account. That method
creates account object, adds it to repository and commits changes.
Now I can enforce uniquness on the infrastrcture level, but that will
result in some bad exceptions.
If the infrastructure represents the repository, then you should probably do this, but the exceptions represent a correctness check that the check for duplicates was done properly in a higher level layer. IOW, the exception would never be raised if the higher level layers were implemented correctly.
If the infrastructure is more generic and just holds low level services, then then the implementation of the check might be implemented there. But it would be invoked from a higher level layer closer to where the problem is first manifested.
I can enfocre the check using DuplicateAccountSpecification on
Services layer by checking for duplicates before adding new account
to repository. That will result in domain not enforcing this rule
which means that it may be possible to bypass it.
I am not sure what the last sentence means. What domain is that? The repository? If so, see above; it is fair to implement a check in one layer while invoking it in another and then asserting that the check was invoked correctly for an exception.
Finally I can enforce this rule in the model code, but how. And by how
I mean a generic way, that lets me add, remove rules. I have few
ideas, but none of them seam very clean.
This sounds like there is something special about the Model layer (e.g., substantial parts of it are hard-wired for a particular RAD environment). So I can't speculate on the answer.
You omit a fourth choice: the check is executed in the UI layer. This would usually be preferred if the user is providing the account identity. That's because, as a general rule, one wants to validate user inputs as close to their entry as is feasible. (Deferring such checks can result in the need for complex Undos is the intevening layers, among othre things.)
However, the implementation of the check (i.e., the grunt work of querying the repository) doesn't belong in the UI layer. That's because the UI is concerned with display and data entry paradigms rather than data storage paradigms. So the UI layer would invoke some lower level service (e.g., in the Infrastructure layer) to actually perform the check.
That presents a problem if this is a CRUD/USER layered model because layers usually only talk to adjacent layers in such models. In that case the UI request would have to be daisy-chained through the layers as a sequence of service calls to get to the actual repository request implementation.
There is yet another possible problem: optimization. The repository will typically be the performance bottleneck on the application. Issuing a separate query to detect an existing account means two repository accesses for each add, which may still present a problem if other applications access the repository in parallel even if this application's data entry is via human interaction. This is the main justification for using the repository to check duplicates via an exception mechanism on a direct add.
But one can usually address such optimizations in the layer that talks directly to the repository without deferring the check. For example, the layer might read all account keys at startup in a single query and use a table lookup rather than a repository access to to check for duplicates. (It would also need to add/remove keys from the table as records were added/deleted during the session; but that is an optimization trade-off issue.)
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
hsl@xxxxxxxxxxxxxxxxx
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@xxxxxxxxxxxxxxxxx for your copy.
Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
.
- Follow-Ups:
- Re: Enforcing domain rules
- From: Mikeon
- Re: Enforcing domain rules
- References:
- Enforcing domain rules
- From: Mikeon
- Enforcing domain rules
- Prev by Date: Re: Relational-to-OOP Tax (was: Critique of Robert C. Martin's...)
- Next by Date: Re: Relational-to-OOP Tax (was: Critique of Robert C. Martin's...)
- Previous by thread: Enforcing domain rules
- Next by thread: Re: Enforcing domain rules
- Index(es):
Relevant Pages
|