OOP Repository pattern #446
Replies: 19 comments 1 reply
-
Our CLI has a built-in option to generate your second example. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the quick response. I just tried it out. It generated the following: @Injectable({ providedIn: "root" })
export class TestRepository {
private store;
constructor() {
this.store = this.createStore();
}
private createStore(): typeof store {
const store = createStore({ name: "test" }, withActiveId());
return store;
}
} Unfortunately this leaves the @Injectable({ providedIn: "root" })
export class TestRepository {
private readonly store: ReturnType<typeof this.createStore>;
constructor() {
this.store = this.createStore();
}
private createStore(): typeof store {
const store = createStore({ name: "test" }, withActiveId());
return store;
}
} I find it really cool how the Btw, awesome job on this library! |
Beta Was this translation helpful? Give feedback.
-
If you want I can create a PR for the docs and / or the CLI, to improve them with regards to this. |
Beta Was this translation helpful? Give feedback.
-
I am pretty sure it was fine. Weird. @EricPoul do you remember? Seems like something is missing. I am from my phone. |
Beta Was this translation helpful? Give feedback.
-
I've just checked it in my repo and it's not an |
Beta Was this translation helpful? Give feedback.
-
There must be something I'm missing:
|
Beta Was this translation helpful? Give feedback.
-
Yep, I guess, because it's not marked as |
Beta Was this translation helpful? Give feedback.
-
However, I delete a |
Beta Was this translation helpful? Give feedback.
-
Maybe it's some ts configurations? |
Beta Was this translation helpful? Give feedback.
-
Here ts infers type from the assign in the constructor so ts won't allow assigning something different from the initial type later. |
Beta Was this translation helpful? Give feedback.
-
In the TS playground |
Beta Was this translation helpful? Give feedback.
-
Maybe it will be better to strictly type it |
Beta Was this translation helpful? Give feedback.
-
Or mention it in the docs |
Beta Was this translation helpful? Give feedback.
-
I don't mind both variants. It's private property that generates automatically so I don't think that it would bother someone. Just one thing, if it's really |
Beta Was this translation helpful? Give feedback.
-
I would prefer strongly typing it in the CLI, and also updating the docs. What about adding the Also an example with using a BaseRepository might be nice for the docs. Shall I make a PR, or would one of you prefer to do it? |
Beta Was this translation helpful? Give feedback.
-
The repo is created with |
Beta Was this translation helpful? Give feedback.
-
I'm not entirely sure what I have been working on setting up Cypress component testing for an existing application and the only hard part was getting the repository + store to behave properly. |
Beta Was this translation helpful? Give feedback.
-
@marklagendijk read this thread: #433 |
Beta Was this translation helpful? Give feedback.
-
I'm curious why the CLI doesn't generate more declarative code. Class fields can be assigned outside of the constructor. It's easier to read and requires fewer lines of code. Example, generated from CLI: export interface Test {
id: number;
}
@Injectable({ providedIn: 'root' })
export class TestRepository {
test$: Observable<Test[]>;
private store;
constructor() {
this.store = this.createStore();
this.test$ = this.store.pipe(selectAllEntities());
}
private createStore(): typeof store {
const store = createStore({ name: 'test' }, withEntities<Test>());
return store;
}
} Written more declaratively it can be as simple as: export interface Test {
id: number;
}
@Injectable({ providedIn: 'root' })
export class TestRepository {
private store = createStore({ name: 'test' }, withEntities<Test>());
test$ = this.store.pipe(selectAllEntities());
} |
Beta Was this translation helpful? Give feedback.
-
Currently the documentation suggests the following pattern for OOP repositories:
In many cases people using this pattern would want to use Angular root services so they add the
Injectable
annotation:The problem with this is that the
AuthRepository
now has a different lifecycle than theauthStore
. For applications this can be fine (because a root service is also a singleton, same asauthStore
which is a file-level singleton).However, things start to become problematic during testing.
I think it might be better to promote moving the store instance to a property of the repository. Besides that we now can also properly destroy the store instance whenever the service gets destroyed.
Example:
This is nice, however, this does not work well with base classes.
In the case that we want a base class we need to get a bit more creative.
Example:
Let me know what you think!
These are just some patterns I discovered during my struggles to setup component testing for an existing application.
I know it would have helped me a lot if these patterns would have been in the documentation.
At the same time it is hard for me to estimate how widely applicable they would be.
Beta Was this translation helpful? Give feedback.
All reactions