Click here to Skip to main content
15,891,136 members
Articles / Programming Languages / Visual Basic
Article

Refactoring to Adaptive Object Modeling: Entity Relationships and Accountability

Rate me:
Please Sign up or sign in to vote.
3.75/5 (7 votes)
20 Jun 200516 min read 82.9K   242   44   5
This article will deal with Entity Relationships as they relate to the Adaptive Object Model pattern. We will discuss and use for this example Martin Fowler's Accountability pattern, which gives us relationship formation, cardinality between classes, and is the basis for workflow in the AOM pattern.

UML for article

Introduction

Adaptive Object Modeling is a relatively unrealized concept in object oriented design that has found some roots in advanced development processes. It allows that applications are in continual flux (or their requirements are) from adjustments to business rules, environments and user requirements. Its precepts are that using metadata for business objects, rules and process flows, instead of hard coded, static method code, makes the application more flexible to user/client needs. The AOM design model also requires that certain domain 'facts' are maintained, i.e. that there are controlled interpretations of the effects of the 'immediate' changes from user-generated metadata.

Adaptive solutions offer us a way to make applications more configurable (regarding workflow) to the end users. It is not a 99% solution and, to my knowledge there is no end-to-end solution that meets all needs, simply because those needs are more directly defined by the business requirements. However, since business requirements change frequently, writing immutable code flow logic leaves very short lives for code. Even the online industry is feeling the need to configure dynamically: if you are a subscriber to most web portals like Yahoo! or MSN you have a user configurable home page where you can decide which items of interest you would like to display on your page.

