Welcome to MSDN Blogs Sign in | Join | Help

Fluent Interface for System.Identity – Party Implementation (Part 1)

This latest post on developing a fluent interface for the Oslo System.Identity schema will start an implementation of the Party class. Per the architectural specifications for the fluent interface, the Party class will adhere to the Law of Demeter and “Tell, Don’t Ask. As the Party class is large, and important to the System.Identity model, I’ll tackle Party in a couple of different posts.

 

Party is Central to System.Identity

The System.Identity schema is built around a particular design pattern commonly referred to as the “Party Model”. The Party Model is a powerful solution to a common problem found in software – how do you handle the complex relationships that exist between the actors in a system – especially where actors can be both physical and logical participants. This concept is illustrated in the MSDN documentation on System.Identity’s Party entity:

  • “The directory stores information about digital subjects and resources that have relationships. Different kinds of digital subjects typically share many of the same characteristics – while being different. The System.Identity schema provides a single mechanism for defining all the different kinds of things present in the directory –represented through entities called Kinds. The System.Identity schema represents the common aspect of all digital subjects through an entity called a Party.”

The importance of Party to System.Identity is further illustrated in the following UML representation of part of the System.Identity schema. The UML clearly illustrates the centricity of Party to the System.Identity design:

Parties

 

As the diagram above illustrates, Party is associated with almost every other entity in the System.Identity schema. This makes designing a fluent interface for Party an interesting design exercise.

 

NOTE – For those devotess of Domain-Driven Design (DDD) I will be purposefully ignoring the ORM implications of Party (specifically Aggregates) in terms of Party methods, although use of the Law of Demeter and “Tell, Don’t Ask” produces code that is very conducive to “modern” domain model persistence designs. I’ve been toying with the idea of writing a series to reactoring the fluent interface to adhere to DDD and leverage NHibernate, but that might be a while down the road.

 

The Party Basics

As with the fluent interface implementation of the Kind class, Party’s code will exhibit a certain shape given adherence to “Tell, Don’t Ask”. The following snippet shows the first pass on Party’s code:

   1: public class Party : SystemIdentityBase
   2: {
   3:     public string Name { get; private set; }
   4:     public string DisplayName { get; private set; }
   5:     public string YomiDisplayName { get; private set; }
   6:     public string DescriptiveInformation { get; private set; }
   7:     private Kind Kind { get; set; }
   8:     private Kind PrimaryKind { get; set; }
   9:     private List<Role> Roles { get; set; }
  10:  
  11:     public Party ( string name, string displayName, string yomiDisplayName, string descriptiveInformation, Kind kind, Kind primaryKind )
  12:     {
  13:         ChangeName ( name );
  14:         ChangeDisplayName ( name );
  15:         ChangeYomiDisplayName ( yomiDisplayName );
  16:         ChangeDescription ( descriptiveInformation );
  17:         ChangeKind ( kind );
  18:         ChangePrimaryKind ( primaryKind );
  19:  
  20:         Roles = new List<Role> ();
  21:     }
  22:  
  23:     public void ChangeName ( string name )
  24:     {
  25:         Name = name;
  26:     }
  27:  
  28:     public void ChangeDisplayName ( string displayName )
  29:     {
  30:         DisplayName = displayName;
  31:     }
  32:  
  33:     public void ChangeYomiDisplayName ( string yomiDisplayName )
  34:     {
  35:         YomiDisplayName = yomiDisplayName;
  36:     }
  37:  
  38:     public void ChangeDescription ( string descriptiveInformation )
  39:     {
  40:         DescriptiveInformation = descriptiveInformation;
  41:     }
  42:  
  43:     public bool IsOfKind ( Kind kind )
  44:     {
  45:         return Kind.Equals ( kind );
  46:     }
  47:  
  48:     public void ChangeKind ( Kind kind )
  49:     {
  50:         Kind = kind;
  51:     }
  52:  
  53:     public bool IsOfPrimaryKind ( Kind primaryKind )
  54:     {
  55:         return PrimaryKind.Equals ( primaryKind );
  56:     }
  57:  
  58:     public void ChangePrimaryKind ( Kind primaryKind )
  59:     {
  60:         PrimaryKind = primaryKind;
  61:     }
  62: }

 

In addition to the basic aspects of Party (i.e., attributes of Party), the code snippet above contains a private automatic property for the collection of Roles a Party may play. The design of Party’s interface with respect to the Roles collection will be the subject of the rest of this post.

 

NOTE – The remainder of this series will use simple generic Lists to represent the various collections in the System.Identity schema. The use of Lists is not necessarily optimal, so the fluent interface offers GetHashCode() implementations for those applications that require better than O(n) performance.

 

Telling a Party About its Roles

In the context of “Tell, Don’t Ask” we can think about the Party methods in terms of the specific domain that System.Identity addresses. For example, we could think of the Party interface as a means of facilitating the following scenarios:

  • Dave Langer accepts employment with Microsoft Corporation
  • Determining if Dave Langer is employed
  • Determining if Dave Langer was employed by Microsoft Corporation from MM/DD/YYYY to MM/DD/YYYY
  • Dave Langer terminates his employment with Microsoft Corporation
  • Dave Langer is no longer an Architect on any projects at Microsoft Corporation

First in the above list is providing a method for a Party to assume a new Role. The method implementation is straightforward as illustrated by the following code snippet:

   1: public void AssumeRole ( Role role )
   2: {
   3:     if ( !Roles.Contains ( role ) )
   4:     {
   5:         Roles.Add ( role );
   6:     }
   7: }

 

The next scenario is where “Tell, Don’t Ask” really shines in producing code that just has an OO “feel” to it. The Party class’ public interface will provide two methods for determining what Roles a Party might play:

   1: public bool PlaysRole ( Role role )
   2: {
   3:     return Roles.Contains ( role );
   4: }
   5:  
   6: public bool PlaysRole ( Predicate<Role> matchingSpecification )
   7: {
   8:     Role role = Roles.Find ( matchingSpecification );
   9:  
  10:     if ( role == null )
  11:     {
  12:         return false;
  13:     }
  14:  
  15:     return true; 
  16: }

 

The first method in the code snippet above addresses the scenario of “tell me if Dave Langer is employed”, while the second method supports the scenario of “tell me if Dave Langer was employed by Microsoft Corporation from MM/DD/YYYY to MM/DD/YYYY”.

 

Lastly, Party’s interface will provide some OO goodness for telling a Party to stop playing a Role:

   1: public void StopPlayingRole ( Role role )
   2: {
   3:     Role roleToStopPlaying = Roles [ Roles.IndexOf ( role ) ];
   4:  
   5:     roleToStopPlaying.ChangeEndDate ( DateTime.Now );
   6: }
   7:  
   8: public void StopPlayingRoles ( Predicate<Role> matchingSpecficiation )
   9: {
  10:     List<Role> rolesToStopPlaying = Roles.FindAll ( matchingSpecficiation );
  11:     DateTime timeStamp = DateTime.Now;
  12:  
  13:     foreach ( Role role in rolesToStopPlaying )
  14:     {
  15:         role.ChangeEndDate ( timeStamp );
  16:     }
  17: }

 

As System.Identity supports the concept of “logical deletes” for Roles via start and end dates, the methods above don’t actually remove Role objects from the collection. The first method in the code snippet above implements the scenario of “Dave Langer quit work at Microsoft” and the second method implements the scenario of “Dave Langer is no longer an Architect on any project at Microsoft”.

 

Law of Demeter & Collections

The above snippets illustrate the OO goodness that results from applying “Tell, Don’t Ask” to minimize coupling. However, the practical reality is that sometimes it is really darn handy to get a collection directly from an object in the domain. The reasons for this are many, but the single most common reason is to grab the collection so that it can be iterated over and displayed in a UI. Now, if you’re addicted to design patterns like I am then you’ll immediately jump to patterns like Visitor or Model-View-Presenter (MVP) as potential solutions to this problem that don’t violate the Law of Demeter.

The problem with using Visitor or MVP is that the more they are used to maximize cohesion and reduce coupling, the more complicated the class model becomes. Luckily, the Demeter folks consider containers (which they call “Repetition” classes) as exempt from the Law of Demeter. For those that are interested check out this wiki.

In terms of the Party class this means that we can expose the Party class’ collection of Role object:

   1: public IList<Role> PartyRoles ()
   2: {
   3:     return Roles.AsReadOnly ();
   4: }

 

As the above snippet illustrates, direct exposure of the List would be inappropriate due to the fact that clients could directly add and remove Role objects directly, thereby bypassing the AssumeRole(), StopPlayingRole(), and StopPlayingRoles() methods. Additionally, the code above follows the spirit of the Law of Demeter by using the IList interface to further insulate clients from changes in the Party class implementation.

 

Next Time

More Party implementation goodness.

Stay tuned!

 

A Real World Use For Oslo

I’m going to take a small detour from my series on a fluent interface for Oslo’s System.Identity schema to propose a real world scenario where Oslo could be leveraged. This post has its genesis in Kraig Brockschmidt's recent post “What Exactly Does One Do With ‘Oslo’”. While I think Kraig’s post covers a number of important ideas regarding the potential applications of Oslo, the responses to the post nevertheless contain a strong undercurrent of “Great, I still don’t how I would use Oslo in the real world”.

 

I figured, at the risk of arrogance and ridicule, that I would offer such a scenario.

 

Oslo – It’s About Architecture

As I’ve written about previously, I find Oslo an immensely interesting technology (although at first, like many, I didn’t think much of Oslo). One of the significant triggers for my “flipping the bit” on Oslo was reading Chris Sells’ excellent MSDN article on Oslo. Like anybody who has been following Oslo, I’ve seen all the video and web content illustrating Oslo’s DSL capabilities – and like anybody familiar with ANTLR I was intrigued, but not blown away. However, what Chris’ article showed me was that despite all the focus on what was formally called MGrammar, Oslo is actually most interesting as an accelerator for building metadata-driven applications (OK, metadata-driven applications that leverage DSLs ;-).

 

This is significant because Oslo does not provide a targeted implementation solution like ASP.NET or SQL Server do, Oslo provides a solution to address architectural concerns.

 

Kraig validates this view of Oslo when he writes:

  • “What's more valuable is to create a runtime that effectively implements a class of applications, where each specific application is wholly defined by metadata alone. That is, the runtime is a kind of generic application engine for that class. One essentially configures that generic engine with specific metadata to thereby produce any number of particular, custom "applications" (you know, the thingies that are visible on the screen that users poke at all day). From this one realizes a significant productivity gain in comparison to writing each such application from scratch.”

Those readers familiar with Microsoft will undoubtedly recognize in the passage above some ideas that are akin to the Software Factories approach to improving software development. Like Software Factories, Oslo is an attempt to improve the efficiency and quality of application development via an architecture-centric approach.

 

Real World Oslo – It’s About Reusable Architecture

For the sake of argument, if we accept that Oslo is tool to address architectural, rather than implementation, concerns (check out this post for definitions) then it stands to reason that real world applications of Oslo would involve using the technology to address opportunities that are inherently architectural in nature. 

 

For example, the Software Engineering Institute (SEI) provides just such an opportunity in the concept the SEI calls “software product lines”:

  • “A software product line (SPL) is a set of software-intensive systems that share a common, managed set of features satisfying the specific needs of a particular market segment or mission and that are developed from a common set of core assets in a prescribed way.”

While the software product line concept is similar to Software Factories, SPLs have a much lower barrier to entry and have had documented success in the real world. The following SPL case studies are taken from the book “Software Architecture in Practice”:

  • “Cummins, Inc., was able to reduce the time to it takes to produce the software for a diesel engine from about a year to about a week.“
  • “With a family of satellite ground control systems it commissioned, the U.S. National Reconnaissance Office reports the first product requiring 10% of the expected number of developers and having 90% fewer defects."

As a career Fortune 500 IT weenie, I can attest that there exists a class of applications that fit both the architectural characteristics that Kraig and the SEI describe above – enterprise business applications.

 

Real World Oslo – Building a SPL for Enterprise Business Applications

It is possible (I’m asking for some trust on this ;-) to illustrate through architectural analysis that a software product line for enterprise business applications would focus on building reusable software assets/platforms that are:

  • Multitenant
  • Metadata-driven
  • Capable of automating workflow

The above is obviously a non-exhaustive list of the potential characteristics for an enterprise business application software product line, but it clearly illustrates that Oslo is a potential accelerator for any organization (e.g., a large IT shop or ERP software vendor) that builds enterprise business applications.

As Kraig correctly points out in his blog post, use of Oslo is only realistic in situations where economies of scale are to be gained. The ROI of creating a metamodel, DSL, and runtime using Oslo for a single application will typically not compute. This is where the SPL concept starts to make sense. If an organization will be building multiple enterprise business applications, then the creation of core Oslo architectural assets (i.e., metamodels, DSLs, and runtimes) to be reused across development efforts could drive a favorable ROI – both in terms of overall time to market and quality.

Now I realize that what I’m talking about here won’t apply to a wide swath of Microsoft’s customers. I won’t lie to you. If you’re working in a small IT shop then the current state of the Oslo technology is not likely to be interesting to you. If you’re working for a Gold-certified Partner then the current state of Oslo is also not likely to be interesting to you (although you may want to look at MS CRM as an app plat for your clients ;-).

