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

[Boot] Model Booter #1428

Closed
2 tasks
virkt25 opened this issue Jun 14, 2018 · 11 comments
Closed
2 tasks

[Boot] Model Booter #1428

virkt25 opened this issue Jun 14, 2018 · 11 comments

Comments

@virkt25
Copy link
Contributor

virkt25 commented Jun 14, 2018

Description / Steps to reproduce / Feature proposal

Once #1221 is done OR in parallel to that PR, a booter needs to be created to boot .model.js files using @loopback/boot.

Current Behavior

  • Must manually bind models to Context

Expected Behavior

  • Automatically bind models to Context

Acceptance Criteria

  • Create a booter similar for model artifact type. Similar to other artifacts (controllers, datasources, repositories, etc).
    • A potential pitfall / something different about this booter compared to other artifact booters is that the CLI for this artifact will create a generated folder which will have base classes for the models for typing purposes that will be extended by the actual model classes. We probably don't need to pollute the Context by binding the base classes to the Context -- so need to determine a way around this.
  • Appropriate tests / docs

See Reporting Issues for more tips on writing good issues

@dhmlau
Copy link
Member

dhmlau commented Jun 14, 2018

I think it makes sense to include this in DP3, though we're a bit tight on time.
Let me mark it as DP3 and we can re-evaluate again as we finish the june milestone. thanks.

@dhmlau dhmlau added the DP3 label Jun 14, 2018
@bajtos
Copy link
Member

bajtos commented Jun 29, 2018

@virkt25 @dhmlau I am little bit confused why we need a model booter. AFAIK, none of our code is binding Model classes to context. In LB4, a Model is describing data interface and as such it's usually not injected via DI. Persistence behavior is provided by model repositories, and that's the entity we need to register in the context for dependency injection.

I am proposing to close this story as not relevant (for now).

Thoughts?

/cc @raymondfeng

@bajtos
Copy link
Member

bajtos commented Jun 29, 2018

At the moment, we need a reference to a model class at compile time to tell TypeScript what shape the arguments/return values have. In theory, it is possible to inject different implementation of model classes, but our current Repository design does not really support that IIRC.

See e.g. TodoRepository implementation in examples/todo/src/repositories/todo.repository.ts:

export class TodoRepository extends DefaultCrudRepository<
  Todo,
  typeof Todo.prototype.id
> {
  constructor(
    @inject('datasources.db') protected datasource: juggler.DataSource,
  ) {
    super(Todo, datasource);
  }
}

I suppose we could change the repository to allow custom Todo model constructor to be injected:

export class TodoRepository extends DefaultCrudRepository<
  Todo,
  typeof Todo.prototype.id
> {
  constructor(
    @inject('models.Todo') protected todoModel: Class<Todo>,
    @inject('datasources.db') protected datasource: juggler.DataSource,
  ) {
    super(todoModel, datasource);
  }
}

I am not convinced it's a useful feature - why and how would we want to provide a different model implementation? In my mind, one of the primary use cases for Dependency Injection is to allow tests to be written. When it comes to models, there was no need for mocking/stubbing model classes so far, see http://loopback.io/doc/en/lb4/Testing-your-application.html

In that light, and considering that making models injectable requires more changes than a new booter, I think this story is out of scope of DP3 and most likely out of scope of 4.0 GA too.

@dhmlau
Copy link
Member

dhmlau commented Jun 29, 2018

@bajtos and I had a separate discussion, and I'm good with leaving out the model booter.

@virkt25
Copy link
Contributor Author

virkt25 commented Jun 29, 2018

I'm ok with leaving out the story. For future when we do come back to this (if / ever) ... I would like the syntax for declaring a Repository to be simplified to not require the Model in < > and in the super() if that would be at all possible.

@bajtos
Copy link
Member

bajtos commented Jun 29, 2018

I would like the syntax for declaring a Repository to be simplified to not require the Model in < >

Without the providing the specific Model class as a specialization of the generic Repository class/template, TypeScript compiler would not be able to enforce correct usage of model instances returned by repository methods.

Consider the following example:

const product = productRepository.findById(1);
product.foo = 'bar';

Right now, TypeScript understand that product is of type Product and because there is no Product.foo property, it can report a compilation error.

If the Repository was not parameterized by the model class, we would have to return any type, thus disabling all further type checks and allowing the incorrect usage above.

I suppose we could parameterize individual methods, e.g. repo.findById<Product>, but that's cumbersome and leaves space for errors. Consider e.g.

const user = productRepository.findById<User>(1);

What can be done: split the model into an interface declaring properties & methods and the actual model class. Use the model interface to create a specialized version of Repository classes. I am not sure if the extra complexity and duplication is worth the benefits though.

@virkt25
Copy link
Contributor Author

virkt25 commented Jun 29, 2018

Oh I'm definitely not in favour of parameterizing individual methods! I had a feeling it won't be possible because we need it for typing information ... was just curious to see if there was perhaps a way around that I wasn't aware of. As much as I dislike the syntax, the benefit of having the type information is much more!

I don't think we need to add complexity / duplication to resolve this at all -- time and effort are better spent elsewhere.

@virkt25
Copy link
Contributor Author

virkt25 commented Jun 29, 2018

Talked to @raymondfeng and here's the summary of our discussion:

  • Context will serve as the registry of all artifacts so while we may not be injecting Models as a dependency from Context, Models should still be populated into the Context.
  • Will help with future work where we plan on discovering artifacts using @loopback/boot to ensure user can configure their conventions (... and I guess eventually CLI generation should respect that as well).
  • Will help with Workspace (when it's introduced for LB4) ... to again discover, display and manipulate models.

@dhmlau dhmlau added LB4 GA and removed DP3 labels Jul 4, 2018
@bajtos
Copy link
Member

bajtos commented Jul 30, 2018

Talked to @raymondfeng and here's the summary of our discussion:

  • Context will serve as the registry of all artifacts so while we may not be injecting Models as a dependency from Context, Models should still be populated into the Context.
  • Will help with future work where we plan on discovering artifacts using @loopback/boot to ensure user can configure their conventions (... and I guess eventually CLI generation should respect that as well).
  • Will help with Workspace (when it's introduced for LB4) ... to again discover, display and manipulate models.

Fair enough 👍

I feel this does not belong to 4.0 GA scope as we have defined it, I am relabeling this story as post-GA.

@raymondfeng @virkt25 please let me know if you disagree.

@stale
Copy link

stale bot commented Oct 28, 2019

This issue has been marked stale because it has not seen activity within six months. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository. This issue will be closed within 30 days of being stale.

@stale stale bot added the stale label Oct 28, 2019
@stale
Copy link

stale bot commented Nov 27, 2019

This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.

@stale stale bot closed this as completed Nov 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants