in

CodeSmith Community

Your Code. Your Way. Faster!

DOC: I've got NetTiers Generated, now where do I go? Part II

Last post 05-07-2008 6:39 AM by alexlea. 5 replies.
Page 1 of 1 (6 items)
Sort Posts: Previous Next
  • 11-11-2005 7:58 PM

    DOC: I've got NetTiers Generated, now where do I go? Part II

    I thought this deserved another post, since it deals with detailed problem domain.  I wrote this post so that i could appeal to a large audience. Well hopefully. tongue
    This is a followup from the post found here: Part I - http://forum.codesmithtools.com/default.aspx?f=19&m=8499
    jcteague said...
    What is the best approach for dealing with inheritance in your problem domain? For instance, my company does a lot of insurance work. There are many types of insurance policies, Whole Life vs Term Life. When creating a quote, there is some level of shared work and also quite a bit of polymorphism. In this scenario, the Manager pattern has been a little limiting. How would you incorporate an inheritance structure with NetTiers.

    I think that is is part of using the component model as well as a database design that elegantly handles inheritance and use of Views to represent them.

    I really like the extending with partial classes use case. That will make some very interesting implementations.
     
    ok, here it goes...  shocked
     

    Let’s take a look at the following problem domains insurance and loan underwriting, more specifically, contracts.  There are many industries that can drive a developer nuts.  One of them is of course insurance, and the other is loan underwriting, especially mortgage loans.  They change so often, and always create new products, with a new set terms and conditions, and you learn quickly to be very weary of your architecture because it can change at any moment. 

     

    I remember reading an article in the Wall Street Journal about insurance and how the industry has the ability to change the entire financial stability of the Global Market.  In the 1970’s, FTC issued findings in Whole Life Insurance, and said that the product was not beneficial paid a measly 1.5% in interest.  As a result, the industry decided they needed to revamp its entire product line. So they said, the heck with whole life, we need a new product, let’s create Universal life insurance, and solve all our problems, and the interest earned would now be closer to 15%.  Their revenue streams now positive and the sale of the most beneficial job (insurance sales) in the late 70’s and 80’s created a massive shift of money.  Trillions of dollars were transferred throughout the end of the century, in the largest money transfer of any kind in the history of the world.    

     

    My point is, the products the insurance industry offers varies often, and can have a significant impact on the financial market in a hurry.  This can lead to the suits scrambling to have departments create a new product in a hurry.  This brings us full circle to you, the poor developer left to create this “Magical” solution tomorrow, that was needed yesterday by the suits to gain a stronghold on the changing market.

     

    I will give you my perspective from my limited business intelligence knowledge in insurance, and give my perspective on a more general design on contracts and policies.  This domain basically revolves around a set of terms and a set of conditions, tied to a policy holder.

     

    Terms:

    Typically these terms (or definition), can join 2 or more people or business entities and an obligation.  The term defines the obligations and is considered the “body” of the policy.  Take for example a Term Life Insurance product.  I, the underwriter, will pay out to your policy of 100,000 dollars to your beneficiary, if you die within the next term length x years.  You, the policy holder, will pay us 30 dollars a month, for term length x years. 

     

    The problems you’re left with are, since these are set in stone as a contract, how do you maintain new products that might arise, and still maintain a good grasp on the policies that are already in place?   How do you make adjustments to the policy, riders, etc., and still keep the terms in tact and know whether or not that adjustment was made prior to or after any particular date.  We’ll talk about your inheritance model in just a bit.

     

    Conditions:

    The next portion is the conditions, which are by definition always includes the unknown and variables that would break the obligations and the policy is no longer valid.   An example would be, if you jump off a bridge, we, the underwriter will not pay out any money.  There are a series of these, which would be considered mostly the policy rules if these are broken this is not valid.

     

    I hear what you’re saying about using inheritance to determine a whole life vs. term policy in way that inheritance makes sense.   The problem here is that the products behavior can change, and they can change often.  They can change from year to year, and their conditions can change.  You can add a rider on your policy, in mid-stream, and those conditions can change as well.

     

    In OO, we’re first taught about inheritance and that’s really the hook.  Look see, a Car is a Vehicle, and a Truck is a Vehicle too.   The IS-A construct makes sense and makes us believe that inheritance will solve all our problems.  I’d like to say that a

    Well that’s great and all, but the reality is that there is a huge difference in the components that make up these cars, and they potentially change every year.  Just go into your local auto parts dealer and see the massive books they have on parts for individual cars.

     

    So here’s my recommendation, and I’ve attached the sample code as well, because this editor applies breaks and it’s difficult to see. You will be able to see that the architecture and patterns in use, make it possible to not have to scramble all the time, even in a complex development environment, like yours.   I recommend and show that using inheritance is good, but only for Type Matching only and not for behavior.  Behavior typically varies the most, and changes the most. and behavior should be left to the Processors.  This whole manager pattern follow the open/Closed Principle, meaning, the architecture is left open for inclusion but closed for modification,  so you are able to add additional products at any time, and it will not affect any current code.  Or if you have to suddenly change a product, you may do so without affecting any other code(nothing like bringing down an entire system).  You will never be left having to manager a fury of if/then/else conditional logic, as all of the code as it’s place and we’re always separating out the code for the differing products.  The code is not in one place as in the Components pattern by itself, however, in very large systems, it’s easier to manage many files because the different parts of the overall entity usually follow an organizational pattern to them as well.  So behavior will always be found in a single location.

     

      So this statement works, but there’s really nothing to TermLifePolicy, because the actual implementation is in the body and processors.

     

                if (policy is TermLifePolicy)

     

    All of the inheritance is mostly used only for type matching and all of the implemlentation code favors composition when coding toward an interface.  The HAS-A Construct lends itself great with the Strategy Pattern, and does not tie yourself down with coupling.  and lies within the body of the entity, Terms, Conditions, and PolicyHolder, using a Strategy pattern. I’m using a marriage of both the manager pattern and the Components pattern to show you that there is still flexibity in using both patterns, or I could use extensively one without the other and still be able to manage.

     

    I hope this helps, I’m not sure it does, please let me know if I just made things more confusing.

     

     
    See attached version for cleaner look, the editor messes it up.
    using System;
    using System.Collections.Generic;
     
    namespace FunWithInsurance
    {
     
     
    /// <summary>
    /// Basically the manager or component is responsible for
    /// implementation of security authorization, logging auditing
    /// and upmost behavior verbs, ie. Create(), Save(), Get(), Delete(), CreateQuote()
    /// I'm using a Manager here for my example.
    /// The context is your meta data used to maintain a healthy application
    /// </summary>
    public class PolicyManager
    {
     
    public PolicyManager() { }
     
     
     
    #region Create Policy
    public IPolicy CreatePolicy(IPolicy policy, out Context context)
    {
     
    if (!this.HasRights(context, ActionType.Create))
    {
        Log.SecurityLog(policy, context, ActionType.Create);
     
        throw new Exception("This action is not allowed.");
    }
     
    // Before Event Handling:
    // Now is a good time to subscribe or fire to necessary events
    // that happen BEFORE you hand off a policy to Create
    // ex. Notifications and Messaging, or Invalid State
    try
    {
     
        // Get the processor
        PolicyProcessor policyProcessor = ProcessorFactory.Create(policy);
        //Call the processor
       IPolicy policy = policyProcessor.ProcessCreate(policy, context);
     
    }
    catch (Exception exc)
    {
     
        //log exception, object, context, and verb
        Log.ExceptionLog(exc, policy, context, Action.Create);
    }
     
    // Post Event Handling
    // Now is a good time to subscribe or fire to necessary events
    // that happen AFTER a policy get's processed from Create
    // ex. Notifications and Messaging, or Invalid State
    //Since this type of information is extremely sensitive we log all actions
    Log.Entry(policy, context, ActionType.Create);
     
    // Return entity
    return policy;
     
    }
    #endregion
     
    #region Save Policy
    /// <summary>
    /// Notice there is no actual implementation here. I'm really just here to keep things moving around
    /// and ensure that the health of my application is in order.
    /// Think of a manager in a store. The manager really only walks around and handles exceptional cases.
    /// The manager does not actually do any work, other than
    /// 1. Overrides (Security and Auth - based on context)
    /// 2. Angry Customers (thrown Exceptions)
    /// 3. Handles Manager On Duty (MOD) Calls (Event Management)
    /// 4. opens and Locks the Store (The manager object should be the entry point for all things in your complex application)
    /// </summary>
    /// <param name="policy">entity</param>
    /// <param name="context">context can enclose security authorization and anything</param>
    /// <returns>IPolicy as a typed Policy</returns>
    public IPolicy SavePolicy(IPolicy policy, out Context context)
    {
    if (!this.HasRights(context, ActionType.Save))
    {
    Audit.SecurityLog(policy, context, ActionType.Save);
    throw new Exception("This action is not allowed.");
    }
    // Before Event Handling:
    // Now is a good time to subscribe or fire to necessary events
    // that happen BEFORE you hand off a policy to Create
    // ex. Notifications and Messaging, or Invalid State
    try
    {
    // Get the processor
    PolicyProcessor policyProcessor = ProcessorFactory.Create(policy, context);
    //Call the processor
    IPolicy policy = policyProcessor.ProcessSave();
    }
    catch (Exception exc)
    {
    //log exception, object, context, and verb
    Log.ExceptionLog(exc, policy, context, Action.Save);
    }
    // Post Event Handling
    // Now is a good time to subscribe or fire to necessary events
    // that happen AFTER a policy get's processed from Create
    // ex. Notifications and Messaging, or Invalid State
    //Since this type of information is extremely sensitive we log all actions
    Log.Entry(policy, c, ActionType.Save);
    // Return entity
     
    return policy;
    }
    #endregion
    #region ProcessorFactory
    public class ProcessorFactory
    {
    public static PolicyProcessor Create(IPolicy policy, Context context)
    {
    // use a property in Policy to create a new policy processor to use.
    // You can get fancy by using reflection and Activator.CreateInstance, to determine this as well.
    // ensure that you pass in both the policy and context to processor.
    }
    }
    #endregion
    }
    #region Policy Processors
    public class PolicyProcessor
    {
    public IPolicy ProcessCreate();
    public IPolicy ProcessSave();
    public IPolicy ProcessDelete();
    public IPolicy ProcessGetBy();
    }
     
    #region TermLifeProcessor
    /// <summary>
    /// this process is responsible for the actual implementations to for my particular policy.
    /// </summary>
    public class TermLifeProcessor : PolicyProcessor
    {
    private IPolicy policy;
    private Context context;
    /// <summary>
    /// The factory is responsible for the creation of the Processor, and assigning the policy and context.
    /// </summary>
    /// <param name="policy"></param>
    /// <param name="context"></param>
    TermLifeProcessor(IPolicy policy, Context context)
    {
    this.policy = policy;
    this.context = context;
    }
    /// <summary>
    /// All the real magic is done in here
    /// this process is responsible for these steps to save my policy.
    /// 1. it has to validate and save the terms
    /// 2. it has to validate and save the conditions
    /// 3. it has to validate and save my policyholder info,
    /// 4. which would in turn call the policyholdermanager//
    /// 5. which would validate and save my policyholder rider info, you get the idea.
    /// </summary>
    /// <param name="policy"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public IPolicy ProcessSave()
    {
    if (IsEntityValid(policy))
    {
    if (context.HasTransaction
    && context.TransactionManager != null
    && context.TransactionManager.Isopen)
    {
    DataRepository.PolicyProvider.Save(context.TransactionManager, policy);
    DataRepository.TermsProvider.Save(context.TransactionManager, policy.TermsCollection);
    DataRepository.ConditionsProvider.Save(context.TransactionManager, policy.ConditionsCollection);
    }
    // or if modeled correctly, you can just call Deep save
    }
    }
    public IPolicy ProcessCreate()
    {
    //same body type as ProcessSave()
    }
    /// <summary>
    /// check the entity, along with the children this processor is responsible for.
    /// for this particular product
    /// </summary>
    /// <returns></returns>
    public bool IsEntityValid()
    {
    bool isValid = true;
    // You can do your type checking
    if (!(policy is TermLifePolicy))
    {
    isValid = false;
    }
    if(policy.Coverage > Policy.MaxCoverage)
    {
    this.context.Messages.Add(new Message("The coverage amount is invalid.", MessageType.ProcessorError));
    isValid = false;
    }
    if (policy.Term.TermLength > Policy.Term.MaxTermLength)
    {
    this.context.Messages.Add(new Message("The term length is invalid, it can not exceed 30 years.", MessageType.ProcessorError));
    isValid = false;
    }
    return isValid;
    }
    }
    #endregion
    public class WholeLifeProcessor : PolicyProcessor
    {
    // All the work with the entities goes in here.
    // same as above, just with different business rules
    }
    #endregion
    #region BLL Context and Stuff
    public enum ActionType
    {
    Create,
    Save,
    Process,
    Read,
    Get,
    CreateQuote
    }
    /// <summary>
    /// This can be considered the Meta-Data Class
    /// can contain current user, roles, groups, permissions
    /// pages/forms affected
    /// AuditTrail things like that.
    /// transaction enlistment
    /// Warnings and Errors that can be sent back to the UI
    /// </summary>
    public class Context
    {
    public SecurityPrincipal User
    {
    get { }
    }
    /// <summary>
    /// Able to wrap the transaction manager for enlistment.
    /// </summary>
    public DataAccessLayer.TransactionManager TransactionManager
    {
    get { }
    set { }
    }
    // messages that can be delivered back to the UI, for showing
    public List<Message> MessageList;
    }
    #endregion
     
    #region Business Entity classes
    public class Person : Entities.Person
    {
    string Name;
    string Age;
    string Relationship;
    }
    public class PolicyHolder
    {
    public Person Assignee;
    List<Person> Riders;
    List<Person> Benificiary;
    }
    public interface IPolicy
    {
    public virtual Entities.TermCollection Terms
    { get; set; }
    public virtual Entities.ConditionCollection Conditions
    { get; set; }
    }
     
    public class TermLifePolicy : Entities.Policy, IPolicy
    {
    public TermCollection Terms
    {
    get {
    if (terms == null)
    terms = TermLifeTerm.GetTermsByPolicyId(this.PolicyId, this.Context);
    return terms;
    }
    }
    public ConditionCollection Conditions
    {
    get
    {
    if (conditions == null)
    conditions = TermLifeCondition.GetConditionByPolicyId(this.PolicyId, this.Context);
    }
    }
    }
    public class WholeLifePolicy : Entities.Policy
    {
    public TermCollection Terms
    {
    get
    {
    if (terms == null)
    terms = WholeLifeTerm.GetTermsByPolicyId(this.PolicyId, this.Context);
    return terms;
    }
    }
    public ConditionCollection Conditions
    {
    get
    {
    if (conditions == null)
    conditions = WholeLifeCondition.GetConditionByPolicyId(this.PolicyId, this.Context);
    }
    }
    }
    /// <summary>
    /// Inheritance for Type Matching Only,
    /// No Actual Behavior implementation here
    /// favor using compositon, HAS-A relationships to fullfil
    /// Whole Life Term specific implementation needs
    /// </summary>
    public class WholeLifeTerm : Terms
    {
    #region Create Mapping Methods
    /// <summary>
    /// If you do not have a static factory creational pattern in the DAL,
    /// like i posted in the forums
    /// http://forum.codesmithtools.com/default.aspx?f=19&p=1&m=8534
    /// Posted 11/7/2005 7:52 PM (GMT -6)
    /// (about halfway down the page)
    ///
    /// Then you will have to map your entities to your Decorator Objects.
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    public static WholeLifeTerm Create(Entities.Term t)
    {
    WholeLifeTerm w = new WholeLifeTerm();
    this.termID = t.TermId;
    this.specificTerm = GetSpecificTermFromSomewhere();
    return w;
    }
    public static TermCollection Create (Entities.TermCollection terms)
    {
    TermCollection tc = new TermCollection();
    foreach(Term t in terms)
    c.Add(Create(t));
    return tc;
    }
    #endregion
     
    /// <summary>
    /// My Terms Data Access
    /// </summary>
    /// <param name="policyId"></param>
    /// <returns></returns>
    public static Entities.TermsCollection GetTermsByPolicy(int policyId)
    {
    // having to map, because the NetTiers.DAL is being used as is out of the box.
    // if we are creating and using inheritance for Type Matching, then you'll have to map to your business type
    // otherwise, if you use a creational factory in the DAL, then you can have those types be created when you
    // specify what type to create.
    // More Info on creational factory pattern: See the summary in the Create Method above.
    return Create(DataRepository.TermsProvider.GetTermsByPolicyId(policyId));
    }
    public MySpecificTerm SpecificTerm
    {
    get { }
    set { }
    }
    }
    #region More Terms and Conditions -
    /// <summary>
    /// Inheritance for Type Matching Only,
    /// No Actual Behavior implementation here
    /// favor using compositon, HAS-A relationships to
    /// fullfil Whole Life Condition specific implementation needs
    ///
    /// SEE IMPLEMENTATION ABOVE as it's the same but now dealing with Conditions.
    /// </summary>
    public class WholeLifeCondition : Conditions
    {
    public MySpecificCondition SpecificCondition
    {
    get { }
    set { }
    }
    }
    /// <summary>
    /// Inheritance for Type Matching Only,
    /// No Actual Behavior implementation here
    /// favor using compositon, HAS-A relationships to fullfil Term Life Term specific implementation needs
    ///
    /// SEE IMPLEMENTATION ABOVE as it's the same but now dealing with Conditions.
    /// </summary>
    public class TermLifeTerm : Term
    {
    public MySpecificTerm SpecificTerm
    {
    get { }
    set { }
    }
    }
    /// <summary>
    /// Inheritance for Type Matching Only,
    /// No Actual Behavior Implementation Here
    /// favor using compositon, HAS-A relationships to fullfil term-life specific implementation needs
    ///
    /// SEE IMPLEMENTATION ABOVE as it's the same but now dealing with Conditions.
    /// </summary>
    public class TermLIfeCondition : Condition
    {
    public MySpecificCondition SpecificCondition
    {
    get { }
    set { }
    }
    }
    #endregion
    /// <summary>
    /// Basic Term, inherits from generated entity.
    /// </summary>
    public class Term : Entities.Term
    {
    }
    /// <summary>
    /// Basic Condition table, inherits from Entity.Condition
    /// </summary>
    public class Condition : Entities.Condition
    {
    }
    #endregion
    }

    Post Edited (Robert Hinojosa) : 11/11/2005 8:52:19 PM GMT


    Robert Hinojosa

    -------------------------------------
    Member of the Codesmith Tools, .netTiers, teams

    http://www.nettiers.com
    -------------------------------------
    • Post Points: 115
  • 11-22-2005 3:07 AM In reply to

    • johnnyj
    • Top 500 Contributor
    • Joined on 11-17-2005
    • Posts 11
    • Points 315

    RE: DOC: I've got NetTiers Generated, now where do I go? Part II

    Robert,

    Great to see your new posts - They were a joy to read... :-)
    I am working on the 'fatness' of my business layer and its great to hear your spin on the matter.
    Thanks for putting your thoughts up for those of us facing this important quandary!

    john.

    P.S. Big Respect for all your hard work. Keep it up, and Thank You.
    • Post Points: 5
  • 12-30-2005 2:58 PM In reply to

    • zkent
    • Top 50 Contributor
    • Joined on 11-16-2004
    • Colchester, VT, USA, N. America, Earth....
    • Posts 83
    • Points 1,425

    Re: DOC: I've got NetTiers Generated, now where do I go? Part II

    John,

    What does the following code do?  I dont understand the <Person> syntax.

        public class PolicyHolder
        {
            public Person Assignee;
            List<Person> Riders;
            List<Person> Benificiary;
        }

    Zach
    Zachary Kent
    Director of IT

    R. J. Peters Associates, Inc.

    www.avmax.net
    • Post Points: 65
  • 12-30-2005 11:09 PM In reply to

    • bgjohnso
    • Top 10 Contributor
    • Joined on 09-15-2005
    • Spokane, WS
    • Posts 763
    • Points 22,465

    Re: DOC: I've got NetTiers Generated, now where do I go? Part II

    Zach,

    That syntax is for generics in .Net 2.0.  In a nutshell, generics give you the ability to have strongly typed collections or lists.  List<Person> says that you are declaring a List object that contains Person objects.  It gets around having to cast objects are you retrieve them from the collection.  Just do a search on google for generics and you will get all the info you ever wanted.

     

    Ben Johnson
    ------------------------------
     Member of the .NetTiers team
     Visit http://www.nettiers.com
    ------------------------------
    • Post Points: 5
  • 03-30-2006 8:35 AM In reply to

    • omar_ita
    • Top 150 Contributor
    • Joined on 11-29-2005
    • Posts 32
    • Points 820

    Re: DOC: I've got NetTiers Generated, now where do I go? Part II

    Here's a little explanation of generics..

    http://www.codeproject.com/csharp/generics_explained.asp


    • Post Points: 5
  • 05-07-2008 6:39 AM In reply to

    • alexlea
    • Top 500 Contributor
    • Joined on 04-25-2006
    • Posts 11
    • Points 205

    Re: DOC: I've got NetTiers Generated, now where do I go? Part II

     This is a fantastic article, thanks!

     Am I right in assuming the newer xxxxxxService classes are synonomous with the Manager class in this example? How would Service.Execute(ProcessList) be incorporated as in this example there is no processing pipeline, just a single processor. Also, here the processor has multiple public methods: Create, Save, Delete, GetBy, one for each unit of work. Where appropriate should they be replaced with methods in the Service class calling a dedicated processor for each work unit? e.g.:

    public void CreatePolicy (IPolicy policy)

    {

        Execute (new CreatePolicyProcessor (policy));

    Obviously some of those methods are now provided out of the box.

    Also in the above example where do the derived entity types such as TermLifePolicy : Entities.Policy, IPolicy come from? Can they only practically be used for Create operations? When updating you have usually retrieved and existing entity which would of the base type Entities.Policy.

    Any chance of a few pointers as to how this could be implemented with the 2.2 templates? 

     

    • Post Points: 5
Page 1 of 1 (6 items)
Copyright © 2008 CodeSmith Tools, LLC
Powered by Community Server (Commercial Edition), by Telligent Systems