However, I don’t see this being a problem at all. As I stated above, tools like ASP.NET and SQL Server are implementation solutions and are applicable to a wide swath of Microsoft customer problems while Oslo is only applicable to those customer’s facing the architectural problems that Oslo addresses. Logically, Microsoft developing and selling Oslo (assuming we end up selling it ;-) is no different than Microsoft developing and selling AX.

 

Oh, Wait. I’m Also a Real World Example

Not to be ham-handed, but it seems appropriate to mention that I’m also a real world example for Oslo (although a biased example ;-). One of the things I spend a lot of time thinking about is how to accelerate the efficiency and quality of delivering business systems to Microsoft. As you might imagine, as the world’s largest software company Microsoft has a number of rather unique requirements in terms of its enterprise business applications – but they all share architectural characteristics. As such, I’ve been exploring and watching Oslo with great interest – maybe your organization should as well. 

As always, feedback is greatly appreciated.

Posted by dalanger | 3 Comments

Fluent Interface for System.Identity – Kind’s Expression Builder

<Author’s Note>

It’s been quite a while since my last blog post. The reason for the gap was due to my non-work time being consumed with swimming (some might say wallowing ;-) in the architectural soup writing a ThinkWeek paper related to Microsoft IT (MSIT) software architecture. Writing the paper took quite a bit more effort than I expected, but I found it a highly enjoyable exercise (yes, I know, I have no life). Now that the paper is done, I’m back to finishing up this series on System.Identity.

</Author’s Note>

The last post in this series finished up some of the plumbing aspects of the System.Identity fluent interface, focusing on the impacts of persisting the fluent interface to the Oslo Repository on the implementation of the Equals() and GetHashCode() methods inherited from System.Object. With the details of the ORM persistence for the fluent interface and the definition of the Kind class’ Command-Query API taken care of, it’s time to take a look at the Kind Expression Builder.

 

A Method Chaining Builder for Kinds

The Expression Builder that will be explored in this post is a class that provides a fluent interface for the construction of Kind objects through the use of Method Chaining. Specifically, the desirable end state is for the code that creates Kind objects to look like the following:

   1: Kind kind = new KindBuilder ()
   2:     .IsNamed ( "TestKind" )
   3:     .CanBeDescribedAs ( "SomeDescription" )
   4:     .CanBeIdentifiedByTheKeywords ( "Keyword" )
   5:     .IsStoredInFolder ( 250 )
   6:     .IsOwnedBy ( owningParty );

 

The desired end state code above illustrates the public interface of the KindBuilder class, using this information the following code snippet shows the Method Chaining public interface of KindBuilder:

   1: public class KindBuilder
   2: {
   3:     public KindBuilder IsNamed ( string name )
   4:     { }
   5:  
   6:     public KindBuilder CanBeDescribedAs ( string descriptiveInformation )
   7:     { }
   8:  
   9:     public KindBuilder CanBeIdentifiedByTheKeywords ( string keywords )
  10:     { }
  11:  
  12:     public KindBuilder IsStoredInFolder ( int folder )
  13:     { }
  14:  
  15:     public KindBuilder IsOwnedBy ( Party owner )
  16:     { }
  17: }

 

The code above is rather straightforward, with the only thing worthy of note is that each of KindBuilder’s public methods return back an instance of KindBuilder. As one might imagine, this is the “secret sauce” that allows Method Chaining to work.

However, the public interface of KindBuilder isn’t yet complete. While the code snippet immediately above addresses the Method Chaining aspect of KindBuilder’s public interface, line #1 of the desirable end state code snippet clearly illustrates that a KindBuilder instance gets converted to a Kind instance at the completion of the method chain. C#’s implicit operator makes this kind of goodness a snap to implement:

   1: public static implicit operator Kind ( KindBuilder builder )
   2: { }

 

The Complete KindBuilder

With the public interface of KindBuilder defined, all that is left is to add some simple state to the class and then implement the implicit operator. The following illustrates the complete KindBuilder class:

   1: public class KindBuilder
   2: {
   3:     private string Name { get; set; }
   4:     private string DescriptiveInformation { get; set; }
   5:     private string Keywords { get; set; }
   6:     private int Folder { get; set; }
   7:     private Party Owner { get; set; }
   8:  
   9:     public KindBuilder IsNamed ( string name )
  10:     {
  11:         Name = name;
  12:         
  13:         return this;
  14:     }
  15:  
  16:     public KindBuilder CanBeDescribedAs ( string descriptiveInformation )
  17:     {
  18:         DescriptiveInformation = descriptiveInformation;
  19:  
  20:         return this;
  21:     }
  22:  
  23:     public KindBuilder CanBeIdentifiedByTheKeywords ( string keywords )
  24:     {
  25:         Keywords = keywords;
  26:  
  27:         return this;
  28:     }
  29:  
  30:     public KindBuilder IsStoredInFolder ( int folder )
  31:     {
  32:         Folder = folder;
  33:  
  34:         return this;
  35:     }
  36:  
  37:     public KindBuilder IsOwnedBy ( Party owner )
  38:     {
  39:         Owner = owner;
  40:  
  41:         return this;
  42:     }
  43:  
  44:     public static implicit operator Kind ( KindBuilder builder )
  45:     {
  46:         return new Kind ( builder.Folder, builder.Name, builder.DescriptiveInformation, builder.Keywords, builder.Owner );
  47:     }
  48: }

 

For those that are interested, code for the SystemIdentityBase, Kind, and KindBuilder classes (with unit tests) is available for download from my SkyDrive. The link to the .ZIP is located a the bottom of this post.

 

Next Time

The subject of the next post will be coverage of the System.Identity Party class. As the models for System.Identity illustrate, Party is a central concept in System.Identity. Working the Party class using the architectural specifications for the fluent interface should be an interesting design exercise.

 

SkyDrive Files

Fluent Interface for System.Identity – M, Persistence, & GetHashCode()

As I wrote about last time, leveraging the System.Identity schema with the Oslo Repository introduces some ORM database persistence considerations into the design of the fluent interface. In the last article I introduced how to override the Equals() method inherited from System.Object. In accordance with MSDN guidance, I’ll be writing an overload of the GetHashCode() method inherited from System.Object that, like the Equals() override, addresses the ORM considerations of the fluent interface.

As with the last post, I’ll be leveraging the excellent coverage of the GetHashCode() method in the book “Effective C#”.

In looking at the considerations for an overload of GetHashCode(), the fluent interface code must adhere to the following rules:

  1. If two objects are equal they must generate the same hash code
  2. The hash code is an invariant for an object – meaning that if even if fields on the object are changed, the hash code always remains the same
  3. The hash function should generate a random distribution of integer values – this ensures efficiency (aka read less collisions in a hash table) so it is more desirable than a hard and fast rule

Given that our fluent interface is essentially a runtime representation of the System.Identity schema in the Oslo Repository, the Id field (which is populated by SQL Server when objects are persisted the first time) qualifies as the hash code source for fluent interface objects that are rehydrated from the Oslo Repository. However, the Id field won’t work for objects that haven’t yet been persisted to the Repository.

Ergo, our GetHashCode() implementation will need to handle two primary objects states – persisted and non-persisted.

 

The State of the Hash

Addressing this split state requirement necessitates the use of a member variable, so for the time being I’ll locate this new field in the SystemIdentityBase class so that all the fluent interface classes can inherit it:

   1: public abstract class SystemIdentityBase
   2: {
   3:     protected Int64? Id { get; private set; }
   4:     protected int Folder { get; private set; }
   5:     private int? BaseHashCode { get; set; }
   6:  
   7:     // Rest of code removed for brevity
   8: }

 

As the above code snippet illustrates, I’ll use a nullable integer field to store the hash code for fluent interface objects that haven’t yet been assigned an Id value by the Oslo Repository (SQL Server).

I’ll continue to leverage the SystemIdentityBase class for the GetHashCode() implementation:

   1: public override int GetHashCode ()
   2: {
   3:     if ( BaseHashCode.HasValue )
   4:     {
   5:         return BaseHashCode.Value;
   6:     }
   7: }

 

Simple enough – if it isn’t null, use the BaseHashCode for the return value of the GetHashCode() method. Putting this first in the method implementation ensures compliance with rule #2 above.

The next step is to address the situation where a fluent interface object has been loaded from the Oslo Repository. In this case I’ll use the hash code of the Id field as the hash code for the object:

   1: if (Id.HasValue)
   2: {
   3:     return Id.GetHashCode();
   4: }

 

As I know that the Oslo Repository masters the Id field (not to mention that fact that it’s marked private and can’t be altered), the usage of the Id field’s hash code addresses rules #1 and #2 above.

Lastly, I need to handle the situation where a fluent interface object is being stuck in a hash table, but hasn’t been persisted yet. To keep things simple (and correct), I’ll punt in this case to the System.Object implementation of GetHashCode(). The following snippet shows the complete method implementation:

   1: public override int GetHashCode ()
   2: {
   3:     if ( BaseHashCode.HasValue )
   4:     {
   5:         return BaseHashCode.Value;
   6:     }
   7:  
   8:     if (Id.HasValue)
   9:     {
  10:         return Id.GetHashCode();
  11:     }
  12:     else
  13:     {
  14:         BaseHashCode = base.GetHashCode();
  15:  
  16:         return BaseHashCode.Value;
  17:     }
  18: }

 

Now I’ve got a reusable implementation of GetHashCode() that all the fluent interface classes will get for “free”.

 

Houston, We Have a Problem

With this implementation of GetHashCode() sitting in the SystemIdentityBase class I’ve got a bit of a problem. In the last post I placed the Equals() override in the Kind class. Looks like some quick refactoring is in order.

In looking at the Equals() code, most of it is easily transferrable to the SystemIdentityBase class. After some quick VS magic I have the following method added to SystemIdentityBase:

   1: public override bool Equals ( object obj )
   2: {
   3:     if ( obj == null )
   4:     {
   5:         return false;
   6:     }
   7:  
   8:     if ( ReferenceEquals ( this, obj ) )
   9:     {
  10:         return true;
  11:     }
  12:  
  13:     if ( this.GetType () != obj.GetType () )
  14:     {
  15:         return false;
  16:     }
  17:  
  18:     Kind otherKind = obj as Kind;
  19:  
  20:     if ( Id.HasValue && otherKind.Id.HasValue && ( Id.Value == otherKind.Id.Value ) )
  21:     {
  22:         return true;
  23:     }
  24:  
  25:     return Name == otherKind.Name &&
  26:            Keywords == otherKind.Keywords &&
  27:            Owner.Equals ( otherKind.Owner );
  28: }

 

The problem arises on lines 18-27 in the snippet above – this is code specific to the Kind class. What I need is for SystemIdentityBase to provide an Equals() implementation that could be overridden on a class-by-class basis. Some minor tweaks and a quick virtual method should do the trick:

   1: public override bool Equals ( object obj )
   2: {
   3:     if ( obj == null )
   4:     {
   5:         return false;
   6:     }
   7:  
   8:     if ( ReferenceEquals ( this, obj ) )
   9:     {
  10:         return true;
  11:     }
  12:  
  13:     if ( this.GetType () != obj.GetType () )
  14:     {
  15:         return false;
  16:     }
  17:  
  18:     SystemIdentityBase otherObject = obj as SystemIdentityBase;
  19:  
  20:     if ( Id.HasValue && otherObject.Id.HasValue && ( Id.Value == otherObject.Id.Value ) )
  21:     {
  22:         return true;
  23:     }
  24:  
  25:     return CompareObjectMembers ( otherSystemIdentityBase );
  26: }
  27:  
  28: protected virtual bool CompareObjectMembers ( SystemIdentityBase otherObject )
  29: {
  30:     return false;
  31: }

 

I like it. The fluent interface is taking on a “frameworky” vibe that just gives an OO bigot like me a deep sense of goodness (it’s sad, I know). All fluent interface classes will now inherit ORM-aware implementations of Equals() and GetHashCode() and have the option of overriding the Equals() functionality if needed.

As a last step I’ll remove the Equals() implementation out of the Kind class and add the following override to the Kind class:

   1: protected override bool CompareObjectMembers ( SystemIdentityBase otherObject )
   2: {
   3:     Kind otherKind = otherObject as Kind;
   4:  
   5:     return Name == otherKind.Name &&
   6:            Keywords == otherKind.Keywords &&
   7:            Owner.Equals ( otherKind.Owner );
   8: }

 

Houston, We’re Not Quite Done

Some readers will unlikely notice that this last code snippet breaks rule #1 listed above. Not a problem, I’ll refactor a little OO goodness into the GetHashCode() method to address the problem:

   1: public override int GetHashCode ()
   2: {
   3:     if ( BaseHashCode.HasValue )
   4:     {
   5:         return BaseHashCode.Value;
   6:     }
   7:  
   8:     if ( Id.HasValue )
   9:     {
  10:         return Id.GetHashCode ();
  11:     }
  12:     else
  13:     {
  14:         BaseHashCode = GetBaseHashCode ();
  15:  
  16:         return BaseHashCode.Value;
  17:     }
  18: }
  19:  
  20: protected virtual int GetBaseHashCode ()
  21: {
  22:     return base.GetHashCode ();
  23: }

 

