-
Notifications
You must be signed in to change notification settings - Fork 1.1k
docs: add geo-coding service to Todo tutorial #1441
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
Conversation
9266b9b to
98ac0f2
Compare
| geocode(address: string): Promise<GeoPoint[]>; | ||
| } | ||
|
|
||
| export class GeocoderServiceProvider implements Provider<GeocoderService> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why we don't use @serviceProxy - http://loopback.io/doc/en/lb4/Calling-other-APIs-and-web-services.html#declare-service-proxies-for-your-controller.
At the moment, services are backed/configured by datasources. If we want to promote service as the 1st class artifact, we probably should evaluate the possibility of dividing datasource into two types:
datasourceservice
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I started to look into testing services, I found @serviceProxy to make testing difficult, because tests cannot use the same code path for obtaining the service proxy instance as the production code uses.
See this integration test for an example:
I am of the opinion that integration tests should not be using Application, Context and Dependency Injection, instead they should instantiate all classes directly from code. This makes refactorings easier, because all dependencies and couplings are explicitly expressed in code and IDE tooling can update them accordingly. (Compare that to acceptance tests where a lot of configuration is based on convention and string names.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we did not need to tweak datasource settings to add caching proxy, the code would become even more simple:
const dataSource = new GeocoderDataSource();
service = new GeocoderServiceProvider(dataSource).value();Originally, before support for booting datasources was added, this used to be a one-liner. I think we may be able to get there using default arguments in the current design too.
service = new GeocoderServiceProvider().value();At the moment, services are backed/configured by datasources. If we want to promote service as the 1st class artifact, we probably should evaluate the possibility of dividing datasource into two types:
- datasource
- service
I am pretty happy about the current design, to be honest.
- A datasource is a long-living singleton-like object that manages state shared by all incoming HTTP requests - PersitedModel definitions, connection pool, etc.
- A
Repositoryor aServiceis a lightweight cheap-to-create facade exposing user-friendly API to controllers, leveraging datasources to do the heavy lifting.
In my mind, a Service (or a Service Proxy) is similar to a Repository.
@raymondfeng thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am going to land this pull request. If there are any changes identified in the outcome of this discussion, then I'll open a new pull request to address them.
Such changes are likely to affect the following places:
examples/todoimplementation- "Calling other services" docs
- "Testing your application" docs
shimks
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what approach we should consider with the 'bonus' service proxy tutorial. I think the service proxy tutorial should live in its own sidebar entry under something like 'advanced tutorial' so that it can live alongside with future tutorials on features such as relations. Thoughts?
|
|
||
| To call | ||
| [other APIs and web services](./Calling-other-APIs-and-web-services.html) from | ||
| LoopBack applications, we recommend to use Service Proxies as a design pattern |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is a Service Proxy? I think a link to its definition (either our own or external) would be helpful here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. The concept of a Service Proxy is described in Calling-other-APIs-and-web-services.html. I think it should have it's own page in http://loopback.io/doc/en/lb4/Concepts.html, but that's out of scope of this pull request.
I have described Service Proxy in this very same paragraph:
a design pattern
for encapsulating low-level implementation details of communication with
3rd-party services and providing JavaScript/TypeScript API that's easy to
consume e.g. from Controllers.
I'll reword this paragraph to make it (hopefully) easier to understand.
| $ lb4 datasource | ||
| ? Datasource name: geocoder | ||
| ? Select the connector for geocoder: REST services (supported by StrongLoop) | ||
| ? Base URL for the REST service: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these prompts were defaulted, I think we should still add in the default choices after the colons
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default choice is an empty string.
| endpoints. | ||
|
|
||
| #### /src/datasources/geocoder.datasource.json | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a link to a page explaning what the settings actually mean in context to the connector would be great here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, will add.
|
|
||
| ### Implement a service provider | ||
|
|
||
| Create a new directory `src/services` and add the following two new files: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do these new files do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in be80a19
|
|
||
| ### Register the service for dependency injection | ||
|
|
||
| Because `@loopback/boot` does not support loading of services yet (see |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want a place holder for this section until the boot feature can be completed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by a placeholder? IMO, the content of the tutorial should describe steps that people can do right now (as of DP3).
The pull request adding support for automatic loading of services should update examples/todo and this tutorial section to match the new simplified approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, I think I had this mistaken with something else :p
| } | ||
|
|
||
| setupServices() { | ||
| this.service(GeocoderServiceProvider); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should highlight this section or at least mention it before to make it easier for the readers to identify what's been added
|
|
||
| Previous step: [Add a controller](todo-tutorial-controller.md) | ||
|
|
||
| Next step: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be adding a link to the geoservice section as a 'next step' if it's a bonus?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, why not? The reader finished the core tutorial and the next step is to look at bonus sections.
In my understanding, the Todo tutorial is matching the implemention of In my mind, integrating with backend HTTP services (SOAP, REST, Swagger/OpenAPI) is one of the primary use cases for LoopBack and therefore it deserves a mention in the first tutorial we are presenting to our users. Maybe I should reorganize the content to better integrate the new section about services into tutorial structure and flow? I choose "bonus section" approach because it seemed to be the fastest way. The task of updating the Todo tutorial was not in the original acceptance criteria of #1311, I discovered it while updating the Todo example project. To move this pull request forward (and finish #1311), I am proposing to keep the current "bonus section" structure and defer any improvements/reorganization to a follow-up issue. Thoughts? |
98ac0f2 to
be80a19
Compare
Sounds good to me 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| use Service Proxies as a design pattern for encapsulating low-level | ||
| implementation details of communication with 3rd-party services and providing | ||
| JavaScript/TypeScript API that's easy to consume e.g. from Controllers. See | ||
| [Calling other APIs and web services](./Calling-other-APIs-and-web-services.html) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.md here so that users browsing the docs from github can go to a valid link
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, fixed.
be80a19 to
aa8aed3
Compare
aa8aed3 to
e236423
Compare
Update Todo tutorial - describe how to add a Geocoder service.
See #1311
Checklist
npm testpasses on your machinepackages/cliwere updatedexamples/*were updated