Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External validation against rule: Always Keep a Valid State in the Memory #65

Closed
linfengOu opened this issue Mar 5, 2023 · 2 comments
Closed

Comments

@linfengOu
Copy link

Hey there! Thanks for the work.
I've been utilizing your methodology in building my own project for near 2 years.

However I still have a question about this rule when external validation is needed: always keep a valid state in the memory :
Say if I have a big list of accounts, and they are organized in parent-children relationship, i.e. an account can be a top level account, or it can be child of a top level account.
I have this Account entity in domain layer and a NewAccount method which is supposed to create a valid Account entity:

type Account struct {
    id uuid.UUID
    parentAccountId uuid.UUID
    ...
}

By following the rule, I have to verify if parentAccountId is valid in the NewAccount method. But how? It requires to check database if this parentAccountId exists or not. Seems not possible in domain layer.

Right now I'm putting this check logic in repository layer, but seems a bit violating the rule : (

There are also other scenarios I can think of that maybe certain fields requires remote call to external system to valid - it requires services in application layer - it's not accessible from domain layer.

Any suggestions?

Thank you!

@m110
Copy link
Member

m110 commented Mar 11, 2023

Hey @linfengOu! Glad to hear our ideas were useful! :)

I think checking it on the repository level makes sense most of the time. After all, your domain code doesn't know where the parent account is stored and doesn't need to care. From the domain point of view, a valid parentAccountID would be "not empty" and this is what you can check in the constructor.

It's similar to things like enforcing unique email addresses. It sounds like domain logic, but it's just more practical to have a UNIQUE constraint on the database level and check it there (if your database supports it). Similarly, if you're using a relational database, you could have a foreign key constraint that won't allow using parent accounts that don't exist.

In a sense, this becomes part of the repository contract, even if not explicitly stated. You could include it in the interface comments, for example. Something like "Save saves the account, making sure the parent account exists".

When in doubt, I like to remind myself that repositories are not just dumb database proxies. They deal with the domain entities and have knowledge about them.

But if you wanted to do it the other way, you could also have the application command validate it. Or even a domain service or an "account factory" injected with something that checks if the account exists. As long as you hide the "checker" behind an interface, you should be fine. :)

Hope this helps!

@linfengOu
Copy link
Author

Thank you very much @m110!
I like your point about repositories are not just dumb database proxies. They deal with the domain entities and have knowledge about them.

I love the the idea to make check logic an app command as well. I'll give it a try.

Thanks again, and happy coding!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants