Grails: Can I use domain objects when I don't

2019-04-06 05:51发布

Some of my domain classes are getting rather rich: They implement an interesting comparable, might have plus, minus, multiply and div, many have some convenient getters which call services and determine complicated things. And most of all, they have the right properties. I am using these both for the normal "database transactions" and also in times when I just want an object that has all those methods but may not want to save it.

My teammates are convinced that this is very bad, and advise that I should be using DTO (Data Transfer Objects) which, as I understand, would be a POGO/POJO with one of the domain class' code copy/pasted in. This seems really un-dry, and I can't see the benefit. Is there something wrong with using domain objects as regular objects from time to time? Am I missing the point of DTO's?

2条回答
▲ chillily
2楼-- · 2019-04-06 06:32

Grails domain classes are somewhat misnamed, since an application's domain tier is usually made up of persistent and non-persistent classes. But Grails domain classes are always persistent. You can have non-persistent domain (in the traditional sense) classes but they would have to be in src/groovy or src/java. That can be frustrating because then the domain tier is split in the application into two places. We've had requests for non-persistent domain classes, e.g. something like static persistent = false or something similar, but it's not implemented yet.

I think if you want to take advantage of the non-persistent features of domain classes (e.g. validation, dependency injection, etc.) then it's fine to have some classes that could be database-backed but aren't. You just need to document that in the code or have some sort of convention, e.g. a special package structure or naming convention. If you never call GORM methods like save(), list(), findAllByFoo(), etc. then there won't be any database access.

As far as DTOs go, they can be un-DRY but there's a plugin that helps - see http://grails.org/plugin/dto. It hasn't been updated in a while but I'm pretty sure it still works. It has a nice feature where it will create a DTO instance from a persistent domain class instance with the syntax domainObj as DTO. You do need to keep changes synced between the classes, but the initial DTO generation is automatic via a script.

查看更多
太酷不给撩
3楼-- · 2019-04-06 06:51

I think you're in the right path.

1 - The moment you have to create a class only to take care of a domain class, you make your model more coupled. You are creating more dependencies, which is clearly bad. Your objects should be capable of taking care of themselves.

2 - The model your friends are talking about is actually known as the Anemic Domain Model, where you have data separated from the logic of your program and it was first described by Martin Fowler as an Anti-Pattern. This separation between logic and data is very used in procedural programming but not in Object Oriented Programming (the purpose of OOP is the exact opposite).

3 - Reduces code reuse.

4 - Is harder to test, once you have to initialize the logic separated from your data. At the same time, data leaks through your system.

DTO is something you could use, for sure. But it is not advised that you do though. It was initially designed to carry data(objects) through processes or tiers. Then, for some reason, people started using it between layers, which is not worthy. Makes your program more complex (once you have these entities spread across your application) and it allows global access.

What you are doing is called Rich Domain Model, and there's no problem of using it. But, of course you should be careful with that. If you see your class carrying too much responsibilities, then maybe it's time to design another classes to help (maybe you're breaking the SRP principle).

Take a look at how domain objects are designed in Grails. They encourage you to write rich models (validation, DB transaction etc.).

查看更多
登录 后发表回答