

Angular-tips: Consuming services - Foxandxss
http://angular-tips.com/blog/2013/08/consuming-services/

======
lusr
1\. This tightly couples the service to the view. Changes in the view and/or
service will potentially result in nasty surprises and spaghetti code. For
instance, what happens if the business processes change one day and "login"
needs to return "logged in but email address unconfirmed"? You want the rules
to deal with that scenario confined to a LoginController, not scattered around
through each view (consider: an omnipresent login box view vs. a login/signup
form view used when a user performs an action that potentially requires login,
e.g. "Checkout")

2\. In reality, this simple sample obscures what happens in the real world
when you add an input for the user key & password:

a. you will need to pass the parameters to the auth service. At that point
hopefully you will won't do anything crazy and will simply e.g. bind the user
key & password to $scope properties, and pass the scope properties through to
the auth service.

b. As stated in (1), your login & logout controller functions need to consider
the result of their auth calls and map that result back to a meaningful state
for the view -- in the simplest case, it'll just be "logged in" or "logged
out", but it can also be e.g. "logged in but email address unconfirmed", which
could require a message to be displayed to the user. The best place for this
state is again a $scope property.

So, in practice you would just use a $scope.loggedIn or $scope.user property
maintained by the controller login() and logout() functions to resolve this
issue.

~~~
aidos
Is it not ok to have all of that state you're talking about down in the
service? In my experience any state you have in the controllers can be
problematic in bigger apps. When I started out I used to proxy everything
through the controller but I've found that you end up with a lot of
duplication that doesn't ever seem to pay off.

When you're talking about the various auth states you might have - they could
be changed by more than just this view. That state could also be exposed in
different controllers / views in different ways. Sort of seems like the state
that each of those would use is the same (that in the service) - so is it ok
for the views to just reference that state in the service directly?

Interested in hearing where that falls down. I'm fairly new to developing rich
interfaces and I've struggled to find completely deinitive information on how
best to architect these patterns. Lots of examples out there bind the views to
the services but that may be shortsighted.

~~~
lusr
I'm mostly a back-end developer and I don't have much experience with rich
front-end interfaces other than my own little side projects and a WPF project
from about a year back - however, I do believe the same principles apply to
both front- and back-end design.

Specifically, you should be following the SRP - duplicated code is a symptom
that you are not. Without seeing your code that you feel doesn't pay off, it's
difficult to answer your question more directly.

I will say there's no reason you can't design your server-side services to be
consumed directly by the view, in which case I wouldn't see a problem
referencing the service directly from the view (e.g. the UserService exposed
by the server implements (a) normal login, (b) login as part of checkout and
(c) registration).

Alternatively, you could build a client-side service to wrap the server-side
service and reference that directly from your views (e.g. a UserController
that wraps the UserService and is consumed by (a) the omnipresent login view,
(b) a login/signup view, and (c) the registration view).

Over and above this, there is some middle-ground where you reuse _structures_.
For example, a User structure (with IsAuthenticated, UserName, FullName etc.)
would be assigned to a $scope.CurrentUser property for the views. Consequently
you don't reimplement the User object the service implements, and you don't
vaguely depend on the entire UserService, but the data contract the view
_does_ depend on from the controller is still explicit by looking at the
$scope definition in the controller. Similarly, the operation contract is
defined by the controller functions. This improves maintainability and
readability IMO.

------
aidos
This seems pretty obvious but it highlights an issue for people approaching a
framework like angular. There are bits of magic that happen and you're never
quite sure where they end. In this case it's just basic js assignment
behaviour.

On a slightly deeper level it raises the issue of how much the view should
know about the services. The final result here is a lot less code at the
expense of the views directly interacting with the services.

~~~
Foxandxss
I really appreciate your answer. As I said in the first post, I am a learner
too, so I will update it with your insights :)

------
ghc
Whenever I teach a Python workshop I have to make sure to go over this or it
leads to confusion for about 20% of people.

But that's for new programmers. Either AngularJS is attracting people very new
to programming, or there must be some popular language (not Haskell) where

    
    
        a = 10
        b = a
        a = 20
        b == a is True
    

is still true. What language that is, I don't know.

~~~
lusr
The problem is that the types in Javascript + dependency injected AngularJS
services are hidden. If you forget that "auth.loggedIn" is a value-type, you
might unconsciously assume it's a reference type. This is one reason I prefer
statically-typed languages -- it's much more difficult to make this sort of
mistake since the type information is always visible even if you have the most
basic IDE.

------
Foxandxss
Hello friends, I updated the post with your new insights. I hope you find it
better. If not, please reply all you need or even better (Make some pull
requests :P).

As I said in the first post, I am the first who is learning Angular.js but I
find that teaching what are you learning is the best way to learn. So here am
I teaching the best I can.

Of course, there is things that I ignore, so I really appreciate all your
comments, so I learnt a LOT about services today.

Thank you.

------
likeclockwork
What happens when you have two controllers sharing the same service in
different parts of an app and both of their associated views need to reflect
the state of the service?

I don't think a digest loop would be called on the other scope if they are
siblings rather than descending from each other.

Maybe this isn't a real problem, but it's something I've wondered about when
it comes to this sort of thing.

