One AddIn or Many

Latest post 05-27-2008 11:38 AM by Terry. 2 replies.
  • 05-22-2008 11:12 AM

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    One AddIn or Many

    This is a re-start of an email conversation from a couple weeks back.  The recommendation was to start with the Forums, so here I go.  Note that I'm trying to simplify this as much as I can so some of this isn't entirely representitive of how we are implementing this...

    One of the parts of our to-be system involves sending messages to users as they are ordering a product.  Our products are complex so there are LOTS of potential messages... say 100-400 unique messages per product.  Messages are more than just text for us because they have override levels (security), one or more controls on the screen they relate to (for visual color-coding) and the text in the message needs to be built dynamically.  For example, we might have a user enter a Size that is too big to manufacture.  Instead of just saying "Size is too big" we want to say "The requested size of [XXXX] is larger than our maximum size of [YYYY]."  In this case, the size they entered needs to be put in on the fly AND the maximum size might vary depending on the way they've configured the item they are ordering.  Finally, the logic to determine whether or not to show the message can be very complex.

    This is where VSTA comes in.  We are planning to use VSTA to address the building of the message text dynamically as well as the logic to determine whether or not to show the message.  Here's the plan...

    At run time, we instantiate a collection of all potential Message Objects.  As the user interacts with the order entry screen, we loop through each message and fire an event [OnEvaluate()] so the object can evaluate whether it should display.  The event sets a property on the Message [.Display() AS Boolean].  We then check this Property and if it's true we fire another event [OnDisplay()] to build the text of the message and stuff it into another property [.MessageText() As String].  Finally, we use that .MessageText() and several other properties to send the message to the UI.

    So far, this is nothing too crazy.  The question comes in when we look at how to structure the AddIns.  There seem to be three general approaches to the problem.  I'll describe each along with advantages/disadvantages.

    1) Create one AddIn for each Message.  In this scenario, each Message object would be the one and only Primary Host Item in it's dedicated AddIn project/dll.  This is very clean in terms of isolating the code for a message to one class file and the class file would have just two events in it.  Very user friendly.  The down side is that I'll have to load up hundreds of addin's for a user to order a product.  Maybe not a big deal except that we are running a web order entry system that is being used by a couple hundred users at a time.  This concerns me from a performance and stability perspective.

    2) Create one AddIn for the Product.  Here, we would have our Primary Host Item be some sort of Product object.  This Product object would be the one and only Primary Host Item in the AddIn project.  We would then have the two events (OnEvaluate and OnDisplay) declaired directly in the Prouct class.  Then we would call these events over and over as we looped through all the messages, passing in some sort of MessageEventArgs that helped the event know what message was being evaluated.  The advantage to this approach is that I only have to load one AddIn/Dll for each user/product, which should perform quite well.  Unfortunately there is a HUGE disadvantage in having logic for 100-400 different messages all put into one event handler.  With so many messages, this aproach is really not realistic for business users to manage.

    3) Create one AddIn for the Product with one Host Item for each message.  This is a blended approach where we have one AddIn and it's Primary Host Item is some sort of Product Class.  When the AddIn Developer is in design time and creating messages, we add a Host Item Class File to the AddIn Project for each message they create.  When they go to write code for the two events on each message, they will be added to the Class File that is dedicated to that unique message.  This provides all the code isolation benefits of approach #1 while having the single AddIn/Dll performance and stability benefits of #2.  The only unknown is creating an AddIn project with hundreds of class files.  I guess my experience is to trust the compliler's ability to deal with lots of class files more than I trust the Run Time to handle loading and unloading 1000's of dlls.

    I'm sure it's apparent that #3 is my current opinion, but I want to be sure there aren't known or suspected issues with this approach.  Or, if #1 with all those little AddIn dll's is really nothing to be concerned about because there another disadvantage for #3.  We support versioning, check-in/out and environment support for each message.  This means that having them all wrapped up in one AddIn isn't that simple.  In reality, at run time I'm going to have to go out to the DB and get the current version of all those messages, grab their code, re-construct the AddIn Project, compile it and then load the AddIn Dll.  If I went with #1 I could have each message version's AddIn pre-compiled and just load the ones that are active at the moment.

    Opine away!

     

  • 05-27-2008 11:08 AM In reply to

    • Melody
    • Top 10 Contributor
    • Joined on 04-26-2007
    • Syracuse, NY
    • Posts 246

    Re: One AddIn or Many

    Terry,
    There are certainly pro's and con's to each approach.  I would suggest making prototypes of each approach and use these to determine which will work best for you in practice. 

    1)  Create one AddIn for each Message.
    >This concerns me from a performance and stability perspective.
    It will take time to load 100's of add-ins so there will be a performance hit- but it may be faster to do this using precompiled assemblies than what you described for approach 3 (at run time I'm going to have to go out to the DB and get the current version of all those messages, grab their code, re-construct the AddIn Project, compile it and then load the AddIn Dll) which I believe would also apply for approach 2.

    This is certainly the easiest and cleanest approach and may be the easiest for the end user to understand. 

    2) Create one AddIn for the Product.
    >Unfortunately there is a HUGE disadvantage in having logic for 100-400 different messages all put into one event handler.
    It seems that all three approaches would have all of the logic tied into one event handler (am I misunderstanding this?).  Also, wouldn’t this approach have the same draw back as approach 3- that at run time the current versions would need to be grabbed from the DB and recompiled? 

    One idea to make this approach easier is to use an IPH to automate the code creation and event hook-up.  For example, add a button to the IDE that when pressed will add a code file and hook-up/unhook the event in the start up and shut down methods.  If you are interested in this approach, check out the SDK walkthrough on In-Process Hosts (IPH) and this MSDN page on programmatically adding items to a project.

    3) Create one AddIn for the Product with one Host Item for each message.
    >The only unknown is creating an AddIn project with hundreds of class files.
    There are no known issues with this- I did very limited testing and was able to create a DPM project for a document with 500 drawings.  It did take a long time to create all of the files (10+ minutes) but the build time wasn’t too bad.

    >I'm sure it's apparent that #3 is my current opinion, but I want to be sure there aren't known or suspected issues with this approach.
    There are no known or suspected issues with this approach.

    >Or, if #1 with all those little AddIn dll's is really nothing to be concerned about because there another disadvantage for #3.  We support versioning, check-in/out and environment support for each message.  This means that having them all wrapped up in one AddIn isn't that simple.  In reality, at run time I'm going to have to go out to the DB and get the current version of all those messages, grab their code, re-construct the AddIn Project, compile it and then load the AddIn Dll.  If I went with #1 I could have each message version's AddIn pre-compiled and just load the ones that are active at the moment.

    It sounds like you will be dealing with/storing each message individually- versioning per message not product and updating specific messages without wanting to check out all of the messages for a product.  Based on this and the complexity and time involved with grabbing the current code from the DB and recompiling, I would suggest approach 1 (KeepItSimple).  However, this design decision ultimately lies with you.  Again, I would suggest prototyping each approach to get a more realistic idea of the performance hits involved with loading 100’s of add-ins or managing one add-in with hundreds of files which need to be updated then recompiled.  I would also consider the end-user perspective, will your end users be able to use and navigate through a project with 100’s of files or will they be more confused by having 100’s of projects? 

    Another approach may be to chunk the messages- have one project that holds all of the messages for one type of logic (example add-in CheckSize with 5 code files/messages:  CheckWidth, CheckHeight, CheckWidthHeightRatio…).  This would reduce the number of add-ins loaded and offer the end user small easy to use files without forcing them to work with only one message at a time.  You could also consider versioning the group instead of the individual messages so that you are still only using precompiled assemblies.

     

    I hope this helped- please let me know if you have any questions.
    Thanks,
    -Melody

  • 05-27-2008 11:38 AM In reply to

    • Terry
    • Top 10 Contributor
    • Joined on 05-10-2006
    • Posts 90

    Re: One AddIn or Many

    Thanks that does help.

    In #2 where you are wondering what would be different between the approaches and where the code ends up.  I was saying that in #1 there would be just one class file with a set of events that would have to address every unique message.  In the Others, you have a dedicated class file (HostItem) for each message so even though the events would be essentially the same, the code in them would only be concerned about that one message.

    One thing I left out of the discussion for the sake of simplicity is our concept of MessageGroups.  These are similar to what you were suggesting toward the end of the reply.  A Message group is a container that also has conditional logic that will determine if it's messages need to be evaluated.  My current design has this Message Group as the primary Host Item for an AddIn and then the messages that are in that group would go into it's addin project as additional HostItems.  This has the advantage of reducing the number of messages per AddIn becuase they will be divided into groups.  It will still suffer from some of the run-time complexities of #3, but not as bad.  The only catch here is that users can still choose to have just one Message Group so I need to design around the possibility that they will do something like that.... though it really wouldn't make any sense.

    Based on this, I'm going to continue with the design as-is.  Fortunately, I have most of the VSTA functionality of our system packaged into a "black-box" type of implementation, so some of this can be changed without starting from scratch if needs be.

    Wish me luck...

Page 1 of 1 (3 items) | RSS
Copyright Summit Software Company, 2008. All rights reserved.