Excellent. As with the Equals() method there’s a default implementation that will work with a large number of the fluent interface classes, but I’ve provided a nice extensibility point for classes that need different behavior.

To wrap up this post I’ll add a override to the Kind class for the GetHashCode() functionality that it needs:

   1: protected override int GetBaseHashCode ()
   2: {
   3:     int hash = 23;
   4:  
   5:     hash = ( ( hash << 5 ) * 37 ) + ( Name == null ? 0 : Name.GetHashCode () );
   6:     hash = ( ( hash << 5 ) * 37 ) + ( Keywords == null ? 0 : Keywords.GetHashCode () );
   7:     hash = ( ( hash << 5 ) * 37 ) + ( Owner == null ? 0 : Owner.GetHashCode () );
   8:  
   9:     return hash;
  10: }

 

The algorithm above I gleaned from an excellent post that interested folks can read here. Please note that I do not profess to be a hash code algorithms expert, however the code snippet above doesn’t seem to far out of whack from a number of articles/posts I’ve read on the subject.

 

Next Time

For my next post in the series I’ll take a look at an Expression Builder for the Kind class.

Until next time, thanx for reading!

Fluent Interface for System.Identity – M, Persistence, & Equals()

As I wrote in Part 2 of the series, System.Identity ships in the latest Oslo CTP as part of the Oslo Repository. This has the direct effect of introducing ORM database persistence considerations into the design of the System.Identity fluent interface I’ve been crafting.

One of these considerations has already manifested in the following snippet of seemingly straightforward code:

   1: public bool IsOwnedBy ( Party owner )
   2: {
   3:     if ( Owner == null || owner == null )
   4:     {
   5:         return false;
   6:     }
   7:     else
   8:     {
   9:         return Owner.Equals ( owner );
  10:     }
  11: }

 

In the snippet above, line #9 evaluates the equality of the object’s Owner property (as an instance of the Party class) vis-à-vis the passed-in owner parameter.

As it turns out, the Equals() and GetHashCode() methods become quite interesting when dealing with objects that are dehydrated to, and rehydrated from, a database. The subject of this post will be outlining an implementation of Equals() that will work correctly with the fluent interface and a persistence mechanism (e.g., NHibernate) that might be used to store and retrieve objects from the Oslo Repository. My next post will tackle an similar implementation of GetHashCode().

 

It’s All About the Id

While Oslo’s M language can be used as a straight-up textual modeling language, M has been deliberately designed to make using a SQL Sever database as a model repository incredibly easy. In line with this design goal, M supports a number of language features that directly enable model persistence in SQL Server.

From the M for the Oslo Repository in the May CTP, I offer the HasFolderAndAutoId.m file:

   1: //-----------------------------------------------------------------------------
   2: // Copyright (c) Microsoft Corporation.  All rights reserved.
   3: //-----------------------------------------------------------------------------
   4:  
   5: module System 
   6: {
   7:     export HasFolderAndAutoId;
   8:  
   9:     // Mixin used to include a SQLServer-managed numeric identifier and a folder reference.
  10:     // Use this mixin when defining normal content types or extents. 
  11:     type HasFolderAndAutoId : HasFolder
  12:     { 
  13:         Id : Integer64 => AutoNumber();
  14:         
  15:     } where identity Id; 
  16:     
  17: }

The HasFolderAndAutoId is used as a mixin by all the extents within the System.Identity schema and clearly illustrates that the Id field is used to store a SQL Server-managed identity field. This has particular ramifications when considering what it means for one object instance to be equal to another in the fluent interface.

At base, the problem stems from the fact that the primary means of establishing equality between two System.Identity objects at runtime is the value of the Id field and not the memory address of the object instances – the same row in a database table can be instantiated as more than one object in memory. Since establishing this ‘database equivalence’ is not the default behavior of the Equals() method inherited from System.Object, some custom code is required to ensure that the fluent interface works correctly.

Just to make things a little more interesting, a System.Identity object’s Id field is not actually populated with a value until the first time the object is saved to SQL Server. However, at runtime we may very well have legitimate need to call the Equals() method before the objects are saved. As such, we need an Equals() implementation that handles both states – persisted objects (with Id values) and non-persisted objects (no Id values assigned yet).

To address the no Id situation I’ll just make the Id field of the SystemIdentityBase class (which the Kind class inherits from) a nullable field. Here’s the updated code:

   1: public abstract class SystemIdentityBase
   2: {
   3:     protected Int64? Id { get; private set; }
   4:  
   5:     // Rest of code omitted
   6: }

 

Handling Reflexivity

OK, with that taken care of, I can stub in some of the no-brainer code for the Equals() method implementation. For those readers that are interested, the book “Effective C#” has excellent coverage of overriding the Equals() method. The code that follows borrows heavily from the book’s goodness:

   1: public override bool Equals ( object obj )
   2: {
   3:     if ( obj == null )
   4:     {
   5:         return false;
   6:     }
   7:  
   8:     if ( ReferenceEquals ( this, obj ) )
   9:     {
  10:         return true;
  11:     }
  12:  
  13:     if ( this.GetType () != obj.GetType () )
  14:     {
  15:         return false;
  16:     }
  17:  
  18:     throw new NotImplementedException ();
  19: }

Lines 3-11 above are textbook C#, but the code on line 13-16 is interesting. If you take a look at MSDN’s coverage of overriding Equals() there’s this interesting little tidbit:

  • x.Equals(y) returns the same value as y.Equals(x).

