People who are using the DAO part of exposed, if y...
# exposed
g
People who are using the DAO part of exposed, if you have something like a repository layer in your application. Do you return the actual DAO from these repositories, or do you rather return a stupid data class of it?
j
For internal logic we (usually) use the DAO objects. When we return the data outside the application we map it to a data class (DTO).
to be fair, our testing setup isn't great...
g
Haha, that was my next question...
j
we do have some tests where as part of the test setup we write some data into the db first.
e
I recommend returning stupid data classes. The DAO entities are impossible to do any mocking with.. Unless you want all your tests to use a H2 DB..
g
Yeah. I was thinking about that. But if I want to use DAO classes, and then create a new entity when all repository methods return stupid data classes; i wont be able to do that? Then I have to do that one repository uses multiple DAO classes and binds them together, which I would like the service to do.
e
I can't quite follow.. can you dress that with some pseudo-code? 🙂
g
Let's say I do not return any DTO's from repositories. I and wanna create a new
StudentDAO
with some predefined
ClassDAO
with is a 1-* relation. So I have a method in a repository:
Copy code
fun createStudent(name: String, classes: List<ClassModel>) { 

//I can't pass in `ClassesDAO` here, given I never return that type from the repository.
So I have to use the `ClassDAO` in the `StudentRepository`

val classesDao = ClassDao.findAll(....)
But I wanna have a tight mapping between the repository and DAO. So for example, the only way to find
Class
entities should only be via the
ClassRepository
. But I don't wanna use the
ClassRepository
in my
StudentRepository
Because the service should be the one connecting the two of them. In my opinion.
e
Honestly, I prefer the DSL mode over DAO. DSL has no magic, you have full control, and you are able to write your
rowResult --> stupidDao
mapping logic manually
g
Yeah, most people seems to prefer the DSL. But fetching with relations is something I rather not do myself...
But I guess, you can't have anything...
e
Maybe CQRS pattern works better? Not repository-per-entity but rather implementations responsible for separate flows
g
Never heard about that. Will look into it. Thanks!
d
We made interfaces on our domain layer... which allows to have an implementation for DAO and one for tests... still not ideal, and for IDs you'd need something to map them to the id in the interface...
For all these problems, I was seriously considering alternatives like #komapper or kotysa...
g
Yeah. I'm thinking about just removing the DAO completely and just using the DSL, and just do the mapping myself. I don't have too many cases were that is needed.
d
I started with DAO and interfaces and then switched to the DSL... and stayed with the interfaces 🙈... It would have been nice to have the DAO, but all these points really made it a pain.
The two libs I mentioned aren't DAOs but they do handle the mapping for you.
g
Ah, I see. What was the main downside of using a interface with two different implementations? Was it just the mapping with the ids?
d
It complicated a bunch of things, like my tests -- I needed to make stub objects implementing that interface -- so I'm not really testing the REAL thing the application is working with -- sometimes that leads to subtle errors like making something nullable on the interface and the DAO and leaving it not nullable in the stub. That's apart from a bunch of boilerplate code just for testing I had to make.
g
I see. I'll just go with refactoring and using the DSL which then just return simple data classes. Then there is a good abstraction between the repositories and services I guess. The services does not know that exposed is even used. Which seems nice.
👍🏼 1
140 Views