Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Trying to be a better programmer

I have an application that keeps track of Roles and Permissions, I had classes for Role and Permission which were just value objects.

class Role
{
  int RoleID
  string RoleName
}

class Permission
{
  int PermissionID
  string PermissionName
}

If I wanted to get the permissions for a Role I would do

List<Permission> permissions = PermissionDAL.GetPermissions(RoleID)

But for convenience (it's a Desktop application) I had to move the permission collection to the Role class so I could just do

permissions = roleInstance.GetPermissions();

and the Role class becomes

class Role
{
  List<Permission> permissions = null;
  int RoleID
  string RoleName

  public List<Permission> Permissions
  {
     get
     {
        if(permissions == null)
           permissions = PermissionDAL.GetPermissions(this.RoleID);

        return permissions;
     }
  }
}

Question 1: the challenge - here is the scenario

Role r = getARole();
   //for user to see
display(r.Permissions); 

   //user adding permission to role
RoleDAL.AddPermission(RoleID, PermissionID);

   //display new permissions
display(r.Permissions); 
   //But no, data is not refreshed because of the null check. 
   //Do I need to call a new instance of this Role?

Question 2 : I think this violate Inversion of Control?

Question 3 : How would you do an IoC for List<Role>, setting the permissions for each Role in the collection, if one were to use IoC.

Thanks

share|improve this question
2  
to call a new instance of this Role would be my personal preference. I'd also drop that null-check and instead, would use something like promise aka future for a lazy init of permissions –  gnat Jul 16 '12 at 6:12
add comment

1 Answer

up vote 2 down vote accepted
  1. Yes, this behavior is common in lazy-loaded data objects based on rapidly-changing data stores. You force a change here, but similar concurrency issues can happen in a multi-user system even when you're looking at data in a read-only fashion.

    The easiest solution to your specific issue is to add the permission to the Permissions list manually in addition to writing it to the database. However, that doesn't solve concurrency; another user could add a permission after you get a list of them and you'll never know. There are many other solutions that will solve this snag; most of them require a simple SQL statement to stand in for the larger SQL statement. For instance, you could ask for a count of the number of records, and if that doesn't match the length of your list then repopulate it. You could also keep track of the "last modified date" of each element in the list, and if the most recent modified date of the records you would pull is newer than the newest last modified date of the data you have, refresh the data. Or, you can simply track how long ago you last refreshed, and if that's beyond a certain threshold you set the data is "stale" and should be refreshed. These will necessarily require a round trip to the database, but they're scalar queries so they economize on network bandwidth (and shouldn't perform terribly against a well-structured DBMS).

  2. No, this does not break Inversion of Control, because this logic should go into the Role.Permissions accessor and thus you can continue to use one resolved instance as necessary. Even if you couldn't, there are ways to inject a factory method that can be used to produce as many "factory-scoped" (one per request) Role objects as you might need.

  3. This depends on the IoC framework you're using (or if you aren't using one), and how you want that framework to produce Roles. If you have a factory method registered that takes a RoleID and produces a Role object, you can make that call as many times as you want. The Role object, by its nature, will then require something it can call to get the list of Permissions. Injecting the DAO is one option (and not a bad one as long as consuming code doesn't have to know about the DAO), but I would prefer a delegate Func<int, IEnumerable<Permission>> (and another Func<IEnumerable<Permission>, bool> that you'll use to determine if it's necessary to refresh data) that you can inject into Role and that Role can use without having to know where it came from; then if you had to, you could pretty much tear your data access layer out and start completely from scratch, without any other object knowing the difference.

share|improve this answer
    
well explained and enlightened –  tunmise fasipe Jul 16 '12 at 21:09
    
#2: if you with "this logic" is referring to IOC-resolution, then having that kind of code in property accessors is considered an anit-pattern by many: stackoverflow.com/a/2179260/507339 . But you're right in it doesn't break IOC. –  Nilzor Mar 5 at 10:10
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.