This has some interesting ramifications on the implementation of the Equals() override. The bullet above prescribes that overrides of Equals() have to support reflexivity. When one considers polymorphic inheritance, this gets a little complicated. Take, for example, two classes where one class (call it ‘B’) inherits from another (call it ‘A’). Using these hypothetical classes, the bullet above prescribes that the instance call of ‘a.Equals(b)’ must return the same value as the instance call of ‘b.Equals(a)’. This example illustrates that 100% reflexivity cannot be provided unless we consider only exact types in our Equals() overrides (again, take a look at “Effective C#” for great coverage of this topic).

The code in lines 13-16 ensures that only objects that are of the exact same type continue on for further Equals() processing.

 

Addressing Database Equivalence

Given the starting code above, I can add the following to the Equals() method:

   1: Kind otherKind = obj as Kind;
   2:  
   3: if ( Id.HasValue && otherKind.Id.HasValue && ( Id.Value == otherKind.Id.Value ) )
   4: {
   5:     return true;
   6: }

Here we address the ramifications of M-based persistence in SQL Server. Essentially, the code on line 3 in the snippet above says that two Kind objects in memory are equal if they have the same SQL Server-controlled Id (which implies that both have non-null Id fields).

No rocket science here.

 

The End Game

Lastly, the Equals() method handles the case where two non-null Kind objects are being compared, the two objects are at different memory addresses, and one of them (or both) doesn’t have an Id populated by SQL Server. Here’s the last of the code:

   1: return Name == otherKind.Name &&
   2:        Keywords. == otherKind.Keywords &&
   3:        Owner.Equals ( otherKind.Owner );

The code snippet above clearly illustrates that I’m taking the point of view that two Kind object are equal if the Name, Keywords, and Owners are equal (given the constraints listed immediately above the snippet).

This is purely a call on my part since System.Identity does not (to my knowledge) provide any guidance on the equivalence of the extents defined in the schema.

Just for the sake of completeness, here’s the full method in a single listing:

   1: public override bool Equals ( object obj )
   2: {
   3:     if ( obj == null )
   4:     {
   5:         return false;
   6:     }
   7:  
   8:     if ( ReferenceEquals ( this, obj ) )
   9:     {
  10:         return true;
  11:     }
  12:  
  13:     if ( this.GetType () != obj.GetType () )
  14:     {
  15:         return false;
  16:     }
  17:  
  18:     Kind otherKind = obj as Kind;
  19:  
  20:     if ( Id.HasValue && otherKind.Id.HasValue && ( Id.Value == otherKind.Id.Value ) )
  21:     {
  22:         return true;
  23:     }
  24:  
  25:     return Name == otherKind.Name &&
  26:            Keywords. == otherKind.Keywords &&
  27:            Owner.Equals ( otherKind.Owner );
  28: }

 

Next Time

As I mentioned above, the subject of my next post will be an implementation of GetHashCode() that will address the ramifications of M-based persistence in SQL Server.

Stay tuned!

Fluent Interface for System.Identity – Kind Command-Query API

Part 1 of this series functioned as an introduction to the motivations for creating a fluent interface for Oslo’s System.Identity. Part 1 also covered a number of architectural and design specifications that will be followed in the shaping of the interface’s code. In this post I’ll continue the crafting of the fluent interface by exploring an implementation of the Kind command-query API.

 

Refactoring the Base

Before I tackle the Kind class, I need to spend a little bit of time refactoring the SystemIdentityBase class that I developed in Part 1. Specifically, the class needs to be changed to more accurately reflect it’s use as a base class for command-query API child classes in the fluent interface. The code snippet below illustrates the latest rev of the SystemIdentityBase class:

   1: public abstract class SystemIdentityBase
   2: {
   3:     protected Int64 Id { get; private set; }
   4:     protected int Folder { get; private set; }
   5:  
   6:     public SystemIdentityBase ()
   7:     {
   8:         MoveToFolder ( 100 );
   9:     }
  10:  
  11:     public SystemIdentityBase ( int folder )
  12:     {
  13:         MoveToFolder ( folder );
  14:     }
  15:  
  16:     public bool IsInFolder ( int folder )
  17:     {
  18:         return Folder == folder;
  19:     }
  20:  
  21:     public void MoveToFolder ( int folder )
  22:     {
  23:         Folder = folder;
  24:     }

As the snippet above illustrates, the SystemIdentityBase class’ properties have been refactored to allow child classes access to the ‘get’ properties. As we will see later in the series, direct access to these properties will make future code much cleaner without fracturing the OO design. The code snippet also illustrates the refactoring of the class constructors to use the MoveToFolder () method. This refactoring centralizes the ‘set’ functionality in a single location, thereby allowing future logic to reside in a single place – not rocket science to be sure, but nice nevertheless.

 

Breaking “Tell, Don’t Ask”

Now that we have our base class refactored, we can take a stab at the Kind class. The very first thing that we’ll do with the Kind class is break “Tell, Don’t Ask”:

   1: public class Kind : SystemIdentityBase
   2: {
   3:     public string Name { get; private set; }
   4:     public string DescriptiveInformation { get; private set; }
   5: }

Hopefully what the code snippet above illustrates is that there are times when it is appropriate from an OO design perspective to allow clients to ask an object about the object’s state. I would argue that line #3 in the snippet reflects very much the way things work in the real world and, therefore, is good OO design.

Think about the legal system here in the US. When in a court of law a witness is not asked a series of questions (e.g., “Is your name John?”, “Is your name David?”) to establish the witness’ identity – the witness states their name for the record. Additionally, changing one’s legal name in the US is not a trivial affair – there is a process involved that sometimes rejects the name change (although my understanding is that this is rare).

These concepts are modeled in the code snippet above by allowing public read access to the Name property, but making changes to Name private.

The same real-world experience is applied to a Kind’s DescriptiveInformation. In the real world no one is asked “Are you male?” or “Is your weight 187 pounds?”. As with names, descriptive information is directly solicited in the real world. As those of us who have tried to lose weight know, it is often a nontrivial effort to change our descriptive information as well :-).

The remaining two properties of the Kind class don’t fall into the same category as Name and DescriptiveInformation so I’ll make them private:

   1: public class Kind : SystemIdentityBase
   2: {
   3:     public string Name { get; private set; }
   4:     public string DescriptiveInformation { get; private set; }
   5:     private string Keywords { get; set; }
   6:     private Party Owner { get; set; }
   7: }

 

Back to “Tell, Don’t Ask”

In accordance with the “Tell, Don’t Ask” architectural specification, I’ll add some methods to the Kind class’ interface:

   1: public void ChangeName ( string name )
   2: {
   3:     Name = name;
   4: }
   5:  
   6: public void ChangeDescription ( string descriptiveInformation )
   7: {
   8:     DescriptiveInformation = descriptiveInformation;
   9: }
  10:  
  11: public void ChangeKeywords ( string keywords )
  12: {
  13:     Keywords = keywords;
  14: }

The ChangeName(), ChangeDescription(), and ChangeKeyword() methods are straightforward, so I won’t belabor them. The following methods that I’ll add are far more interesting:

   1: public bool MatchesKeywords ( Func<string, bool> matchingSpecification )
   2: {
   3:     return matchingSpecification ( Keywords );
   4: }
   5:  
   6: public bool MatchesKeyword ( string keyword, KeywordComparisonType comparisonType )
   7: {
   8:     switch ( comparisonType )
   9:     {
  10:         case KeywordComparisonType.CaseSensitive:
  11:             return Keywords.Contains ( keyword );
  12:         case KeywordComparisonType.CaseInsensitive:
  13:             return Keywords.ToLower ().Contains ( keyword.ToLower () );
  14:         default:
  15:             throw new ArgumentOutOfRangeException ();
  16:     }
  17: }

The MatchesKeywords() method, arguably, is the epitome of “Tell, Don’t Ask” – it allows a client to provide the exact means of deciding a keyword match through the use of a delegate. By way of comparison, the MatchesKeyword() method doesn’t use a lot of “tech” to get the job done. For those that are curious about the implementation of the switch statement in the snippet above, I would refer you to “Effective C#”, Item #8 for more info.

The following snippet finishes up this rev of the Kind class by addressing the Owner functionality:

   1: public void ChangeOwner ( Party owner )
   2: {
   3:     Owner = owner;
   4: }
   5:  
   6: public bool IsOwnedBy ( Party owner )
   7: {
   8:     if ( Owner == null || owner == null )
   9:     {
  10:         return false;
  11:     }
  12:     else
  13:     {
  14:         return Owner.Equals ( owner );
  15:     }
  16: }

Generally speaking, there’s not much in the snippet above that we haven’t seen already. The one exception to this is line #14 – the call to the Equals() method of the Owner object (which is an instance of the Party class). While this line of code appears trivial, it does in fact have some very interesting ramifications to the fluent interface implementation.

These ramifications are born of the fact that System.Identity is shipped as part of the latest Oslo CTP’s Repository – which means that the fluent interface must also address concerns related to persistence.

 

Next Time

For the next post in the series I’ll address some of the ORM considerations that arise from Oslo’s use of SQL Server as the System.Identity persistence mechanism.

Stay tuned!

Fluent Interface for System.Identity – The Basics

<Author’s Note>

A very talented Developer I know just recently gave me some very succinct feedback on my blog - “good blog…too long”.

As I respect this Developer’s opinion quite highly (not to mention I always try to listen to Developers), I am going to start putting his suggestion into practice by chunking further posts into smaller pieces.

It is worthy to note that these smaller pieces will quite likely lead to more frequent posts – apologies in advance for any RSS bloat.

</Author’s Note>

 

Introduction

As I’ve written about previously, I’m highly interested in DSLs and Oslo’s System.Identity schema. Based on these two interests I recently decided that I would start exploring a Fluent Interface as an Internal DSL for the System.Identity schema. My motivations for this are two-fold:

  1. Give myself an excuse to play around with actual code
  2. Attempt to illustrate the power of the Party Model (via System.Identity) using an avenue that may be more appealing than (as much as it pains me to type this ;-) UML

Being both an Architect and unrepentant Object-Oriented bigot, I’ve convinced myself that this exploration will adhere to number of “modern” OO Software Engineering best practices. My intent with taking the tack is to hit a number of coding topics that are near and dear to my cold and black Architect heart. We shall see if I will be successful in this regard.

 

Fluent Interface Architectural/Design Principles

Throughout this subseries on System.Identity I plan to adhere to a number of Architectural/Design specifications in crafting the interface code:

  1. The architectural specification of the Law of Demeter
  2. Martin Fowler’s design specification for a Parsing Layer
  3. Domain-Driven Design’s (DDD’s) design specification for Aggregates
  4. The Pragmatic Bookshelf’s design specification for “Tell, don’t ask
  5. Design specifications from the concepts included in Prefactoring

As we shall see, application of these five specifications will have very interesting consequences on the shape of the code. Indeed, I wouldn’t be surprised at all if the code’s shape ends up looking quite a bit different from “run of the mill” C#. One potential effect of this might be that the Command-Query API will tend to look more like a Fluent Interface. 

To be honest, I expect that quite a number of readers will disagree with either my interpretations of these specifications, or they will disagree with my practical application of these specifications in the code. Some readers will undoubtedly disagree with both.

This is 100% by design and I sincerely look forward to any discussion on these topics.

 

Starter Class

As we saw in the UML models of System.Identity, every class had two basic attributes – an Id field and a Folder field. For the sake of convenience we’ll create an abstract base class that encapsulates this universality:

 

   1: public abstract class SystemIdentityBase
   2: {
   3:     private Int64 Id { get; set; }
   4:     private int Folder { get; set; }
   5:  
   6:     public SystemIdentityBase ()
   7:     {
   8:         Folder = 100;
   9:     }
  10: }

What some folks might find interesting in the snippet above is that the automatic properties on lines 3 and 4 are marked private. One of the design specifications from Prefactoring is that it is better to put a level of indirection between the state of an object and the object’s operations. In terms of early versions of C# that meant only accessing a class’ member variables via a property – even in private helper methods.

Since automatic properties can’t hold any business logic or data access code, I would argue that automatic properties are nothing more than syntactic sugar for old school member variables.  Therefore, under Prefactoring thinking, an additional level of indirection is required. In accordance with this design specification, the automatic properties are marked private.

We can now augment SystemIdentityBase’s public interface with some methods that adhere to Prefactoring, the Law of Demeter and the “Tell, don’t ask” specifications:

   1: public bool IsInFolder ( int folder )
   2: {
   3:     return Folder == folder;
   4: }
   5:  
   6: public void MoveToFolder ( int folder )
   7: {
   8:     Folder = folder;
   9: }

The IsInFolder() method conforms to “Tell, don’t ask” specification by disallowing clients of SystemIdentityBase instances from directly retrieving the Folder value and basing decisions on that value. To use a conversational metaphor, this results in statements along the lines of “Tell me if you’re currently in this folder” rather than “Give me your current folder”. This is a core aspect of “Tell, don’t ask” and simultaneously increases cohesion and lowers coupling in the code. Another benefit of shaping the code in this manner is an increase in the “fluency” of the Command-Query API.

In terms of the Law of Demeter, the IsInFolder() method is compliant with the architectural specification because it prevents code like the following:

   1: var testValue = 125;
   2:  
   3: if ( testValue == someEntity.Folder )
   4: {
   5:     // Do some cool logic here
   6: }

While the snippet above seems innocuous enough, what really happens behind the scenes is the following:

   1: var testValue = 125;
   2:  
   3: if ( someEntity.Folder.Operator == ( testValue ) )
   4: {
   5:     // Do some cool logic here
   6: }

Strictly speaking, this “two dot” situation is violation of the Law of Demeter (being quite the stickler here, aren’t I? ;-). Compare the above code to the following:

   1: var testValue = 125;
   2:  
   3: if ( someEntity.IsInFolder ( testValue ) )
   4: {
   5:     // Do some cool logic here
   6: }

Call me an OO junkie, but I just like the look of this last code snippet a lot better – even though I’ve personally written a ton of code that uses the straight “property-ask, then compare” approach. The code just feels like OO should. I also know that from first-hand experience that this style of code is easier to maintain over long periods (say 5 year or so) in Production.

Compared to IsInFolder(), the MoveToFolder() method is a straight forward “setter” method for the Folder automatic property and really doesn’t bear a lot of explanation. That being said, it is interesting to note that we again have another increase in the fluency of the Command-Query API from compliance with the chosen architectural/design specifications. Take the following code snippet as an example:

   1: var testValue = 125;
   2:  
   3: someEntity.MoveToFolder ( testValue );

For the time being I’ll leave the Id fields of the entities alone. I’ve got two main reasons for this:

  1. The Ids are really just RDBMS implementation details – a good ORM framework (e.g., NHibernate) usually takes care of the administration of these things transparently
  2. Leaving out makes the posts shorter and we don’t miss any of the goodness

 

Next Time

For the next post in the series we’ll move to take a look at an implementation of the Command-Query API Kind class.

Until next time, thoughts greatly appreciated!

The Formal Goodness of Agile Software Architecture – Part 2

In Part 1 of this short series I discussed an article that proposes the Intensional/Locality Thesis for formally distinguishing between what is Architecture and what is Design. Part 1 also covered how the Thesis has shaped my thinking about the role of the Architect and Software Architecture within an Agile project team.

As I was writing Part 1, specifically the bulleted lists of architectural specifications, it occurred to me that I had used a number of mechanisms on past projects to communicate Architecture. These mechanisms have included:

  • Whiteboard conversations (my personal favorite)
  • Word documents using text (my least favorite)
  • Visio diagrams (OK, but lacks some rigor)
  • UML models (another personal favorite)

It was towards the end of writing Part 1 that I decided that in fact there would be two posts – Part 1 describing how the Intensional/Locality Thesis reshaped my thinking and this post describing how to use UML models to communicate architectural specifications (in compliance with the Thesis) in an Agile way.

As I was thinking about the prep work for this post, I figured I would have to fire up Sparx and create a UML model to use as a case study. However, as I got prepared to do some modeling it occurred to me that I might already have something better.

A number of months back I created a sample UML model to illustrate one way that UML could be used for Software Architecture on an Agile project. The main goal of the sample was to illustrate how UML can be a powerful communication and documentation tool that enhances the agility of a team – how Architecture can be a point of leverage.

Intrigued by the reuse potential, I’ve decided to use this UML model to see how it stands up to the ideas discussed in Part 1. What follows in this post is the unaltered UML model I created, interpreted in the context of the Intension/Locality Thesis.

NOTE – There is a complete HTML representation of this UML model available from my SkyDrive. The link to the .ZIP is located at the bottom of this post.

 

The Conceptual View

The first item of interest in the UML model is the Conceptual View. The intent of this model is to communicate the overall architecture of the software at a relatively high level of abstraction. While not 100% correct from a UML standards perspective, this model leverages the UML Component diagram as the means of communication. The Conceptual View is depicted below:

ConceptualView

When using the concepts in Part 1 to interpret the model depicted above, we can quickly identify that the Conceptual View declares a number of architectural specifications. We can also identify that these specifications adhere to the two main categories described in Part 1:

  • “Traditional” architectural specifications (e.g., Pipes and Filters)
  • Design specifications (aka Patterns) that have been elevated to architectural specifications

The first thing that is worthy to note is that the Conceptual View prominently lays out the first architectural specification – the use of a Layered Architecture.

Additionally, the Conceptual View incorporates a large number of constraints on the structure of the software:

  • The Presentation Layer depends upon the Services Layer
  • The Services Layer depends upon the Application Layer
  • The Application Layer depends on a Data Access Layer (DAL)
  • The Application Layer depends upon the following:
    • The Exception Handling Application Block of the Enterprise Library
    • The Logging Application Block of the Enterprise Library
  • The DAL depends on the following:
    • The Caching Application Block of the Enterprise Library
    • NHibernate framework

That’s a lot of architectural goodness derived from a single diagram, but is typical of the large amount of leverage I’ve seen in crafting architectures that are replete with Design Patterns.

As you might imagine, a full-blown collection of architectural specifications would likely include guidance on how Repositories should be implemented using NHibernate, how the Exception Handling Application Block will be configured, how the Caching Application Block should be used, etc.

For the sake of brevity the UML model isn’t 100% complete, but it does illustrate a very powerful mechanism that UML has for modeling architectural specifications – UML patterns.

 

Repository Architectural Specification

As the Conceptual View illustrates, there is an architectural specification for the use of the “Repository Pattern”. As covered in Part 1 of the series, I tend to think that one of the duties of the Agile Architect is transforming appropriate Design Patterns (which are inherently design specifications under the Intensional/Locality Thesis) into architectural specifications. This transformation is attained mainly through moving the scope of a Design Pattern from local to non-local. As illustrated in the Conceptual View, this transformation is embodied in the following subsection of the model:

RepositoryArchSpec

The problem with this architectural specification is that it isn’t very clear to both the Developers and Code Reviewers/Code Pairs what this means in terms of the constraints on the structure of the software - even if the team is familiar with Repositories and has read Evans. That’s not so say there’s no value in the architectural specification as it stands (there is definite value in communicating the architecture at a high level), it’s just that if the specification could be enhanced it would become an even greater point of leverage for the team.

This enhancement can be accomplished very easily using the UML concept of a Pattern (some additional info is available here). Rather than bore you with the all the UML standards goodness, I’ll just pull the depiction from the model of the “Repository Pattern”:

RepositoryPattern

As discussed in the Eden and Kazman article on the Intension/Locality Thesis, both architectural and design specifications concentrate on the definition of constraints on the structure of the software – they just differ on the scope of the constraints (the locality). The UML pattern specification above clearly illustrates this concept in the definition of the roles that constitute the pattern (e.g., “Repository Factory”) and constraints on those roles (e.g., “Only domain entities that are Aggregate Roots can have Repositories”).

What is particularly noteworthy in model above is that the pattern roles define a further constraint in terms of the use of a standard code interface (“IRepository<T>”). We’ll see the implication of this below.

As I discussed in Part 1, notice how this pattern does not specify to a Developer on the team which exact Aggregates, Aggregate Roots, and Repositories need to be built (e.g., Contracts, Customers, Orders, etc) – it only specifies only how these items should be built.

While this enhancement of the Repository architectural specification provides powerful leverage to the team, UML has one last enhancement to increase the power of Agile Software Architecture. The following model illustrates a hypothetical example of software that is in compliance with the Repository architectural specification:

RepositoryPatternExample

As I described in Part 1, I would argue this model exemplifies the difference between Architecture and Design in an Agile project. I would also argue that the model above illustrates the differences between the Architect and Developer roles on an Agile project. Specifically, the model above illustrates that the Agile Architect is responsible for the definition of the architectural constraints of the software (Repository in this case). Additionally, the model illustrates that another role on the team identifies that a design is required for the concept of “Product” that complies with the architecture of the software – the Developer role on Agile projects.

NOTE – As I’ve wrote previously, the best Architects also craft software. As such, it is important to understand that Architects may bounce back and forth between the Architect and Developer roles on an Agile project – defining architectural specifications one day and delivery software in compliance with the architecture the next.

A second, more complex, example will hopefully cement these ideas.

 

WCF Service Architectural Specification

The Conceptual View of the software architecture identifies the usage of the “WCF Service Pattern” as an architectural specification. Specifically, the following subsection of the Conceptual View defines this architectural specification:

WCFServiceArchSpec

As we saw previously with the Repository architectural specification, the WCF Service architectural specification has a UML pattern specification:

WCFServicePattern

While the WCF Service architectural specification is quite a bit more complicated than the Repository architectural specification, it is worthy to note that it again clearly segments Architecture from Design and segments the Architect from the Developer on an Agile project. Another thing that is worthy to note in the model above is the multiplicity constraint within the “WCF Operation Contract” role in the pattern. Specifically, this constraint specifies that every instance of the WCF Service architectural specification must have at least one instance of the “WCF Operation Contract” role, but there is no upper bound on the number of “WCF Operation Contracts”.

As with the Repository architectural specification, the WCF Service architectural specification also included an example instantiation of a design that is compliant with architectural spec. The model below illustrates this example design:

WCFServicePatternExample

There you have it! Some very powerful examples of how to leverage UML for Agile Architecture that is compliant with the Intension/Locality Thesis.

 

Reusable Code Assets

The above architectural specifications rely on some common reusable code assets as part of their constraints on the structure of the code. The following model illustrates the these assets from the UML model.

CoreClassesAndInterfaces

Don’t Fear UML & Software Architecture

Believe it or not, UML and Software Architecture are not antithetical to the use of Agile.

I’ve personally seen these tools and techniques succeed under both XP-like and Scrum-like (I use “-like” because I never seen a “pure” implementation – nor do I ever expect to ;-) methodologies. Typically architecture in these instances were a Sprint (or two 2-week XP iterations) at the start of the project, and then the architecture is iteratively addressed Agile-style throughout the project. Those of you who are in the know will recognize this as akin to some of the ideas behind RUP Elaboration.

I heartily advise giving this a try – your Developers will love you for it and it just might increase the fun you have as an Architect to boot!

Any feedback from Architects and Developers on this series would be greatly appreciated.

SkyDrive Files

The Formal Goodness of Agile Software Architecture – Part 1

The purely addictive aspects of working at The Big Show for a geek like me cannot be underestimated. In many ways Microsoft is like any other Fortune 500 company I’ve worked or consulted for, but I’m often reminded that working for Microsoft is different – it’s pure crack for geeks.

As an example, I recently attended a talk given by one of Microsoft’s Distinguished Engineers (DEs) on the subject of Software Architecture. One of the core tenets of this talk was the classification of what constitutes “Architecture” and what constitutes “Design”.

This is a subject I personally have found fascinating for a long time. In my years as an Architect I’ve had to explain the differences between these two highly abstract ideas on a number of occasions. Over time I became convinced that I had some really insightful, if not profound, explanations on the subject.

Later, when I was afforded the singular privilege of working with some very senior Developer talent (BTW, I define “senior Developer” based on knowledge and skill, not necessarily years of experience) in successfully developing software using Agile practices, I started to second-guess the wisdom of my explanations on what constitutes “Architecture” and “Design”.

Over the past few years I haven’t really had a satisfactory way of thinking about these concepts that mapped to my experiences doing Agile “the right way”.

It was during the course of the DE’s talk that I realized that this Architect may have found the “secret sauce” (to steal a term from Gabriel) I was looking for.

This particular DE strongly recommended an article where the authors (Eden and Kazman) formalize the distinction between “Architecture” and “Design”.

What I read was a simple and elegant way to classify what is “Architecture” and what is “Design”.

What I read explained the goodness that I’ve seen in building software in an Agile way.

What I read was pure, unadulterated crack…

 

Intension/Locality Thesis

In the article Eden and Kazman propose a formal basis for the distinction between the concepts of “Architecture”, “Design”, and “Implementation”. This distinction is formalized as the Intension/Locality Thesis:

  1. Architectural specifications are intensional and non-local;
  2. Design specifications are intensional but local;
  3. Implementation specifications are both extensional and local.

For the purposes of this post I’ll be ignoring the third point above, focusing instead on how the Intension/Locality Thesis applies to Agile Software Architecture. Before I can do this, I need to talk a bit about Intension and Locality.

NOTE – The rest of this post uses the term “specification” since the cited article uses this term extensively. However, I personally use this term very loosely. In my mind an Agile specification doesn’t necessarily entail a Word document or UML diagram. A whiteboard session with the Developers where certain decisions are reached (and maybe documented with digital photos), I would argue, also can constitute a specification in the context of this post.

 

What is Intension?

According to the dictionary the relevant definition is:

5. Logic. (of a term) the set of attributes belonging to all and only those things to which the given term is correctly applied; connotation; comprehension. Compare extension (def. 12).

Within the article, the authors further elaborate that specifications are intensional in nature if they define concepts in terms of constraints rather than relying on specific (or extensional) definitions.

For example, the specification “All source code will be written in a .NET language” is intensional in nature. This specification is intensional because it allows any programming language that is compliant with the constraint “a .NET language” (define that how you will ;-) to be used to author source code.

By way of comparison, the specification “All source code will be written in C# and/or VB.NET” is extensional in nature. The extensional constraint explicitly defines which programming languages can be used – C# and VB.NET.

Another way of thinking about intensional specifications is in terms of the number of ways that software can be structured to be in compliance with the specification – for intensional specifications the number of software structures that could be compliant with the spec is infinite (or a very, very large number).

 

What is Locality?

The article formalizes the idea of locality through the concept of subsumption. Essentially, a specification is considered local if every subsequent extension to the software is executed in a manner that complies with the initial specification. That is, every extension to the software subsumes the initial specification.

Since this is a little abstract, another way to think of specifications is that they are local if a subsection of the software satisfies the constraints of the specification without having an effect on the structure of the rest of the software.

By way of comparison, a non-local specification has an effect on the entire software structure – every nook and cranny. In terms of extension, this means that each and every change to the software must be in constant compliance with the original specification.

An example of a non-local specification is the requirement that all .NET classes must eventually have System.Object as a base class. In the case of .NET, this specification is so pervasive that the .NET compiler implicitly adds the System.Object inheritance even if the Developer doesn’t explicitly code it up. Any time you extend existing .NET software with a new class, the extension is always in compliance with this specification.

 

What is Design?

According to the Intension/Locality Thesis “Design” is simultaneously intensional and local. Based on the understandings of intension and locality described above, the following can be deduced about design specifications:

  1. Design provides a specification for software that can be fulfilled in an infinite number of ways.
  2. The constraints imposed by the Design specification are limited in scope – they do not affect every nook and cranny of the software’s structure.

Based on this meaning of Design, the article interestingly points out that the Gang of Four (GoF) arguably provides the quintessential set of Object-Oriented design specifications.

For example, the usage of the Strategy pattern within a set of C# code files fulfills the requirement of being intensional (the Strategy pattern can be coded in an infinite number of ways) and it is also limited in scope (the locality is the set of C# code files).

Additionally, subsequent extensions to the C# code can easily subsume the original design specification. For example, the addition of a Factory for the creation of Concrete Strategy instances to the code subsumes the original design specification. In turn, a further extension to the C# code to incorporate a Use Case Controller that uses the Factory and Strategies subsumes both design specifications, thereby continuing the “chain of locality” for the previous design specifications for the code.

 

What is Architecture?

Like Design, Architecture specifications must be intensional. However, Architecture is non-local – the constraints of Architecture specifications enforce compliance through every nook and cranny of the software’s structure.

The article cites the Law of Demeter as an example of an Architectural specification. From Wikipedia’s article, the Law of Demeter can be written as:

More formally, the Law of Demeter for functions requires that a method M of an object O may only invoke the methods of the following kinds of objects:

  1. O itself
  2. M’s parameters
  3. any objects created/instantiated within M
  4. O’s direct component objects

In reading the above definition it is clear that the Law of Demeter can be implemented in an infinite number of ways (it is intensional). What is also clear is that the Law of Demeter has an effect on every nook and cranny of the software’s structure (OK, this implicitly assumes using the OO paradigm, but you get the point ;-) – it literally dictates the way Developers engineer all of the software (it is non-local).

Another interesting way to think about the Law of Demeter is in terms of subsumption.

Take the hypothetical example of a piece of software that has been engineered in compliance with the Law of Demeter. If this piece of software is extended at a later point in time in a way that isn’t compliant with the Law of Demeter, but doesn’t alter the original structure, then we have the following situation:

  • The new software structure subsumes the original specification
  • The new software structure violates the architecture specification of the Law of Demeter.

Thinking about subsumption gives another way of defining whether a specification is architectural – can extensions to a compliant software structure subsume the original specification and then subsequently violate the original specification? If the answer is yes, then the specification is Architecture, not Design.

The article cites a number of classic examples of architecture specifications that are widespread in the industry, namely Pipes and Filters and Layered Architecture.

 

Agile Software Architectures

What I find so compelling about the concepts described above is that they explain the successes I’ve experienced firsthand in Agile projects. The tools, techniques, and practices that organically grew out of my working with the Developers on these projects can all be easily equated to the Intension/Locality Thesis – we just didn’t know that there was formal goodness that explained why we were successful.

Specifically, I would argue that the Intension/Locality Thesis explains the following in terms of Agile development:

  • What constitutes the Architecture of the software (or the “Metaphor” if you’re into XP)
  • What constitutes the Design of the software
  • What is the purview and concerns of the Architect
  • What is the purview and concerns of the Developer
  • What is the purview and concerns of the Code Reviewer/Code Pair

The first two bullet points are now old hat given the Intension/Locality Thesis, but interpreting the remaining three bullet points in terms of the Thesis and Agile is particularly interesting.

 

The Agile Architect

My experience has been that the Intension/Locality Thesis underlies the ability of an Architect to be agile by formalizing the mechanisms by which the Agile Architect leads through leverage. In terms of the Thesis, this usually takes on two primary forms:

  • The identification of those architectural specifications that most fit the problem space the software is attempting to address. Examples of these architectural specifications include:
    • Layered Architecture
    • Pipes and Filters
    • Law of Demeter
    • Unit test code coverage metrics (e.g., all Use Case Controllers shall have 80+% coverage)
    • Coding standards (e.g., no direct access to class member variables)
  • The identification of design specifications as constraints on the software structure. These identifications transform the design specifications to architectural specifications by making them non-local in nature. Examples of these identifications include:
    • All UI Layer code shall be written using the Model-View Presenter (MVP) pattern
    • All MVP Presenters shall rely on a WCF Service Layer as the Model
    • All WCF services shall delegate implementation to Use Case Controllers
    • The Application Layer Domain Model shall be built as DDD Aggregates
    • All Data Store access shall be implemented using DDD Repositories

You’ll notice a large emphasis on the usage of “off the shelf” architectural and design specifications above (aka Patterns). This is, IMHO, nothing more than the natural manifestation of leverage that organically occurs within successful Agile projects – the result of the need for real-time, high-bandwidth communication between team members. My experience has been that teams inevitably come up with a vocabulary to facilitate high-bandwidth communication. As such, it only makes sense to me not to have to reinvent the wheel every time.

 

The Agile Developer

The Intension/Locality Thesis again provides an elegant formalization for thinking about the role of the Developer on an Agile project. In terms of the Thesis, the Agile Developer is primarily responsible for one thing – engineering software that complies with the architectural specifications.

Now we all know that Agile Developers are responsible for far more than this. For example, Developers are responsible for executing the Agile practices of the team (e.g., CI, Pair Programming, Daily Scrums, etc), but it is interesting to note that on an Agile team the actual engineering constraints are actually pretty light.

However, my experience has been that the best Developers (not to mention the only Developers I would want to work with on an Agile project) self-enforce another engineering constraint on the software – they extensively leverage “off the shelf” design specifications (aka Patterns) in their code.

As an example, take the following hypothetical scenario. A Developer is working on a project where an architectural specification is “All WCF services shall delegate implementation to Use Case Controllers”. As part of the Developer’s Use Case Controller implementation the developer elects to employ the Visitor pattern to apply validation logic on incoming messages to the Controller.

Notice that the Agile Developer doesn’t run her Visitor-based design by the Architect or Dev Lead – they just implement it. No design docs, no design reviews, just the essence of Agile – the creation of quality software by empowered team members.

 

The Agile Code Reviewer/Code Pair

Again, the Intention/Locality Thesis provides excellence guidance as to the activities and concerns of the Agile Code Reviewer (or Code Pair). In line with the Thesis, the Code Reviewer is primarily concerned with the monitoring of, coaching on, and enforcement of the architectural specification constraints within the software.

I would argue that this is a critical idea that often gets lost. If everyone is spending inordinate amounts of time preparing for, conducting, and remediating Code Reviews how Agile can your team actually be? If a team legitimately needs this level of “quality control” then I would argue that the team has likely picked the wrong delivery methodology based on the risk profile of the project (which, BTW, may include the risk that the Developers are not senior enough to do Agile).

I would also add that the best Agile teams have Code Reviewers that naturally taken on a secondary review concern for the identification of any “code smells” within the software. Typically, these code smells tend to take on one of three primary forms:

  • The Developer could benefit from the application of one or more Patterns (design specifications)
  • The Developer applied a Pattern in a suboptimal/non-intuitive way
  • The Developer applied too many Patterns

As I’ve written about previously, the use of Code Reviewers should really be about creating leverage through the federation of architectural stewardship. What the Identity/Locality Thesis gives us is a formal and elegant way to classify exactly what “architectural stewardship” means.

 

Next Time

The Identity/Locality Thesis has got me pretty hopped up right now. As such, I’ve taken a short break from writing about System.Identity and M.

For my next post I’m going to wrap up my thoughts on the Thesis by exploring one last concept – how an Agile Software Architecture can be effectively modeled in UML for easy consumption by the team.

Stay Tuned!

Oslo “M” Graphs and Inheritance

In my last post I explored the subject of applying Object-Relational Mapping (ORM) concept to modeling in M. What I discovered was that M handles ORM pretty well and allows for the modeling of polymorphic inheritance within M metamodels – thereby enabling rich Object-Oriented runtimes to consume Oslo metamodels.

At the end of the post I briefly discussed the question of which of the two ORM patterns discussed in the post was best – at which point I quickly punted on the question.

My reasoning for punting was that a final accounting would need to wait until I explored the M graph implications of each of the ORM patterns.

This post will be that final accounting.

 

Table per Class Hierarchy Graphs

In the ORM post I first took a look at using a single M type to create an extent that would model an entire class hierarchy in the SQL Server Repository. This is ORM pattern has been an effective design for relatively simple class hierarchies where the classes don’t change much. For reference, here’s the M for the types and extents covered in the post:

   1: type Department
   2: {
   3:     Id: Integer64 => AutoNumber();
   4:     Folder: Integer32 => 100;
   5:     Name: Text#64;
   6: } where identity Id;
   7:  
   8:  
   9: type Person
  10: {
  11:     Id: Integer64 => AutoNumber();
  12:     Folder: Integer32 => 100;
  13:     Discriminator: Text where value in {"Person","Manager","IndividualContributor"};
  14:     FirstName: Text#32;
  15:     LastName: Text#32;
  16:     Department: Department? where value in Departments;
  17:     JobTitle: Text#32?;
  18:     Manager: Person? where value in People;
  19: } where identity Id;
  20:  
  21:  
  22: // Extent definitions
  23: Departments: Department*;
  24: People: Person*;

In terms of M graphs to instantiate the model, the code is really straightforward:

   1: // M graphs
   2: Departments
   3: {
   4:     Department1 { Name => "Department#1" },
   5:     Department2 { Name => "Department#2" }
   6: }
   7:  
   8: People
   9: {
  10:     JohnDoe { FirstName => "John", LastName => "Doe", Discriminator => "Person"  },
  11:     JoeManager { FirstName => "Joe", LastName => "Manager", Discriminator => "Manager", Department => Departments.Department1, JobTitle => "Manager", Manager => People.SteveDirector },
  12:     SteveDirector { FirstName => "Steve", LastName => "Director", Discriminator => "Manager", Department => Departments.Department1, JobTitle => "Director" },
  13:     FredWorker { FirstName => "Fred", LastName => "Worker", Discriminator => "IndividualContributor", Department => Departments.Department1, JobTitle => "Manager", Manager => People.JoeManager }
  14: }

As we can see from the code above, instantiating Person instances in the model is just a matter of providing the correct data based on the type being instantiated (as defined by the Discriminator field).

What I found pretty cool is that Intellipad actually gives you Intellisense when you’re authoring M graphs. This was very handy when referencing items in other collections. Here’s a screenshot illustrating the coolness:

MGraphIntellisense

Table per Concrete Class Graphs

The second ORM pattern relies on a M type and an extent for each concrete class in the hierarchy. Within the Oslo Repository this ORM pattern manifests as a collection of SQL Server tables where the tables representing derived classes (Manager and IndividualContributor) have Primary Keys (PKs) that are Foreign Keys (FKs) to the table representing the Person class. In using this ORM pattern, a join is required to the People table whenever a Manager or IndividualContributor is retrieved from the SQL Server Repository.

Here’s the M code for the ORM pattern:

   1: type Department
   2: {
   3:     Id: Integer64 => AutoNumber();
   4:     Folder: Integer32 => 100;
   5:     Name: Text#64;
   6: } where identity Id;
   7:  
   8: type Person
   9: {
  10:     Id: Integer64 => AutoNumber();
  11:     Folder: Integer32 => 100;
  12:     FirstName: Text#32;
  13:     LastName: Text#32;
  14:     Discriminator: Text where value in {"Person","Manager","IndividualContributor"};
  15: } where identity Id;
  16:  
  17:  
  18: type Employee
  19: {
  20:     Person: Person where value in People;
  21:     EmployeeId: Integer16;
  22:     Department: Department where value in Departments;
  23:     JobTitle: Text#32;
  24:     
  25: } where identity Person;
  26:  
  27:  
  28: type Manager : Employee
  29: {
  30:     Manager: Manager? where value in Managers;
  31: } where value.Manager.Person.Discriminator == "Manager";
  32:  
  33:  
  34: type IndividualContributor : Employee
  35: {
  36:     Manager: Manager where value in Managers;
  37: } where value.Manager.Person.Discriminator == "Manager";
  38:  
  39:  
  40: // Extent definitions
  41: Departments: Department*;
  42: People: Person*;
  43: Managers: Manager*;
  44: IndividualContributors: IndividualContributor*;

And the M graphs to instantiate the model:

   1: // M graphs
   2: Departments
   3: {
   4:     Department1 { Name => "Department1" }
   5: }
   6:  
   7: People
   8: {
   9:     JaneDoe { FirstName => "Jane", LastName => "Doe", Discriminator => "Person" }
  10: }
  11:  
  12: Managers
  13: {
  14:     SteveDirector { Person => { FirstName => "Steve", LastName => "Director", Discriminator => "Manager" }, EmployeeId => 1234, Department => Departments.Department1, JobTitle => "Director" },
  15:     JoeManager { Person => { FirstName => "Joe", LastName => "Manager", Discriminator => "Manager" }, EmployeeId => 4321, Department => Departments.Department1, JobTitle => "Manager", Manager => Managers.SteveDirector }
  16: }
  17:  
  18: IndividualContributors
  19: {
  20:     FredWorker { Person => { FirstName => "Fred", LastName => "Worker", Discriminator => "IndividualContributor" }, EmployeeId =>1122, Department => Departments.Department1, JobTitle => "Worker", Manager => Managers.JoeManager }
  21: }

The M graph code above illustrates the effects of this ORM pattern on model instantiation – notably the “in-graph” instantiations of Person instances within the Manager and IndividualContributor instances.

 

The Verdict

I would argue that the Table per Concrete Class ORM pattern, overall, is the better solution for modeling polymorphic inheritance in M models. My argument rests mainly on the following three factors:

  1. I like the explicitness of having to code up the “Person-ness” in the M graphs for Managers and IndividualContributors. The OO bigot in me is drawn very much to the clean separation between what Managers and IndividualContributors inherit from Person and what they extend from Person.
  2. The use of this ORM pattern allows for the explicit expression of the constraints in the original design (see the UML in the previous post for further details).
  3. The use of three separate types, and extents, allows for greater flexibility in terms of extension of the classes in the hierarchy (especially for the derived classes).

The only downside to the pattern is that the joins could become a performance bottleneck for deep/complicated inheritance hierarchies – although I’m not quite sure if this would be a problem in “normal” usage (I would tend towards an architecture that cached metamodel data at runtime, but that’s just me).

 

Next Time

This little investigation into M graphs has gotten me very excited about the possibilities of the Oslo platform.

As such, I’m going to be focusing my efforts now on actually working with M graphs at runtime with C# code.

Until next time, any thoughts/comments would be greatly appreciated.

Posted by dalanger | 1 Comments
Filed under: , , ,

Modeling Inheritance in Oslo’s “M”

As I recently posted, I’m very intrigued by the potential of the Oslo platform to democratize the use of metamodel-driven software architectures. As a first step in exploring the capabilities of the latest Oslo CTP I took some time over the weekend to dive into M – particularly modeling types using M (formerly known as MSchema). As I’m particularly interested in Oslo’s ability to provide a metamodel runtime, my plan was to take a UML-based metamodel, convert it into M, and stick it into the Repository. With plan in place, I fired up Intellipad, pulled up Oslo’s SDK docs, and started coding.

Everything was going smooth. M’s syntax is relatively intuitive and Intellipad is a reasonable tool (although I have to admit a definite preference to a full-blown IDE). The T-SQL preview pane in Intellipad is also very helpful to understand the evolving “shape” of your model in real time. Then, out of the blue, an old friend reared its inelegant head – Object-Relational Mapping (ORM).

This shouldn’t have surprised me since M is, at base, relational in nature.

The reason why I’m dealing with ORM in M is due to my Object-Oriented bias – I just can’t imagine a non-trivial runtime consuming the Oslo metamodel that wasn’t OO in nature. As such, it just seems natural to me to define my M metamodel in a way where the generated Repository tables would support some core OO concepts, namely polymorphic inheritance.

A quick search of the ‘Net didn’t really reveal any sources outlining inheritance patterns in M, although I found a number of items from folks complaining that M doesn’t support inheritance out of the box.

I figured since I needed to model inheritance in M for ORM support, I would whip up a quick post on the subject in case someone else would find the content useful.

For those that are interested, Scott Ambler wrote an excellent article on ORM. The article provides an awesome background on the subject and I’m implicitly assuming this level of knowledge for the rest of the post.

 

NOTE – I’m by far from an M expert, so I would greatly appreciated any feedback on this post – especially any assistance around better modeling inheritance in M.

 

The Scenario

UML class diagram below illustrates our OO scenario to be modeled in M. Please note that the scenario is very much contrived (and I would argue bad design, since the Party Model is a far superior solution), but it will suit our purposes for this post:

OsloInheritance

It is worthy to note that the UML model defines the following constraints that our M modeling will attempt to replicate:

  1. Departments can have zero-to-many Employees
  2. Each Employee must have a Department
  3. An IndividualContributor must have a Manager
  4. A Manager may, or may not, have a Manager

 

Table per Class Hierarchy

Using this ORM pattern we will map the Person, Employee, Manager, and IndividualContributor classes to a single M type which we will then declare as an extent. First, though, we will start with our M for Department:

   1: type Department
   2: {
   3:     Id: Integer64 => AutoNumber();
   4:     Folder: Integer32 => 100;
   5:     Name: Text#64;
   6: } where identity Id;

 

Next is the M code for our combined Person type. Note that the constraints get pretty gnarly since we have to accommodate different types within the People extent via the Discriminator field. Note that the extent definitions at the end of the code snippet:

   1: type Person
   2: {
   3:     Id: Integer64 => AutoNumber();
   4:     Folder: Integer32 => 100;
   5:     Discriminator: Text where value in {"Person","Manager","IndividualContributor"};
   6:     FirstName: Text#32;
   7:     LastName: Text#32;
   8:     Department: Department? where value in Departments;
   9:     Manager: Person? where value in People;
  10: } where identity Id;
  11:  
  12:  
  13: // Extent definitions
  14: Departments: Department*;
  15: People: Person*;

 

As the M code above illustrates, the Person type stands in for all classes in the hierarchy. As such, the Person type has a couple of optional fields that allow for the modeling of Managers and IndividualContributors. Additionally, the Person type defines a discriminator field that allows for the determination of the type (“Person”, “Manager”, “IndividualContributor”) of a particular Person instance.

For those folks that have battled the ORM dragon before, the M code for Person is very much old hat. In exchange for a simple model (a single table for the whole class hierarchy) we’ve had to give up some fidelity in terms of constraints that were defined in the UML class diagram – we’ll need to implement those constraints elsewhere (e.g., a DSL grammar), unfortunately.

The M code above generates the following T-SQL for Repository storage of the model:

   1:  
   2: set xact_abort on;
   3: go
   4:  
   5: begin transaction;
   6: go
   7:  
   8: set ansi_nulls on;
   9: go
  10:  
  11: create schema [TablePerClassHierarchyInheritance];
  12: go
  13:  
  14: create table [TablePerClassHierarchyInheritance].[Departments]
  15: (
  16:   [Id] bigint not null identity,
  17:   [Folder] int not null default 100,
  18:   [Name] nvarchar(64) not null,
  19:   constraint [PK_Departments] primary key clustered ([Id])
  20: );
  21: go
  22:  
  23: create function [TablePerClassHierarchyInheritance].[Check_People_Func]
  24: (
  25:   @_Id as bigint
  26: ,   @_Department as bigint
  27: ,   @_Discriminator as nvarchar(max)
  28: ,   @_FirstName as nvarchar(32)
  29: ,   @_Folder as int
  30: ,   @_LastName as nvarchar(32)
  31: ,   @_Manager as bigint
  32: )
  33: returns bit  as
  34:   begin
  35:     return case
  36:   when @_Discriminator in (N'Person',
  37: N'Manager',
  38: N'IndividualContributor') then (1)
  39:   else (0)
  40: end
  41:  
  42:   end
  43: go
  44:  
  45: create table [TablePerClassHierarchyInheritance].[People]
  46: (
  47:   [Id] bigint not null identity,
  48:   [Department] bigint null,
  49:   [Discriminator] nvarchar(max) not null,
  50:   [FirstName] nvarchar(32) not null,
  51:   [Folder] int not null default 100,
  52:   [LastName] nvarchar(32) not null,
  53:   [Manager] bigint null,
  54:   constraint [PK_People] primary key clustered ([Id]),
  55:   constraint [FK_People_Department_TablePerClassHierarchyInheritance_Departments] foreign key ([Department]) references [TablePerClassHierarchyInheritance].[Departments] ([Id]),
  56:   constraint [FK_People_Manager_TablePerClassHierarchyInheritance_People] foreign key ([Manager]) references [TablePerClassHierarchyInheritance].[People] ([Id]),
  57:   constraint [Check_People] check (([TablePerClassHierarchyInheritance].[Check_People_Func]([Id], [Department], [Discriminator], [FirstName], [Folder], [LastName], [Manager])) = 1)
  58: );
  59: go
  60:  
  61: commit transaction;
  62: go

 

What I really appreciate about M when I look at the T-SQL listing above is the fact that I can work at a higher level of abstraction. To be frank, I haven’t written any substantive T-SQL in quite a few years. Part of this is due to my move from a Developer role to an Architect role and part of it is due to the advent of higher level tools that have obviated the need for me to write substantive T-SQL (e.g., NHibernate). Given my desire to be able to metamodel to a persistent SQL Server data store that will be consumed by an OO runtime, and my relative lack of T-SQL skill, I look at the T-SQL code in the listing above and get excited about the long-term possibilities of metamodeling in Oslo.

Cool stuff.

 

Table per Concrete Class

Let’s switch gears to another classic ORM pattern - “Table per Concrete Class”. Using this ORM pattern we will map the Person, Manager, and IndividualContributor classes to their own types. For fun, we’ll use a Employee type that acts as a mix-in. Since the Department type is exactly the same as above I’ll leave it out this time. Here’s the M code for Person:

   1: type Person
   2: {
   3:     Id: Integer64 => AutoNumber();
   4:     Folder: Integer32 => 100;
   5:     FirstName: Text#32;
   6:     LastName: Text#32;
   7:     Discriminator: Text where value in {"Person","Manager","IndividualContributor"};
   8: } where identity Id;

 

The M code in line 7 above is worthy of a brief explanation. From an ORM pattern perspective, the Discriminator field is, strictly speaking, optional. I modeled Person in this way to make querying against the Person class hierarchy in the Repository easier. As we’ll see later on, the use of the Discriminator field is used to determine the type of join that is needed in the Repository to query for a derived instance of the Person class hierarchy.

Next is the code for the Employee mix-in. Since both Manager and IndividualContributor inherit from Employee in the UML model, we’ll model Employee using M to simulate Employee inheriting from Person as an abstract class:

   1: type Employee
   2: {
   3:     Person: Person where value in People;
   4:     EmployeeId: Integer16;
   5:     Department: Department where value in Departments;
   6:     JobTitle: Text#32;
   7:     
   8: } where identity Person;

 

The interesting code in the M listing above is in line 8. Using this code we’re modeling that any M type that leverages the Employee mix-in will have that type’s identity defined in terms of an instance of the Person type. As we’ll see later, the Repository ramifications of this M code is that the SQL tables for M types that leverage the Employee mix-in will have primary keys (PKs) defined in terms of a foreign keys (FKs) to the People SQL table. Additionally, it is worthy to note that the M code above requires that every Employee be assigned to a Department.

OK, now that we have modeled the Employee abstract type inheriting from the Person concrete type (aka extent), we can take a look at some M code for the Manager and IndividualContributor concrete types (and the associated extents):

   1: type Manager : Employee
   2: {
   3:     Manager: Manager? where value in Managers;
   4: } where value.Manager.Person.Discriminator == "Manager";
   5:  
   6:  
   7: type IndividualContributor : Employee
   8: {
   9:     Manager: Manager where value in Managers;
  10: } where value.Manager.Person.Discriminator == "Manager";
  11:  
  12:  
  13: // Extent definitions
  14: Departments: Department*;
  15: People: Person*;
  16: Managers: Manager*;
  17: IndividualContributors: IndividualContributor*;

 

As the list above illustrates, I’ve defined some constraints in the M code above to specify that only Manager instances can be Managers (at the risk of constraining the obvious ;-). While these constraints don’t directly affect the generated Repository T-SQL, they are important as specification information for anyone reading the M code directly (e.g., a Developer building the OO runtime to consume a metamodel).

The M code above is straightforward. A Manager optionally has a Manager, while IndividualContributors must have a Manager.

The M code in the listings above combine to produce the following T-SQL:

   1: set xact_abort on;
   2: go
   3:  
   4: begin transaction;
   5: go
   6:  
   7: set ansi_nulls on;
   8: go
   9:  
  10: create schema [TablePerConcereteClassInheritance];
  11: go
  12:  
  13: create table [TablePerConcereteClassInheritance].[Departments]
  14: (
  15:   [Id] bigint not null identity,
  16:   [Folder] int not null default 100,
  17:   [Name] nvarchar(64) not null,
  18:   constraint [PK_Departments] primary key clustered ([Id])
  19: );
  20: go
  21:  
  22: create function [TablePerConcereteClassInheritance].[Check_People_Func]
  23: (
  24:   @_Id as bigint
  25: ,   @_Discriminator as nvarchar(max)
  26: ,   @_FirstName as nvarchar(32)
  27: ,   @_Folder as int
  28: ,   @_LastName as nvarchar(32)
  29: )
  30: returns bit  as
  31:   begin
  32:     return case
  33:   when @_Discriminator in (N'Person',
  34: N'Manager',
  35: N'IndividualContributor') then (1)
  36:   else (0)
  37: end
  38:  
  39:   end
  40: go
  41:  
  42: create table [TablePerConcereteClassInheritance].[People]
  43: (
  44:   [Id] bigint not null identity,
  45:   [Discriminator] nvarchar(max) not null,
  46:   [FirstName] nvarchar(32) not null,
  47:   [Folder] int not null default 100,
  48:   [LastName] nvarchar(32) not null,
  49:   constraint [PK_People] primary key clustered ([Id]),
  50:   constraint [Check_People] check (([TablePerConcereteClassInheritance].[Check_People_Func]([Id], [Discriminator], [FirstName], [Folder], [LastName])) = 1)
  51: );
  52: go
  53:  
  54: create table [TablePerConcereteClassInheritance].[Managers]
  55: (
  56:   [Person] bigint not null,
  57:   [Department] bigint not null,
  58:   [EmployeeId] smallint not null,
  59:   [JobTitle] nvarchar(32) not null,
  60:   [Manager] bigint null,
  61:   constraint [PK_Managers] primary key clustered ([Person]),
  62:   constraint [FK_Managers_Person_TablePerConcereteClassInheritance_People] foreign key ([Person]) references [TablePerConcereteClassInheritance].[People] ([Id]),
  63:   constraint [FK_Managers_Department_TablePerConcereteClassInheritance_Departments] foreign key ([Department]) references [TablePerConcereteClassInheritance].[Departments] ([Id]),
  64:   constraint [FK_Managers_Manager_TablePerConcereteClassInheritance_Managers] foreign key ([Manager]) references [TablePerConcereteClassInheritance].[Managers] ([Person])
  65: );
  66: go
  67:  
  68: create table [TablePerConcereteClassInheritance].[IndividualContributors]
  69: (
  70:   [Person] bigint not null,
  71:   [Department] bigint not null,
  72:   [EmployeeId] smallint not null,
  73:   [JobTitle] nvarchar(32) not null,
  74:   [Manager] bigint not null,
  75:   constraint [PK_IndividualContributors] primary key clustered ([Person]),
  76:   constraint [FK_IndividualContributors_Person_TablePerConcereteClassInheritance_People] foreign key ([Person]) references [TablePerConcereteClassInheritance].[People] ([Id]),
  77:   constraint [FK_IndividualContributors_Department_TablePerConcereteClassInheritance_Departments] foreign key ([Department]) references [TablePerConcereteClassInheritance].[Departments] ([Id]),
  78:   constraint [FK_IndividualContributors_Manager_TablePerConcereteClassInheritance_Managers] foreign key ([Manager]) references [TablePerConcereteClassInheritance].[Managers] ([Person])
  79: );
  80: go
  81:  
  82: commit transaction;
  83: go

 

The interesting T-SQL code in the listing above resides in lines 54-65 (Managers table) and lines 68-79 (IndividualContributors table). The T-SQL exhibits the following ORM characteristics:

  1. All of the data fields defined in the Employee abstract class have manifested in the table definitions for Managers and IndividualContributors.
  2. Both the Managers and IndividualContributors tables have their primary keys (PKs) defined as foreign keys (FKs) to the People table.

As mentioned above,this T-SQL allows an OO runtime to pull data for a particular instance of the class hierarchy (say Managers) by doing a join between the People and Managers tables.

 

Which Pattern is Best?

From a Repository and OO runtime perspective, all of the tradeoffs described in Scott Ambler’s ORM article apply to the patterns discussed in this post. Rather than try to outline them, I would strongly suggest that interested readers hit Scott’s site since his work is widely considered definitive on the subject.

Unfortunately, from an Oslo runtime perspective the answer to the question of which pattern is best is a bit hard to quantify. I say this mainly because I haven’t yet explored the potential impact of the above ORM patterns on Oslo’s support for M graphs.

This is a critical question from my perspective as M graphs have a lot of potential in terms of allowing a number of very interesting potential Oslo platform capabilities – not the least of which is a potentially standardized mechanism for allow model instance-to-model instance transformations.

As such, the current focus for my next post is on exploring M graphs in greater detail in the context of M models leveraging ORM design patterns.

Stay tuned!

Posted by dalanger | 5 Comments
Filed under: , , ,

Oslo Really is About Model-Driven Development

As I’ve wrote about previously, I’ve flipped the bit on Oslo and I’m currently very excited about the long term prospects for the technology. Like many have wrote about in the blogosphere, I was initially skeptical about Oslo. Seeing the demos for modeling in M types (formerly MSchema) and creating a SQL Server DB for model hydration/dehydration were interesting, but relatively old hat for DDD aficionados like myself (can anyone say NHibernate?). Even the demos around M languages (formerly MGrammar) weren’t necessarily compelling as I am quite familiar with ANTLR and it seemed that Microsoft was just getting into “the ANTLR business”, cool but nothing really to write home about.

Oddly enough, what changed my perception of Oslo were the writings of a thought leader in the UML community – Anneke Kleppe. Anneke has authored a ton of very interesting work about modeling, Model-Driven Architecture (MDA), and software languages. As I’ve mentioned previously on this blog, I’m very much an unrepentant fan of everything UML. From the MOF to OCL to QVT, I’m firmly convinced that the Microsoft development community could make tremendous gains in productivity and maturity if our community full embraced a lot of the advanced thinking embodied in these technologies (which is why I was so heartened to see The Big Show back working with the OMG).

In studying Anneke’s work I started to get very excited by the prospect that maybe the Oslo guys have reached a very similar conceptualization of the model-driven development (MDD)/DSL space as Anneke had through a separate, but parallel, track. Acting on this hunch, I started doing some research into the subject. While M languages is an interesting technology (I’ve since come to realize that it does have advantages over ANTLR in terms of DSL development), it wasn’t a differentiating factor in the research. The use of what Fowler calls External DSLs is a relatively well-know subject in DSL circles and the conceptual link between M languages and the potential of Oslo is relatively intuitive. What I focused on instead was what I think might be the second-most underappreciated aspect of Oslo (where System.Identity is the most underappreciated, IMHO) – M types.

Quite frankly, what I’ve found so far on M types in the blogosphere isn’t that helpful in trying to understand what the long-term potential of Oslo is as a MDD/DSL platform. At the risk of being offensive to the Microsoft development community, I think this may be more a reflection of the relative modeling immaturity of the community than a fundamental disagreement as to what the vision of Oslo (and M types in particular) is. In fact, we at Microsoft may be (at least partially) responsible for this lack of clarity. I offer as an example of this some text quoted directly from the Oslo site on MSDN:

 

“Oslo” modeling platform models remain relevant throughout the project lifecycle. At the highest level, an “Oslo” modeling platform model can be rendered as a graphical representation of a system design. At a lower level, model data includes the schema for system data. A model describes the data structure of a system. When you use the model to create a solution, “Oslo” modeling platform creates a model instance that includes the data that describes the specific solution. As a result, an “Oslo” modeling platform model serves an integral role in the implementation of a system, in addition to its design.

Deploying and managing a solution is much easier when you can model the entire solution, including how the implementations are deployed. A model enables you to conceptualize the solution, even though it may require multiple components on multiple computers. It is much easier to deploy and manage a complex solution that is modeled, rather trying to deploy and manage a collection of components that are built and deployed separately. For more information about deployment and application models, see System.Application.

The use of modeling extends to the runtime, as well; a model can be more than just a static visual representation of the system. A model-aware application – a database-driven application, in other words – can understand models at runtime and execute them if they have the capability. The model can be updated dynamically at each stage of the design, development, deployment, and execution of the solution. The model can ensure that there is no loss of data from one stage to another stage of the project lifecycle. In the “Oslo” modeling platform modeling tools, anyone (with the appropriate permissions) can review the business requirements, implementation, and production status of the application by examining model data. You can determine exactly what is happening with the solution at each stage of the project lifecycle, including production.

 

Whoa! Those of us that are UML aficionados (and especially the subset of those aficionados that are interested in the MOF) recognize this bit of text as having some very profound implications. In essence, the text above can be interpreted that Oslo is envisioned to be a platform for the creation of software-based solutions that rely on executable models (for those that are interested, Executable UML is a conceptually related body of work). Additionally, MOF-heads will recognize that the text above clearly focuses the scope of Oslo on the executable metamodels of software-based solutions.

When Oslo is understood in this light, an argument can be made that we at Microsoft haven’t necessarily done the best job in evangelizing the potential of Oslo. Most of our (meaning Microsoft’s) talks, articles, blog postings, and demos don’t really capture the executable metamodel aspects of Oslo very well. Hopefully this doesn’t come across as an indictment of the Oslo team, because I think the evangelization problem is very tough. What the MSDN excerpt above tells me is that Oslo is squarely aimed at providing very powerful architectural leverage at a high level of abstraction. It’s must be ridiculously hard, if not impossible, to create a compelling 1-hour Tech Ed preso to illustrate this idea.

In a humble effort to be part of the solution to this evangelization problem, I’m hoping that this post (and others I will likely write in the future) will be used as another resource in evangelizing the potential of Oslo  - with the end goal of generating some well-justified excitement in the community about the platform.

Along these lines I found a completely illuminating MSDN article on Oslo by Chris Sells that clearly echoes the ideas outlined in the MSDN excerpt above, but does so in more concrete terms. If you are interested at all in Oslo, I would highly, highly suggest reading the article. The article is so compelling because it clearly articulates (to my mind, anyway) something that you don’t see a lot on the Internet – M types (and Oslo) is really focused on providing a metamodeling solution (where metadata is just one type of metamodel). Chris also points out that the use of executable metadata actually has a long history at Microsoft (I offer IDL with COM as an example of this from my own past ;-), so Oslo can be seen as Microsoft just taking these ideas to the next level.

The examples that Chris cites are excellent – especially since they show Microsoft’s acceleration towards, in recent years, executable metamodels. However, at the risk of arrogant presumption (Chris is a far smarter guy than I am) I would argue that there exists another example of Microsoft technology that not only relies on executable metadata models, but better typifies Oslo’s potential long term affect on software development – Microsoft Dynamics CRM (MS CRM).

The MS CRM architecture is built upon executable metadata. Specifically, the MS CRM architecture makes use of a dedicated metadata database in SQL Server that is completely separate from the OLTP database that stores MS CRM’s transactional data. Almost every aspect of MS CRM’s execution is affected in one way or in another by the metadata stored within MS CRM’s metamodel. The centricity of executable metadata within MS CRM has a number of profound architectural benefits:

  • MS CRM provides robust data modeling capabilities that allow for powerful custom extensions to the MS CRM OLTP database
  • MS CRM provides robust UI generation capabilities for custom entities
  • MS CRM provides capabilities for customizing the out of the box data entities, including renaming attributes and adding new attributes
  • MS CRM provides capabilities for customizing the MS CRM UI
  • MS CRM provides dynamic generation of  a web service API, with dynamic WSDL, from metadata – including the addition of custom data entities to the web service API
  • MS CRM provides Workflow capabilities to custom data entities added to the system
  • The list goes on

The kind of power and flexibility enumerated above has traditionally been the purview of vendor-provided application platforms (for an interesting take on this power and flexibility, see this whitepaper). From my perspective, I would argue that the real promise for Oslo as a platform (assuming my interpretation of the MSDN excerpt above is correct), is that Oslo will operate as a “solution accelerator” effectively democratizing the ability for development teams of all stripes to enjoy the architectural leverage traditionally embodied in application platforms like MS CRM.

In line with this view, I plan to write a number of blog posts over the next couple of months focusing on some of the potential of Oslo from the perspective of executable metamodels. This actually has interesting ramifications not only for software architectures, but also for the creation and usage of DSLs as well.

I figure that’s enough pontification for one day, so I’ll mention that any thoughts (or corrections) on what I’ve talked about here would be greatly appreciated.

 

Post Script [added after initial writing]

So I thought I was on to something pretty profound with this post – hopefully the bit about MS CRM has some value add :-).

