Should one use Service Location or Service Injection

This is just one opinion – Sakai deeply loves both Location and Injection – both will be around for a *long* time.
My rough rule of thumb actually is to use Location in tool code and Injection in Service code. Although my personal example code (Presentaion tool) uses Injection for the tool jsut to show how cool I am.


Here is my logic – feel free to disagree.
- Tools simply want a service – they just want to find it and use it – end of story – there is little reason to expect that a system admin will want to wire the resources tool to use one UserDirectory impl where the chat tool uses a different impl. I think that injection is most valuable when there is a “re-wire use case”. I like to see tool code more declarative and easy to read and modify. For example when we just write tools in PHP, Ruby or JSP, there will be no “injection” – just use locator and be happy. Location is why we can easily do thins like JWS, JSP, etc. DO don’t diss location – it is your friend.
- Injection is *hard* to debug – sheesh – how many people put log statements in their setters? If it is harder,why do it unless there is some value that we can identify. Why make all the poor saps writing tools do Injection to be cool? *Write less code when possible*…
- I also am not a fan of moving code from Java to XML – some folks *love* the notion that they write 1000 lines of XML so they reuse 200 lines of Java instead of just writing 400 lines of Java. People will say “my IDE” checks the syntax of the XML file – I say – sorry – vi does not do this :)
- Services are where rewiring is likely to happen. For example, we might want to give the SiteService a version of the UserDirectoryService with some little aspect thrown in to log the interactions (silly example) – or perhaps we just want some cool system-wide parameters that get poked into things.
- It *is* possible to confuse Spring and overwhelm it by asking it to resolve too much wiring across the whole system at initial startup – using location allows resolution/lookup to happen without forcing Spring to figure out startup order – the complex bits are wired *together* at startup – and then those simpler things where you just want to do look up are resolved later in system-wide lifecycle. So for me – we should use wiring when there is a benefit – not just because it is seen as “cool”.
- I also strongly prefer injection in Services as this may someday allow us to go “distributed” or “SOA” or “eFramework” – by wriging in clever proxies instead of the real impls – we can seamlessly wire up a Sakai system that puts different servers on different physical hardware. Service injection is *far better* for this use case than location – in some ways if we wired services to each other with location only this distributed SOA implementation wouldbe much harder.
- Also for something like setting the provider – we would be insane not to use injection and Spring – there is no more elegant way to do this – especially when bean properties are enhanced by system-wide properties in Sakai – so the easy stuff comes from one place – while the tricky wiring is always available when you have a need.
Again – this is just my crusty old school feelings and I don’t push my ideas on others – so there is a wide range of approaches across Sakai – This is cool and a strength of the flexibility of Sakai.

4 Comments

  1. Andrew Thornton says:

    Sorry Chuck, gonna have to disagree with you on this… No doubt Nig’ll drop in
    too…
    IMO service location is bad! The only time it’s excusable to use it, is if
    you’re forced to use legacy view techs or broken apis. Even then you
    should make serious effort to protect yourself from it.
    - Everytime you use a cover you make it incredibly hard to unit test that class.
    - Covers make it harder for a sys-admin to diagnose problems in a single tool’s
    use of an api.
    - The use of Covers reduces your code reusability. OK in the case of the Sakai
    Covers this is less of a problem, because e.g. it’s unlikely that there will
    ever be a second SiteService. However in general, Covers force your code to
    live in the assumption of there only ever being one impl, when a later refactor
    of an API make bring into existence a different usage pattern. (Yes in that case
    you’d have to rewrite, but we’re asking how much do you need to rewrite…)
    - A better solution for JSPs and other such dirty techs would be to pass in
    objects for them to use. I cannot believe that anyone would think it a good
    idea to write
    “> may be a bit of text
    You shouldn’t be doing the work in the JSPs so just protect them from it. It
    really isn’t that hard to put things in requestAttributes and in the
    pageContext maps so do that instead.
    - How is injection hard to debug? I don’t get that argument… I mean it’s
    either set in the application xml or it’s not.
    - I too find the XML nature of the wiring tiresome but there are things that
    could be done to improve that. (Spring 2’s dynamic conf, Simpler naming
    schemes, Public/Private Spring contexts…)
    - The confuse spring argument is simply wrong. You cannot *confuse* Spring, it’s
    not some animal in a black box, the rules that the ApplicationContext follows
    are clear: The Dependency Graph must be Acyclic. (It can cope with some Cyclic
    graphs, but IMO cyclicity is just wrong.) Every time you think you
    need a cyclic dependency send Antranig an email. He’s well versed in beetle
    crushing.
    - The complexity argument is bunken for tools anyway. Tools get wired up as the
    webapps that contain them are started up. That means that the shared context
    has already been completely created by the time the tool starts. Thus it should
    be clear that anything that goes wrong with spring at that point is the tools
    fault and cyclicity will be found there.
    Thus, to reiterate only use Service Location if you’re stuck using a dirty view
    tech or a badly written api. Even then you should seriously look at what you’re
    doing, there’s probably a better way to write your code so that you don’t have
    to do this.
    andy

  2. >”my IDE” checks the syntax of the XML file – I say >- sorry – vi does not do this :)
    Nice vi shoutout. :)
    Any chance you’ve gotten a head start on our javascript vi implementation? ;)

  3. Charles Severance says:

    Steven – Does Sash do vi?

  4. Well, basically Andy said it all – there’s not much to add. Always use injection where it is “possible”
    Spring wiring is not just “cool”, it is *correct*. For all the reasons that Andy points out. People are legendarily bad at anticipating the use cases for their code. Just because you can’t imagine the “re-wire use case” right now doesn’t mean there isn’t one. The Sakai codebase is littered with the design results of people who considered that their conception of the reusability of their code artefacts was the *correct* one for all time. A little more humility would have seen them use injection and admit that they didn’t know it all.
    Naturally this sort of thing is always going to be a judgement call – at some point the “bean world” stops, and “normal code” starts. But this conception that “injection is only for big architecture boundaries” is incredibly limiting, and reduces code quality.
    I’m also not a fan of moving “code” from Java to XML, but what you move into a Spring file is *not* code, it is configuration. Java code is for algorithms, XML is for configuration. It’s always great to have everything in the right place.
    Yeah, now the point about the “scripting” languages is very interesting. To the extent that they “can’t” participate in injection, this indicates that there is something wrong with them – but on the other hand it makes perfect sense that a dynamic code artefact *also* needs to be able to express dynamic dependencies. I think the best way to deal with this problem would be to create some kind of “mini-injection” library that we use to host these things so that they can express their dependencies in a clear and documented way (but also in some kind of idiom appropriate for each language), rather than just blindly fetching beans and stuff whenever they want.
    To me, these are environments for “experimenting” and “prototyping” in – and *always* at ‘leaf nodes’ – I don’t think anyone would dream of trying to create a “bean” in PHP/Ruby that could then participate in further injection – although I’d be interested to hear some use cases for this :P
    Once you have got your logic right and your tool is mature, you can take it out of the hands of the users/designers and “upgrade” it to a proper artefact using injection. This is why I am fond of the idea of getting designers to use BeanShell (http://www.beanshell.org/) for their “experimental” Sakai tools rather than Jython/PHP/Ruby, since once they are finished, the developers can inherit the code as is. All we need is a little “packaging syntax” for
    scriptlets to declare their dependencies in a standardised way rather than grabbing the bean context explicitly.
    It’s all about *standardisation*, Chuck! And I know you like that. Going from Location -> Injection is exactly the same kind of transition we had from Ant -> Maven.