kmathy / ngx-reduxor

ngx-reduxor: save time by generating ngrx architecture with no effort!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Discussion about the structure

lexcaraig opened this issue · comments

Issue Type

Suggestion

version + node environment

Actual behavior

The service is included in the store

Expected behavior

It is a great practice to always have the services into the core folder/module. For the future use of the other modules of components. And So all of the NgRx boilerplate remains inside of their own folder.

example (repo, code,...)

app/
   core/
       services/
           auth/
               auth.service.ts
               auth.service.spec.ts
       store/
           auth/
               auth.<effects,reducers,actions>.ts
           all-effects.ts
           app.store.ts
           store-reduxor.module.ts

What do you think about this?

Hi Lex,

I now have plenty of time to work on this tool :)

You're right about this structure, however we need to think about this.
If we follow your suggestion, it means that the StoreReduxorModule needs to import the CoreModule to access to the services provided. Otherwise, the effects won't work. The tool, at the moment, is helpful to create and manage entities (in the future release containing @ngrx/entities). We can also use it to manage small actions or bigger ones.

At the moment, a lot of people don't use this structure. However, we can think to provide a way, like an option, so that the user can have more flexibility and not just an only way.

I have also the intention to create a config file containing all the options, and we can set the option directly on the file or via the generator. What do you think about this?

I would like to give my opinion on this one:

I have also the intention to create a config file containing all the options, and we can set the option directly on the file or via the generator. What do you think about this?

Great idea and a powerful one in terms of setting a personalized and reusable structure.

It is a great practice to always have the services into the core folder/module. For the future use of the other modules of components. And So all of the NgRx boilerplate remains inside of their own folder.

It seems to me that this is the best practices for a normal angular project, but on the other hand, NgRx is a completely different approach to state management. In it, the components should tend to access the services trough actions and the NgRx effects. So it is logical to put most of the services in the store folder...

Although not a definitive structure, one reference that could be used, is the @ngrx example application.
They do not have a 'store' folder per se. The ngrx functionality is intricately associated with each 'entities/features'.
Here is a folder print of it:

+---auth
|   +---actions
|   +---components
|   |   \---__snapshots__
|   +---containers
|   |   \---__snapshots__
|   +---effects
|   +---models
|   +---reducers
|   |   \---__snapshots__
|   \---services
+---books
|   +---actions
|   +---components
|   +---containers
|   |   \---__snapshots__
|   +---effects
|   +---guards
|   +---models
|   \---reducers
|       \---__snapshots__
+---core
|   +---actions
|   +---components
|   +---containers
|   +---reducers
|   \---services
+---material
+---reducers
\---shared
    \---pipes

'auth' and 'books' have their own files for actions, reducers, effects and services, including the components/containers and guards.
And the layout also has it (in the core folder)

Of course this is highly dependent on the actual project, so my argument is debatable. It is here only for consideration. Ideally the above mentioned config file would give one the power to readily choose different types of templates.
Well it is Christmas, there is no problem in wishing for world peace and a freely configurable generator ;)

Happy Holidays.

Hi @paean99

Thanks for your opinion! It seems that the idea of a config file is not bad, so it can be interesting to open a new issue to list the main options and their expected behavior.
I'm also open to PR and some kind of help 😄

About the ngrx structure provided, I'm not totally agree with them. Maybe this can fit to some use cases, but I have to use a different approach to one of my project. Also, I wanted to separate the store logic from the rest of my app. @lexcaraig told me about a solution to easily import these files by configuring the tsconfig file. it was also easy to import the reducer and effect in the module and finally, provide this module for the entire application.

Merry Christmas both 🎅

This is a really good discussions, however, to answer @kmathy question:

If we follow your suggestion, it means that the StoreReduxorModule needs to import the CoreModule to access to the services provided. Otherwise, the effects won't work. The tool, at the moment, is helpful to create and manage entities (in the future release containing ). We can also use it to manage small actions or bigger ones.