However, I found that I’m a Johnny-come-lately to the ideas of Oslo, metamodeling, and MOF linkages. Check out these excellent posts:

http://geekswithblogs.net/cyoung/archive/2009/01/05/128369.aspx

http://geekswithblogs.net/cyoung/archive/2009/04/13/130921.aspx

Posted by dalanger | 7 Comments
Filed under: , , ,

Oslo May CTP Has Improved System.Identity!

The Oslo team released the May 2009 CTP yesterday. For those that are interested in Oslo in general, and System.Identity in particular, then effort to get the new CTP up and running is well worth it. From the perspective of System.Identity, the new Oslo CTP represents an important leap forward in terms of design and capability. Because of this new System.Identity goodness I will be moving to the Oslo May 2009 CTP for future posts on System.Identity.

The good news is that previous blog postings on System.Identity are not invalidated by the latest rev of the System.Identity schema – the underlying principles of System.Identity’s Party Model implementation still hold true. However, there are a few noteworthy changes in the new System.Identity schema that do affect some of our previous understandings of System.Identity. The up side of this is, since we’ve only looked at a subset of the extents in the previous System.Identity schema, we don’t need to spend a lot of effort getting up to speed on the new schema.

In this post I will outline these changes so that folks who have been tracking my explorations of System.Identity can map the new schema to the previous version. I also have added a new UML model to my SkyDrive so that folks can look at the new System.Identity schema in it’s entirety. The link to the .ZIP is located at the bottom of this post.

 