Most portal technologies are indirectly pointing us to a more adaptive model, simply because they are configurable by end-users or power-users. I see adaptive technologies like Adaptive Object Modeling in the same light as a web portal: some functionality is needed to be coded by developers, like database and business logic, but where and when this logic is implemented should be (following business trends) decided upon by business experts, not developers. Some adaptive models incorporate the non-meta-data into tier models tightly coupled with tier meta-data, which is one way to do it, but I prefer to let the EUD (end user developer) have the hand in how business data is handled, and simply allow the AOM framework to give the actual implementation of when and where back to business experts (which most developers don't have the bandwidth to be).

To better understand and practice the techniques of AOM design, I am writing this and several other articles which explain the usage and conversion (or refactoring effort) from a static code model to AOM design.

This article will deals with Entity Relationships as they relate to the Adaptive Object Model pattern. We will discuss and use for this example Martin Fowler's Accountability pattern, which gives us relationship formation, cardinality between classes, and is the basis for workflow in the AOM pattern.

Who this article is for

This article is written primarily for architects and business IT development managers, as well as developers who have some advanced reflection and design experience, and anyone familiar with AOM or other like pattern methodologies, who while interested in these patterns, have not seen practical ideas to the patterns' usage. This series of articles will be the starting point for a AOM framework that I will be releasing later this year.

Background

Why are relationships important in the Adaptive Object Model pattern? Relationships or accountabilities give the pattern its ability to define workflow through class, type and attribute relationships by interpreting meta-data set up by power users. When dealing with interpreter patterns the main advantage is the ad-hoc creation and modification of program workflows. This differs greatly from traditional application workflow methods, which are hard compiled and static with respect to the user. Traditional application workflows are set up by the developer of the application at compile time and offer little in flexibility in regards to the logical flow of the application. Relationships in business operations often change, sometimes daily, and any system that cannot react to user needs immediately usually has a shorter life cycle, or confines and limits the business units using the software. Relationships in the AOM model by using the Accountability pattern are far more flexible in comparison, allowing business experts or power users to redefine the application flow from moment to moment.

To understand how AOM makes use of relationships, we first need to study Martin Fowlers Accountability pattern, which gives us a nice relationship methodology for this type of workflow. The Accountability pattern is a way to define relationships between classes, define rules that govern those relationships, and provide a language interpreted way to define class patterns and relationships. Accountability uses a class and type structure, using type classes to super define implementation classes. It works much the same way language works in describing relationships.

Here we see the UML for the basic Accountability pattern, based on the Fowler model:

Image 2

Let's say that we have a job type of 'President'. This job type is allowed to hire 'Executive' job type personnel, which in turn is allowed to hire 'Manager' job type personnel, and so on. So a typical relationship would look like:

President {who} 'hires' VicePresident {who} 'hires' 
              SalesManager {who} 'hires' SalesAssociate.

The relationships or accountabilities are between President and VicePresident, VicePresident and SalesManager and SalesManager and SalesAssociate. So the workflow to get an entire department hired would be defined by the 'hires' keyword, which in itself stands for an accountability type. The actual accountability relationship is the whole noun-verb-subject relationship, such as: President {who} 'hires' VicePresident. The accountability type 'hires' tells us what type of action we wish to perform and is the verb of the statement. The entity who is commissioner of the action, the 'President' is the actor and is the noun, and the entity who is responsible to the actor, the 'VicePresident' is the subject. So we are using common language elements, an entire relationship schema, and thus a workflow of responsibilities between units.

Cardinality is maintained in these accountability relationships. The tree moves both up and down, that is, a parent knows all its children and a child knows all of its parents. We have the associations decoupled from the actual entities, so that many different relationships can be defined, as opposed to a single immutable parent child relationship, like we might obtain if we held collections of parent or child entities within our current entity object. This gives us a greater number of options to define several different types of relationships.

For instance, let's say we have defined in our application a definition for what kind of positions can hire which other types of positions, but now we need to know which positions reports to which other positions. Depending on the organizational changes in the business, different positions might report at different times to different other positions. If we had single parent child relationships on the entity, we could not change easily the type of relationships, or the accountability type. Let's say instead of using the accountability type 'hires' we wanted to define relationships of 'reportsTo'. That is, SalesAssociate reports to SalesManager, SalesManager reports to VicePresident, and so forth. So this relationship would look like:

SalesAssociate {who} 'ReportsTo' SalesManager, SalesManager {who} 'ReportsTo' 
           VicePresident, VicePresident {who} 'ReportsTo' President

These two relationship chains {'hires' and 'reportsTo'} can live independently and are only dependant on the EntityTypes and rules which govern their particular type. So each AttributeType can define a different workflow within the application.

Defining another group of relationships based on their type is much easier than trying to figure out relationships in any other way, hence the need for an AccountabilityType is easily evident.

Defining the WorkFlow through Meta-Data: Knowledge and Operation

I have divided up the code based on its basic logical functionality, defining two types of classes, types and operational or implementation classes. Type definition classes, such as EntityType, AttributeType, AccountabilityType and ConnectionRule, I grouped using the word knowledge, since they are the part of the framework that defines and holds the basic rules and knowledge of the workflow process. Implementation classes like Entity, Attribute and Accountability, are grouped using the word operational, since they are the actual classes involved in functional work. The operational section of code should not be confused with the OperationalStrategies code, which is where the strategy piece of the framework exists. Strategy discussion is out of scope for this article, and is covered elsewhere.

Let's look at how we begin to set up our relationship data. I always start with the actual meta-data schema before I create any code when working with abstract models like this, simply because it helps me to better think about and see the class relationships. So let's start by looking at the meta-data file KnowledgeConfiguration.config. Notice that the name includes knowledge, indicating that this meta-data defines the knowledge piece of the AOM framework.

Here we see the XML meta-data for the AttributeTypes. It is simply telling us the key name to identify this type, what actual object type it represents, and any event or validation it may require (which is not in scope for this article). This type specification is basically a rule, which will be used to define system allowed types of data which may be used in the application.

XML
 <attributeTypes>
    <attributeType name="EmployeeIdType"
        attributeDeclaritiveType="System.Int32"
        attributeEventType="OnSelect" />
    <attributeType name="FullNameType"
        attributeDeclaritiveType="System.String"
        attributeEventType="OnChange" />
    <attributeType name="IsActiveType"
        attributeDeclaritiveType="System.Boolean"
        attributeEventType="OnChange" />
    <attributeType name="StartDateType"
        attributeDeclaritiveType="System.DateTime"
        attributeEventType="" />
    <attributeType name="IsAdminType"
        attributeDeclaritiveType="System.Boolean"
        attributeEventType="OnSelect" />
</attributeTypes>

Next, we take a look at the meta-data XML for the EntityTypes. EntityTypes are discussed in an earlier article and act as class definitions or abstract classes, serving as a contract for the actual classes or entities. We need this class to determine how different types of entities react and are involved in relationships. They determine what attributes and strategies can be added to the Entity classes and help to define the entity relationships in the accountabilities. In effect, they serve as a rules base for limiting and defining the implementation classes.

XML
<entityTypes>
  <!--Executive Entity Types //-->
  <entityType name="TopLevelExecutiveType" 
    parentEntityType=""
    allowedAttributeTypes=
     "EmployeeIdType,FullNameType,IsActiveType,StartDateType,IsAdminType"/>

  <entityType name="ExecutiveType" 
    parentEntityType=""
    allowedAttributeTypes=
     "EmployeeIdType,FullNameType,IsActiveType,StartDateType"/>

  <!--Employee Entity Types //-->
  <entityType name="TrustedEmployeeType" 
    parentEntityType="EmployeeType"
    allowedAttributeTypes=
     "EmployeeIdType,FullNameType,IsActiveType,StartDateType,IsAdminType"/>

  <entityType name="EmployeeType" 
    parentEntityType=""
    allowedAttributeTypes=
     "EmployeeIdType,FullNameType,IsActiveType,StartDateType"/>

</entityTypes>

Next, we take a look at the meta-data XML for the ConnectionRules. ConnectionRules are a way of defining which types of Entity classes can exist in a particular type of relationship. ConnectionRules are directly defined in the AccountabilityType, which as you read earlier, defines types of relationships. ConnectionRules simply tells us which type of actor can be defined in a particular type of relationship. Notice that the connectionRule XML node contains two attributes besides the key name attribute. allowedCommissioner states which EntityType parent can be defined in a relationship if this rule is implemented, and allowedResponsible indicates which EntityType child can be defined.

XML
<connectionRules>
    <connectionRule name="TopLevelExecutiveSubordinates"
        allowedCommissioner="TopLevelExecutiveType"
        allowedResponsible="ExecutiveType" />
    <connectionRule name="ExecutiveImmediateSubordinates"
        allowedCommissioner="ExecutiveType"
        allowedResponsible="ExecutiveType" />
    <connectionRule name="ExecutiveTrustedSubordinates"
        allowedCommissioner="ExecutiveType"
        allowedResponsible="TrustedEmployeeType" />
    <connectionRule name="ExecutiveSubordinates"
        allowedCommissioner="ExecutiveType"
        allowedResponsible="EmployeeType" />
    <connectionRule name="ManagerTrustedSubordinates"
        allowedCommissioner="ExecutiveType"
        allowedResponsible="TrustedEmployeeType" />
    <connectionRule name="ManagerSubordinates"
        allowedCommissioner="ExecutiveType"
        allowedResponsible="EmployeeType" />
</connectionRules>

Finally, we see the XML meta-data that defines the actual types of accountabilities, such as 'hire' or 'reportsTo'. We use specialized names that further describe the action for this example, to reduce confusion. The name of any relationship should be only as descriptive as is needed, not less or more. Remember, as with all coded or relational data, it is important what a thing is named, for clarity and ease of understanding. Notice that accountabilityType has only two attributes, the key name, and a comma delimited list of connection rule names, that help define which type of rules we want to enforce for this relationship type.

XML
<accountabilityTypes>
    <accountabilityType name="TopLevelExecutiveHiresExecutive"
        rules="TopLevelExecutiveSubordinates" />
    <accountabilityType name="ExecutiveHiresManager"
        rules="TopLevelExecutiveSubordinates,ExecutiveImmediateSubordinates" />
    <accountabilityType name="ExecutiveHiresEmployee"
        rules="ExecutiveTrustedSubordinates,ExecutiveSubordinates" />
    <accountabilityType name="ManagerHiresEmployee"
        rules="ManagerTrustedSubordinates,ManagerSubordinates" />
</accountabilityTypes>

Now that we have looked at the knowledge portion of our meta-data, we can begin to discuss how these rules and types define the class relationships.

So now we will look at the meta-data source file OperationalConfiguration.config. This is the meta-data for the actual program flow of the application, i.e. class, attribute and relationship data. First, let's look at the attributes section. Here we see the attribute XML node has the ubiquitous key name, the attributeType from the knowledge section which defines the data type, and another XML attribute attributeEvent, which shows a particular type of operation strategy call to associate with the attribute. Usage of this element is beyond the scope of this article, and is included simply for the example.

XML
<attributes>
    <attribute name="EmployeeId"
        attributeType="EmployeeIdType"
        attributeEvent="GetEmployee({0})" />
</attributes>

Next we see the the entity section of the XML meta-data. This is where the actual functional class types are set up. Notice we have the EntityType key name from the knowledge section and a comma delimited list of attribute key names. This tells us what type of class this is, what attributes are to be associated (confined by the EntityType allowed AttributeTypes), and based on EntityType will tell us what types of entities we can be included in different types of relationships.

Why do we want to define the types of classes we would like to put into the relationship? Well, an Entity for internal financial data would not be used for a relationship between outside vendors. So the EntityType could prevent an Entity with certain proprietary functionality from being included in a part of the application for outside vendors, who have no business with the financial data of their client. The EntityType defines allowed pieces of functionality for different operations inside an application.

XML
<entities>
    <entity name="President"
        entityType="TopLevelExecutiveType"
        actualAttributes="EmployeeId"
        />
    <entity name="VicePresident"
        entityType="ExecutiveType"
        actualAttributes="EmployeeId"
        />
    <entity name="SalesManager"
        entityType="ExecutiveType"
        actualAttributes="EmployeeId"
        />
    <entity name="CustomerServiceManager"
        entityType="ExecutiveType"
        actualAttributes="EmployeeId"
        />
    <entity name="SalesAssociate"
        entityType="EmployeeType"
        actualAttributes="EmployeeId"
        />
    <entity name="CustomerServiceAssociate"
        entityType="TrustedEmployeeType"
        actualAttributes="EmployeeId"
        />
</entities>

OK, so now we can look at the XML meta-data for the Accountability section. Here we notice that we have three main elements (besides the key name), accountabilityType, actualParent and actualChildren. accountabilityType is the key name for the knowledge element AccountabilityType, and tells us what action or verb we are using for this workflow. The actualParent and actualChildren define what entities we actually want to associate, constrained by the ConnectionRules allowing their particular EntityType access to this association.

So for this example, we can assume:

  • President {who} 'PresidentHiresVicePresident' VicePresident.
  • VicePresident {who} 'VicePresidentHiresManager' SalesManager or CustomerServiceManager.
  • SalesManager or CustomerServiceManager {who} 'ManagerHiresEmployee' SalesAssociate or CustomerServiceAssociate.
XML
<accountibilities>
    <!-- Hiring //-->
    <accountability name="PresidentHiresVicePresident"
        accountabilityType="TopLevelExecutiveHiresExecutive"
        actualParent="President"
        actualChildren="VicePresident" />
    <accountability name="VicePresidentHiresSalesManager"
        accountabilityType="ExecutiveHiresManager"
        actualParent="VicePresident"
        actualChildren="SalesManager" />
    <accountability name="VicePresidentHiresCustomerServiceManager"
        accountabilityType="ExecutiveHiresManager"
        actualParent="VicePresident"
        actualChildren="CustomerServiceManager" />
    <accountability name="VicePresidentHiresSalesAssociate"
        accountabilityType="ExecutiveHiresEmployee"
        actualParent="VicePresident"
        actualChildren="SalesAssociate" />
    <accountability name="SalesManagerHiresSalesAssociate"
        accountabilityType="ManagerHiresEmployee"
        actualParent="SalesManager"
        actualChildren="SalesAssociate" />
    <accountability name=
          "CustomerServiceManagerHiresCustomerServiceAssociate"
        accountabilityType="ManagerHiresEmployee"
        actualParent="CustomerServiceManager"
        actualChildren="CustomerServiceAssociate" />

Note: For this example, we have added another set of accountability types to illustrate that we can have multiple program flows based on type. We can assume that:

  • VicePresident {who} 'VicePresidentReportsToPresident' President.
  • SalesManager {who} 'SalesManagerReportsToVicePresident' VicePresident.
  • CustomerServiceManager {who} 'ManagerReportsToExecutive' VicePresident.

And so forth....

XML
<!-- Organizational Structure //-->
    <accountability name="VicePresidentReportsToPresident"
        accountabilityType="ExecutiveReportsToTopLevelExecutive"
        actualParent="President"
        actualChildren="VicePresident" />
    <accountability name="SalesManagerReportsToVicePresident"
        accountabilityType="ManagerReportsToExecutive"
        actualParent="VicePresident"
        actualChildren="SalesManager" />
    <accountability name="CustomerServiceManagerReportsToVicePresident"
        accountabilityType="ManagerReportsToExecutive"
        actualParent="VicePresident"
        actualChildren="CustomerServiceManager" />
    <accountability name="SalesAssociateReportsToVicePresident"
        accountabilityType="EmployeeReportsToExecutive"
        actualParent="VicePresident"
        actualChildren="SalesAssociate" />
    <accountability name="SalesAssociateReportsToSalesManager"
        accountabilityType="EmployeeReportsToManager"
        actualParent="SalesManager"
        actualChildren="SalesAssociate" />
    <accountability name=
            "CustomerServiceAssociateReportsToCustomerServiceManager"
        accountabilityType="EmployeeReportsToManager"
        actualParent="CustomerServiceManager"
        actualChildren="CustomerServiceAssociate" />
</accountibilities>

Examining Logical Program Flow through AOM Workflows

Now that we have an understanding of the basic schema of the meta-data, we can discuss how relationships are useful in defining program flow in your application. For this example I have created a WinForm application client, which is a good example of how a very basic usage of this model might be implemented. With this example, I have created dynamic menu items which display the operational class' entities, which in turn display links to their relationship entities. The details of each entity is displayed on the form, much as you might display data in a regular application. We leave out how the strategies are implemented (which is covered in another article) and how attribute and application events are handled. This is, of course, only a crude example of relationships in the AOM pattern, but we will see with this example how application workflows can be extracted from the traditional static model to the flexible AOM one.

First, we take a look at the intro screen and see all our entities listed here by name. I do this to give us an idea of where we want to start, but in an actual application, menu items could be handled by AccountabilityType, just like any other section of program flow.

Image 3

Next, let's select the VicePresident entity. We see the entity form, which has the attributes for the entity listed, and the name. Also we notice that the menus have changed, we see three new menu items: Hiring, Manager and Subordinates. The Hiring menu list displays the first workflow from our meta-data of who the vice president can hire. The Manager and Subordinates menu list displays the second list of the relationships of who he reports to. Manager represents the parent relationships or commissioner accountabilities for that relationship. Remember, earlier when we were setting up the AccountabilityTypes of 'reportsTo'? Here we have defined a totally different logical workflow in the application. You could build role based security around each accountability type, so only certain people could see certain aspects of the application. Subordinates works the same way manager does, in that it uses a 'ReportsTo' accountability type, except it uses the child relationships or responsible accountabilities.

Image 4

After Word

Now we can easily see how you can use relationships in AOM in an actual application. We have extracted and examined two basic program workflows, and seen them mirrored in the client interface, with minimal 'hard coding' or static logical code. We defined all our logical rules, process flows as relationships and class definitions in our meta-data, which was rendered to our actual process flow via our interpreter.

What we have not shown is the obvious underlying principle that even though our example was a client workflow, underlying workflows surrounding almost any process can be created. Say we wanted an approval system that sent out requests for approval of an action item to different people in an organization. Based on a person's position, the approval chain would be created, and requests and approvals would flow between valid approvers. What if we needed to change which positions reported to which other ones, without changing the actual program code? We have seen that this is certainly a viable scenario for AOM. As with most flexible tools, it is as useful as the vision of those using it.

Another aspect of project development we leave out here is how actual business related data that exists outside our meta-data is manipulated. This of course is easily plugged into the model, and how tightly coupled your meta-data and your business data becomes really is up to you, although I would lean toward keeping the two separated, even if they live in the same database or repository. Remember the strategies? Here is where these come to play, as well as attribute events and other system related algorithms.

Of course, I have only described one way to view the AOM pattern, in relation to dealing with events and strategies. There is another way that we may discuss later that uses the strategies and events from the attributes, that form business rules and logic. But this will have to be for another time.

Points of Interest

This is the sixth installment in the series I am writing on real world adaptive object modeling. All examples and the bulk of this article are taken from my professional experience as an architect. The examples given are templates only, and the designer must keep in mind that they are the ones who must decide where different patterns, if any, may be best used in their code.

Deciding to perform a refactoring effort from existing code to a pattern or enhanced design model must be weighed on the necessity and need of the code itself. Patterns and Adaptive Models are only design templates, helpers to accommodate better overall design. I might stress that making the effort to use advanced design methodologies will strengthen your overall design ability, but like your basic coding skills, it is something to be learned and cultivated.

Related Articles

Other articles in this series include:

  1. TypeObject
  2. Properties
  3. Strategies
  4. Entity-Relationships and Accountability/Cardinality.
  5. Ghost Loading, Data Mapping and more...
  6. Interpreter methodologies (coming soon)
  7. Discussions on Practical Project usefulness of design.
  8. Discussions on the AOM framework, UI, and advanced concepts.

History

This is the first revision and is the sixth installment in a series.

Credits

Thanks to:

  • Joe Yoder and Ralph Johnson for their various articles on the AOM pattern.
  • Martin Fowler for his interest in my articles and his work on the Accountability pattern.
  • Doga Oztuzun, for his insight and sharing of his relevant project data.
  • Also to anyone else I have forgotten.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Christopher G. Lasater

I am also a published author, please check out my book:
ISBN: 1-59822-031-4
Title: Design Patterns
Author:Christopher G. Lasater
More from my web site
Amazon.com


Comments and Discussions

 
QuestionPattern of a pattern? Pin
boo25-Nov-05 12:34
boo25-Nov-05 12:34 
AnswerRe: Pattern of a pattern? Pin
Christopher G. Lasater28-Nov-05 5:57
Christopher G. Lasater28-Nov-05 5:57 
Only questions unasked are stupid. I am glad you are thinking about patterns with this pattern. And yes you sure could do this.

Chris Lasater
http://www.geocities.com/lasaterconsult
Generalcongratulations Pin
erdsah8812-Jun-05 7:30
erdsah8812-Jun-05 7:30 
GeneralRe: congratulations Pin
Christopher G. Lasater13-Jun-05 4:20
Christopher G. Lasater13-Jun-05 4:20 
GeneralRe: congratulations Pin
erdsah8813-Jun-05 7:51
erdsah8813-Jun-05 7:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.