In my opinion, it is also a good practice I think to have a index.ts file from this guide https://angular.io/guide/glossary where you can just import everything from the service folder and pick only the service you need.

and to add to the storeModule we just need to import @app/services/ the index file. If this makes sense.

I don't totally agree with the NgRx example app structure since I think you have to completely separate your state management(ngrx boilerplate) from angular boilerplate itself. So we can actually tell where the core logic/services of our app is located to make it more meaningful if this make sense. Anw, @kmathy thank you for the invitation. Let's see can I contribute here. :)

also, what do you think of this? @kmathy

/**
 * ngrx
 *      app.effects.ts
 *      app.meta-reducers.ts
 *      app.reducers.ts
 *      app.state-serializer.ts
 *      ngrx-store.module.ts
 */

Just thinking of much more organized and meaningful boilerplates. :)

Happy holidays.

Let me know if you are good with this. If ever I can enhance it and make a PR. :)

There are a lot of changes with your architecture. At the moment, the tool is not widely used so we can do this, but in the future, we have to be careful with this kind of changes to avoid too many Breaking changes.

However, I like it! Can you just explain me what do you mean by "app.state-serializer"?

Also, the user can choose where to put the generated files using the config file I'm writing. We can also add a new option to let the user choose the directory to put services for example

@kmathy the config file is awesome. But my point here is we can have an option in config file or make this structure by default if nothing is changed in the config file. My proposal like so:

/**
* ngrx
*      basic/
*           basic.actions/effects/reducer.ts
*      crud/
*           crud.actions/effects/reducer.ts
*      app.effects.ts
*      app.meta-reducers.ts
*      app.reducers.ts
*      app.state-serializer.ts
*      ngrx-store.module.ts
*/

I just actually separate the codes where they I think they belong like for example i put all the metaReducer into its own file in order for the other developer to be able to add their own metaReducer with ease and don't have to worry where to put what they're adding.

The app.state-serializer that I added is actually a state management for the angular routes. It is also a feature by NgRx, so basically I'm just maximizing or taking advantage of all the features given by the NgRx. state-serializer is actually tracking for the routes via state management and other developers can just edit their custom serializer like so:

import { RouterStateSerializer } from '@ngrx/router-store';
import { RouterStateSnapshot, Params } from '@angular/router';

/**
 * The RouterStateSerializer takes the current RouterStateSnapshot
 * and returns any pertinent information needed. The snapshot contains
 * all information about the state of the router at the given point in time.
 * The entire snapshot is complex and not always needed. In this case, you only
 * need the URL and query parameters from the snapshot in the store. Other items could be
 * returned such as route parameters and static route data.
 */

export interface RouterStateUrl {
  url: string;
  queryParams: Params;
}

export class CustomRouterStateSerializer
  implements RouterStateSerializer<RouterStateUrl> {
  serialize(routerState: RouterStateSnapshot): RouterStateUrl {
    const { url } = routerState;
    const queryParams = routerState.root.queryParams;

    return { url, queryParams };
  }
}

This is also recommended by NgRx team.

Basically I aim for just a cleaner and more meaningful code by putting them in their respective places/file.

Here are the ngrx-packages.

https://github.com/ngrx/platform#packages

About the structure, we can add an option to dispatch the services in the store folder or in another folder.

I agree with your proposal, I like it and it is more meaningful!
I wanted to add a new generator using the ngrx/router feature in the future, but we can already add it. However, we need to be careful: I don't think all developers use the whole features provided by the ngrx platform, so we need to do the followings:

  1. Create a new generator called setup
  2. In this generator, we ask some questions like "Do you want a router state management?" y/n
    2.1 Note: Questions are dynamic: if the developer has already setup a feature, the question doesn't appear anymore. If he has all the setup, this generator is disabled.
  3. Following the answers, we create the right structure for the developer + change configuration if needed.

For convenience, we can "disable" some generators if the developers does not have the required modules. No router state management if he hasn't the @ngrx/router-store installed AND if no router-store module setup (like your state-serializer). It is convenient to prevent errors or AoT compilation.

The main idea is implemented