Relevant Changes in the New System.Identity Schema

One of the most obvious changes (and improvements, IMHO) to System.Identity is the renaming of the TaxonomyEntry extent to the more intuitive Kinds extent. Correspondingly, the TaxonomyRelationship extent has been renamed KindRelationship. As can be seen in the UML below, the structures of these extents is essentially the same – which arguably represents the overall equality of Kind to TaxonomyEntry:

Kind

The next obvious change is the renaming of the PartyToPartyType extent to be the PartyToPartyRelationship extent. In addition to the name change, the new PartyToPartyRelationship extent has additional functionality embodied as new relationships to the IdentityKey extent (which I have not blogged about, but is actually very intuitive). These relationship provide the option of allowing a PartyToPartyRelationship instance to specify the particular Identity mechanism used for each Party that participates in the relationship. The following UML diagram illustrates the new and improved PartyToPartyRelationship extent:

PartyToPartyRelationship

For the purposes of the previous posts, that’s about it!

 

Notable Additions to the New System.Identity Schema Version

As I mentioned in Part 3 of the System.Identity series, a very powerful capability of a Party Model implementation like System.Identity is the ability to support complex relationships that may have access control implications. Part 4 of the System.Identity series will address this exact topic. Lucky for us that the new System.Identity schema adds some extents critical for supporting these scenarios.

