altnetpedia

Developing Frameworks with consumer-selectable Inversion of Control

Modified: 2008/08/17 00:18 by jeremygray - Categorized as: Proceedings
Edit

Context

Given the requirement of creating an application framework that is extensible and leverages Inversion of Control internally (specifically through Service Locator and Dependency Injection), what strategies are available to allow:
  • framework consumers to configure the application framework to utilize the IoC container of their choice
  • framework extenders to leverage the framework's IoC in creation of their own extensions

Edit

Session notes

(Some of the following may be out of sequence or mis-attributed, but this is the best that I can recall of the session while writing up these notes afterward.)

A small group of attendees (approx eight in attendance by the end of the session) convened at 10:00 on Saturday morning to discuss the topic.

To frame the discussion, we asked who was using IoC actively.
  • One attendee is using it regularly, via a scratch-written IoC container (due to client concerns regarding bringing in open source containers)
  • A second attendee has experimented with StructureMap and Unity, but (unless I'm recalling incorrectly) has not used it in a production scenario.
  • The session convener (that's me, Jeremy Gray) has experimented to a small degree with a variety of containers but has to date not worked on a project where IoC was put in place (though many could have benefited from it.)
  • The remaining attendees were generally familiar with IoC but haven't yet had the opportunity to build up knowledge and experience in the space.

The question of what IoC containers are available for .net was brought up, with the following mentioned by one attendee or another (in no particular order):
  • Spring.net
  • Castle (Windsor)
  • StructureMap
  • Object Builder
  • Unity
  • Autofac
  • Ninject
  • (perhaps) LinFu

Moving more directly onto the main session topic, Jeremy described in brief the project that prompted suggestion of the session:
  • Writing an application framework
  • This application framework would benefit greatly from leveraging IoC internally
  • The application framework is to be extended in specific areas by first, second, and third-party development teams
  • The application framework is to be consumed by a variety of first, second, and third-party development teams in order to create end-user applications
  • It would be beneficial if framework extenders were able to do any of the following:
    • Leverage the container abstraction provided with the framework
    • Completely ignore IoC and the framework's use thereof
  • It would be beneficial if framework consumers were able to do any of the following:
    • Choose their own container (perhaps one already in use in their application, elsewhere within their organization, etc.)
    • Completely ignore IoC and the framework's use thereof

This led to discussion of what fundamental IoC container features could be assumed as a safe lowest-common-denominator subset that the framework could present via its IoC container abstraction
  • Service Locator, with the support for both default and named instances
  • constructor-based Dependency Injection

The subject of forcing container configuration requirements was brought up in the context of perhaps providing a configuration module abstraction (not unlike some of the "module" constructs offered by a few of the available containers).
  • One suggestion raised was to implement a common module and configuration model
    • This configuration model could then delegate down to a simpler IoC abstraction model that specific implementations would meet
  • Another suggestion raised was to go 100% convention-over-configuration so as to avoid the implementation effort of support for modules and a shared configuration model
    • This approach would require somewhat less of the framework developers, slightly more of those people adapting containers for use with the framework, but has the benefit of encouraging a degree of consistency that itself has a number of trickle-down benefits.

Along the way, a question came up about aspect orientation and how it relates to IoC
  • AOP relates loosely to IoC in that one of the most common approaches to AOP is with run-time interception, primarily
through the wrapping of dependencies that have already been abstracted through interfaces, where that abstraction through interfaces implies Inversion of Control, even if no IoC container as such is in place within the application.

The question of what AOP can be used for came up:
  • As always, the obvious examples are logging and security

The question of AOP performance was raised, leading to discussion of:
  • static weavers versus runtime interception
  • .net support for aspect-oriented development, with examples including the following:
    • Spring.net AOP
    • PostSharp
    • NAspect
  • debuggability (more accurately, the lack thereof in most cases)
  • possible drop in immediate understandability of code
  • impacts on build
  • concerns from development (and other teams) about the safety of static weavers manipulating compiled code

These topics lead one of the attendees to swing conversation back to what AOP is really good for, with the general response being the separation of completely orthogonal concerns.

Someone asked whether or not one could use AOP to separate out business rules, presumably so that they can be developed elsewhere, Versioned separately, etc.
  • Riffing on the question regarding business rules, validation was brought up as an example of something technically possible but almost surely not desirable to achieve via AOP.

This took the discussion off into further re-enforcement of AOP being best applied to concerns that are truly and transparently orthogonal.
  • e.g. both logging and security can either run successfully, fail silently (in the case of logging), or fail with exceptions (in the case of security) but neither of them really need to affect the callee, any state of the caller or callee, etc.
  • e.g. validation, on the other hand, could be externalized from a rules perspective, but the result of applying those rules needs to feed back into the state of the application in ways that are not a good match for AOP.

As discussion moved on from the AOP aside, someone brought up the issue of how one can introduce IoC to a team
  • Jeremy brought up the ever-persistent hyperfocus on testability as it relates to IoC, whether as a justification for it, a bonus earned from applying it, etc., as a lead-in to a few ways to introduce IoC to a team
  • There are two obvious entry points for IoC introduction.
    • The first of these is that ever-persistent point about testability.
    • The second is the easy replacement of plug-compatible dependencies. Commerce applications were brought up as an easy scenario for the justification of IoC on the basis of being able to easily swap out plug-compatible implementations of things like payment gateways, shipping providers, etc.
  • It was readily admitted that IoC can be difficult to introduce from other angles, and even from the two above, because IoC has simple primary effects but complex and powerful network effects that only become visible over time to team members new to IoC.

Sticking to the topic of testability for the moment, the group spent more time talking about getting people into IoC via the testability angle.
  • The challenge with coming at IoC from this angle is that one needs to sell two things at the same time, first the benefits of test automation and second those of IoC. Selling these two major changes in people's approach at the same time can prove difficult. So how can we make them less so?

Someone asked about whether or not other attendees had been setting code coverage requirements for their test automation.
  • Jeremy suggested that in his experience he found the requirement of specific code coverage to actually work against the team, in that it tends to generate poor tests that cover code, yes, but that don't cover it from the perspective of business requirements.

The quality (or lack thereof) of tests written from a TDD or TAD perspective brought up the subject of BDD.
  • Multiple attendees agreed that it was easier to sell BDD into a project environment, specifically with respect to management acceptance of BDD versus TDD. The primary reason for this is that while both are perceived as extra work BDD is more obviously related to providing a degree of requirements traceability and was thererfore met with more immediate favor.
  • THe increase in test quality of BDD versus TDD led Jeremy to mention that he had also noticed it resulting in a reduction of speculative development
    • TDD's focus on testing code makes it overly easy to write code speculatively (where by speculative I mean without a vetted business requirement for said code), given its focus on testing the code you write
    • whereas BDD focuses on validating the code's implementation of specification, which shifts the focus away from the code one writes to the code one _should_ write.
    • It was also mentioned that the focus on BDD can have an added benefit of leaving any speculative code as uncovererd by tests, which with a bit of occasional review can then result in either the proper coverage of that code or its removal from the codebase. This removal in turn increases the code coverage percentage, yielding a feel-good for the team but without increasing the risk of poor tests created solely to satisfy coverage targets.

Talking about selling TDD versus BDD brought up budgeting of time and resources to help people take the time to do things right, leading the discussion towards project management.

SCRUM was brought up as a way to empower team members to maintain good velocity without sacrificing high quality, leading to a question about accountability to management and how one can go about getting budget to do everything we had been talking about thus far within the session.
  • SCRUM and related techniques were the answer:
    • open sprint reviews
    • well-defined, well-communicated sprint goals
    • publically available sprint and product backlogs with full burn-down history
    • close collaboration with the Product Owner
    • estimation techniques like planning poker, etc.

Someone then raised the subject of producing quality estimates, so that teams can budget time for our various discussion topics. The specific question revolved around what to do when team members consistently produce poor estimates.
  • It is important to create a tight feedback loop between the estimate process and whatever light-weight (or otherwise) tracking of actuals is taking place
  • actively tracking burn-downs and regularly discussing impediments, missed requirements, etc. helps keeping people aware of the various overhead that can impact any one task
  • estimating more frequently, while relating back to recent actual values helps make new estimates more accurate
  • it is important to focus on the capabilities and output of the team and to not single out individuals who may be slower, produce more defects, or who are simply less accurate estimators
    • these are issues to take on with such team members on a one-on-one professional improvement basis, not in front of the team where you can all too easily single people out and reduce morale
  • inaccurate estimators can also be guided subtlely during the estimation process, by choosing to spend more time on estimating work that is frequently prone to estimate inaccuracy

As time wound down, someone asked what they can do to get this all started when it is so hard to see the benefit until after it has been done over an iteration or three.
  • The generally-agreed answer is that doing these things, if you think they are appropriate for the job at hand, is simply a part of doing your job professionally.
  • Take these on guerrila-style, if necessary, sneaking them into iterations, just a bit of improvement here and a bit there, until they show enough success to start surfacing them more explicitly in iteration plans, to management as a part of the process, etc.
    • As an example, The subject of stealing project time for reduction of technical debt was brought up as a way to help a team save itself from within
      • with a bonus suggestion of allowing people, given that individuals always have different pet peeve pieces of debt within any system, to choose their own favorite piece (or pieces) of technical debt to reduce during a given iteration. This does great things for morale in teams that often feel like they are always working on things someone else wants (whether project management, a software architect, or what have you) and never on something that they want. It's a small win, but the reduction of each piece of debt they personally believe in can make them feel all that much better about the project and their role within it.

ScrewTurn Wiki version 2.0.36. Some of the icons created by FamFamFam.