7

I have a User entity which has a HasCompletedSecurity property which indicates whether that particular User has answered the number of security questions required by the system. The number of security questions the system requires is configurable and retrieved from a config file. How should the User class access the configured information?

I currently have an IConfigurationService interface behind which I have implementations which use the ConfigurationManager or the Azure equivalent if it is available. I've encapsulated access to my DI container through a static InjectionService class, and am currently resolving the configured value like so:

public class User
{
    private static readonly IConfigurationService _configurationService = 
        InjectionService.Resolve<IConfigurationService>();

    public bool HasCompletedSecurity
    {
        get
        {
            // Uses the static _configurationService to get the 
            // configured value:
            int numberOfRequiredResponses = 
                GetConfiguredNumberOfRequiredResponses();

            return this.SecurityQuestionResponses.Count()
                >=
                GetConfiguredNumberOfRequiredResponses();
        }
    }
}

This is of course an example of the ServiceLocator anti-pattern, and I don't like it one bit. The static dependency makes unit testing anything which uses this class awkward.

I'm using the Entity Framework and taking a cue from here I don't want to pass my entities through a DI container to give them their dependencies, so... how should I be accessing the configured value instead?

Edit: With this exact example to one side (and I do appreciate the suggestions as to the correct architecture for it), the larger question I'm interested in is how do you manage non-static references to services from entities? Is the answer to just architect the entities in such a way that you never need to?

Steve Wilkes
  • 7,085
  • 3
  • 29
  • 32
  • What's wrong with constructor injection? – jgauffin Jan 31 '12 at 13:39
  • Taking a cue from [here](http://www.udidahan.com/2009/06/14/domain-events-salvation/), I don't want to inject anything into my entities. To use constructor injection, I have to wire the entity framework up to construct the entity through the DI container; where would the EF get a non-static DI container reference from? – Steve Wilkes Jan 31 '12 at 13:49
  • 1
    I vehemently disagree with the premise that service locator itself is an anti-pattern. The way you have used service locator here is not optimal IMO. – Chris Marisic Jan 31 '12 at 13:55
  • @Chris Marisic - "The way you have used service locator here is not optimal IMO" - how d'you mean? – Steve Wilkes Jan 31 '12 at 14:10
  • @SteveWilkes the reason I say your usage of the pattern is not optimal is for the very reasons you opened this question. You inserted an insidious dependency into the User class that is not discoverable and is very unrelated to the intent of the class. You aren't using service location for the need of using service location, you've used this pattern to throw a rope down the hole you've designed so you can climb out. – Chris Marisic Jan 31 '12 at 15:32
  • 1
    Interestingly put :) I don't think we're talking about the exact same thing when we say 'the ServiceLocator pattern'; as I mean it (the way it is described [here](http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx)), it *always* inserts an insidious dependency into classes that is not discoverable. – Steve Wilkes Jan 31 '12 at 15:36
  • @SteveWilkes "it always inserts an insidious dependency" is not a true statement. A great example of where service location matches, is a pipe line processor. You're given an input of type X, then you use service location to get all of the typeX processors and execute them against the current input. At this point you're not using service location to wire in code in a fashion that is exactly the same as using static helper classes but instead are truly locating services that can act as configured at run time. – Chris Marisic Jan 31 '12 at 16:31
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7209/discussion-between-steve-wilkes-and-chris-marisic) – Steve Wilkes Jan 31 '12 at 18:38

2 Answers2

5

Here's how I would define the User class:

public class User
{
    public bool HasCompletedSecurity { get; set; }

    // other members...
}

Seriously, this is a better solution because it decouples the value along the temporal dimension. Consider this: if a user completed all security questions in 2010 and you later on change the business rule, are you then going to invalidate the existing user?

In most cases it would probably be more reasonable to record and persist that sometime in the past, the user completed the security procedure that was in effect at that time. In that way, you don't bother existing users.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • 1
    Seems reasonable, but I don't see it as unreasonable that the rules defining security could change and I could want a user to answer an extra security question / create a more secure password / etc... with that precise example to one side, how about the larger question of accessing non-static services from entities? Is the answer to architect entities in such a way that they never need to? – Steve Wilkes Jan 31 '12 at 14:03
  • 1
    Yes, I find it much more reasonable to design entities so that they represent persisted/historical state. See also this answer: http://stackoverflow.com/questions/4835046/why-not-use-an-ioc-container-to-resolve-dependencies-for-entities-business-objec/4836790#4836790 – Mark Seemann Jan 31 '12 at 15:22
1

You can still using the concept of Inversion of Control without using any sort IoC container or requiring its use in the constructor of your entity. I would approach this using a quasi-strategy pattern and have something like:

public interface ISecurityPolicy
{
    public int MinimumSecurityQuestionResponses { get; }
}

public class User
{
    public void HasCompletedSecurity (ISecurityPolicy security_policy)
    {
         return this.SecurityQuestionResponses.Count()
                     >= security_policy.MinimumSecurityQuestionResponses;
    }
}

This puts the onus of providing the particular security policy that the user must satisfy on the caller, not the User class itself.

From that point on, you can provide that extra parameter however you want to, maybe be wrapping this in a IUserSecurityService that will have the ISecurityPolicy injected into the service, etc.

This is still Inversion of Control, but it's at the method level, since this one particular method is really the only one that cares about the security policy/configuration.

Pete
  • 11,313
  • 4
  • 43
  • 54
  • Interesting... I agree that the number of required security question responses does belong in a `SecurityPolicy` of some sort, but seeing it passed to a `User` to have the user determine if it satisfies the policy kinda pushes me towards @Chris Marisic's answer - that the property is simply in the wrong place. I'll keep this mind for more general examples, though :) – Steve Wilkes Jan 31 '12 at 15:02
  • Yes, that's very true. Encapulating it the way @Chris Marisic shows probably works best for this particular scenario. For the general case where a "dependency" is needed for one particular method of a entity, passing in the dependency as a parameter to the method can greatly simplify things. – Pete Jan 31 '12 at 15:20