The UML diagram below illustrates some of the most important additions to System.Identity that I will be covering in Part 4:

Resource

As can be seen, the latest rev of System.Identity adds the concept of Resource and Policy, and how Parties relate to Resources and Policies, to the schema.

Very exciting, and powerful, stuff.

Stay tuned!

 

SkyDrive Files

 

Implementing UML Associations and Oslo’s System.Identity

As I really don’t have much of a life I was reading an academic paper this evening by Anneke Kleppe. In the References section of the paper there were the a couple of links to some articles on properly implementing UML Associations in source code. The articles are fairly old now (they were written in 2005), but are interesting because they really do illustrate how much functionality is actually implied by very simple UML constructs (back in the day one of my favorite Dev questions for folks who put UML on their resumes was “What are some of the implementation implications of the Composition relationship in terms of the .NET GC?'”, but that’s a story for another day). For today I’ll narrowly resist the temptation to expound upon the tremendous goodness that is UML (even if you never use it, studying makes you such a better Dev and Architect – really it does!), and just provides the links to the articles:

 

Wed Yourself to UML with the Power of Associations – Part 1

Wed Yourself to UML with the Power of Associations – Part 2

 

What struck me as I was reading these articles this evening is that Oslo’s System.Identity can handle all of the scenarios that the articles talk about. Obviously System.Identity (and the Party Model more generally) are layering a level of abstraction on top of what is talked about in the articles, but it just makes feel all warm on the inside to know that the System.Identity (and hence the Party Model) has yet another practical application.

On a side note, reading the articles above has given me a little hankering to actually write some code (God forbid!) putting System.Identity through its paces.

Stay tuned for the insanity…

Posted by dalanger | 1 Comments

Exploring the Party Model with Oslo’s System.Identity – Part 3

In Part 1 of this series we covered the basics of how Oslo’s System.Identity implements the Party Model and how System.Identity can be used to model real world scenarios. We continued our exploration of System.Identity in Part 2 by modeling more complex real world scenarios and illustrating how System.Identity can handle asymmetric relationships and transient nature of real world relationships over time.

In this post we’re going to explore one of the most powerful features of the Party Model – the ability to flexibly model hierarchical structures.

The Scenario

For the purposes of this post we will be using the following real world scenario:

  1. Dave works on the Enterprise Architecture team within Microsoft IT’s Technology Office

Analyzing the Scenario

As we’ve seen in previous posts, System.Identity can support a limitless number of relationship types between Parties. This power allows for fine-grained modeling which is particularly useful for supporting relationships that have some sort of associated semantics. As an example, we saw how System.Identity could support the scenario of “Dave is married to Brenda” at three levels of semantics:

  1. There exists a PartyToPartyType relationship of type ‘Marriage’ between Dave and Brenda
  2. Dave plays the Role of ‘Husband’ vis-a-vis Brenda
  3. Brenda play the Role of ‘Wife’ vis-a-vis Dave

In looking at items #1-3 an argument could be made that item #1 represents the overall structural context of the relationship. This is easy to see when one realizes that items #2 and #3 could be taken away and there is still a lot of meaning that can be derived from the fact that there is a ‘Marriage’ relationship between Dave and Brenda.

The idea that some relationships provide structural context is a core concept within the Party Model. It allows the Party Model to handle a wide range of scenarios beyond just interpersonal relationships – especially for Parties that are not individuals.

As we saw in the first post, organizations are also Parties within the Party Model. This intuitively makes sense as organizations (e.g.,corporations) are entities that can enter into contracts and can also be sued.

Using these ideas, we can leverage the System.Identity schema to model the hierarchical structure of organizations, in this case a portion of Microsoft:

Scenario1

As is illustrated above, we’ve modeled the latter portion of our “Dave works on the Enterprise Architecture team within Microsoft IT’s Technology Office” scenario. Specifically, we’ve again leveraged System.Identity’s PartyToPartyType to represent a structural relationship between Parties – namely a ‘Parent Organization’ structural relationship.

It is important to note in the diagram above that the ‘MSIT Technology Office’ is required to be the ContextParty for the ‘Parent Organization’ relationship to allow the hierarchical structure to make sense conceptually. The party of ‘Microsoft IT’ is a ‘Parent Organization’ in the context of the ‘MSIT Technology Office’ Party – the reverse doesn’t make sense. However, it is also worthy of note that the following hierarchical structure is functionally equivalent to the structure above:

Scenario2

The point of illustrating these two diagrams is to underscore an important point of modeling hierarchies using the Party Model – hierarchical structures are inferred at runtime from the semantics of the relationships in question. Therefore, care has to be taken to ensure the semantic integrity of the hierarchical structures within the Party Model data store (documented standards may be of help here to help ensure consistency).

Using these concepts we can now instantiate MSIT’s Enterprise Architecture team and also instantiate Dave’s employment on the EA team:

Scenario3

Viola! A multi-level hierarchy within the Party Model!

 

Bonus Scenario

As cool as being able to model hierarchies (and everything else) is, the Party Model has yet another piece of goodness that it can provide us. The Party Model’s clean separation of Parties and relationships allows for an interesting capability – the simultaneous modeling of multiple hierarchies across a set of Parties.

Arguably this is a less intuitive application of the Party Model, but it can be a quite handy feature. In essence, the modeling of multiple hierarchies allows for various semantic views into a set of Parties. For example, let’s look at the scenario of “All expenses are billed to, and paid by, Microsoft IT”. We can model this additional hierarchy (let’s call it the ‘billing hierarchy’) using System.Identity in the following manner:

BonusScenario

As the above diagram illustrates, the Party Model supports the concept of layering one hierarchy on top of another. In this specific case we’ve layered the ‘billing hierarchy’ for MSIT on top of the ‘organizational hierarchy’. As we’ve seen previously, any number of hierarchies can be layered on to a set of Parties by just repeating this pattern. As one can imagine, a software architecture based on the Party Model has a lot of power and flexibility.

 

Next Time

I’m going to take a small break for the next post in the series, but when I resume the subject of the post will be the application of the Party Model in terms of modeling access controls.

Stay tuned!

 

SkyDrive Files

More Posts Next page »
 
Page view tracker