Tech Is Hard

Credibility = Talent x Years of experience + Proven hardcore accomplishment

What Am I Modeling?


One reason I like working on legacy systems is that the current intent can be pretty much gleaned from the code and its behavior.  You have to assume it’s working for the most part and when you run into things that look in error, you determine whether there’s a non-obvious reason for it being that way, or it gets confirmed as a problem.  I’m going to use an example business model, but keep in mind that eventually we move all the generic functionality away from the business domain.  I think the example classes might be interesting to look at also.

The classes I was pretty clear on were regions, distribution centers and users.  While there were separate data access modules and service layer modules, cohesion in the latter, a layer that should have been using powerful classes to do all the repetitive logic, was non-existent.  There was absolutely no meaningful state in these classes, they were just a loose collection of related functions.  Each function repeated many of the same data access.  With more than one data method to do the same thing, I had to go check the arguments each time and make sure I was using the best available method.  Terribly granular code, which made people take shortcuts and make assumptions where it was convenient.  Watching the data access log, it was also clear we queried for the same data items many times during a single page load.  I’ve always believed that if you make the common things very easy to do, then I can focus on making my application code really clear and robust.

The 3 entities I listed are in a container relationship: Users are in a single DistCenter and a DistCenter is in a Region.  Starting with a User, instead of explicitly fetching a row in every method that needs to reference the user’s distribution center, I asked something like: “why can’t I instantiate a User with the id parameter and reference $myUser->DistCenter ?”

Let’s start with User, then.

class User {
   public $id;    // user's id and key everywhere
   public $DistCenter;    // reference to $this User's Center
   function __construct($id) {
      $this->id = $id;
   }
   function __get($p) {
   }
   function __set($p, $v) {
   }
}

But when I write

$User = new User();
$Center = $User->DistCenter;

__get doesn’t execute. I want my properties defined explicitly in the classes, but how can I make __get think they’re undefined? After trying null and other tricks, I found that I could unset() them during construction and get my desired result.

class User {
...
   function __construct($id) {
      $this->id = $id;
      Foobar::init($this);
   }
}

class __pm {
   /**
    * Unsets the indicated properties in client class
    *
    * @param  object  $O
    */
   static function init($O) {
      $classType = get_class($O);
      $oReflectClass = new ReflectionClass($classType);

      // For each public property
      foreach ($oReflectClass->getProperties(ReflectionProperty::IS_PUBLIC) as $oReflectProperty) {
         $pName = $oReflectProperty->getName();
         unset($O->{$pName});
      }
   }
}

__pm is the new class to automate all the intelligent property handling. We will have to modify User’s inherent definition a little as we go along to let __pm work, and those changes will become the pattern for any class.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: