The EntitySpaces Community

Share and learn about the EntitySpaces Architecture.
Welcome to The EntitySpaces Community Sign in | Join | Help
in
Home Forums Photos

Suggestion/Feature Request: Separate non-required features within ES templates from "required"

Last post 01-17-2008, 10:21 AM by pritcham. 6 replies.
Sort Posts: Previous Next
  •  01-11-2008, 1:15 PM 7591

    Suggestion/Feature Request: Separate non-required features within ES templates from "required"

    I am still a "trial period" user and I am probably trying to use ES to its extreme capability, but all I ask is that my comments are, at least, used to consider ES going forward.

    What I have found, or my impressions: IT seems to me that several features were implemented within ES templates because they are so common, or simply desired by most users. I also believe that some features are implemented because its hard to imagine that they could conflict with any particular framework design. I ask for VERY careful consideration on this point.

    There are many ways to achieve a task, or to create a framework design and -yes - some frameworks have features in common.

    Take for example, INotifyPropertyChanged; this was implemented on the "core" library for ES. It might seem that all users would want this implememented and it might seem that it would not be a factir for those who do not.

    Now consider my scenario:

    1. INotifyPropertyChanged (Using ES & WCF in an n-tier framework): For me, INotifyPropertyChanged only applies to a UI. I do not have any business logic that seeks to register with PropertyChanged events. Thus, the interface INotifyPropertyChanged, for me, ONLY applies to the UI tier. When a user makes a change in the UI to one control, INotifyPropertyChanged is used for other controls to auto-update. However, the client-side is where the UI code resides, not the ES EntityBase classes where the interfaces are currently implemented.

     2. PropertyChanges: It is required for my model that properties are not considered changed if the same value is applied. I must also not allow a user to make a change, change the value back to the original (which would normally make an object be marked a changed) and save the data with the same values. To achieve this, my ProxyStub classes implement a custom Getter for every property and I have a custom base class for the client ProxyStubs. This allows catching property changes and disabling the Svae button which no changes are applied. The client-side holds a copy of original values and rejects saving if all values match original values... the service-side then redundantly performs the same check in case the client-side is somehow compromised.

    My ProxyStub properties are defined like this:

    [DataMember]
    public System.DateTime? Created {
       
    get { return _Created; }
       
    set { SetPropertyValue<System.DateTime?>("Created", ref this._Created, value); }
    }

    private System.DateTime? _Created;

    3. IDataErrorInfo is the interface Microsoft uses to have business bjects automatically update the UI with an Error Icon. The problem is that On/Off, Pass/Fail notification is inadequate; there are requirements for error levels. Further, again, the ProxyStub classes inertact with the UI, not the core EntityBase classes. So, again the ProxyStubs must be customized and the core classes have uneeded overhead.

    4. Interfaces: My business logic tier interacts with interfaces, not implementations. When ES reads the tables within the database, I have it create copy constructors for my ProxyStub classes ... AND... I have the EntityBase classes also implement the interface as well to create copy constructors and methods.

    Here is a sample:

           [DataContract(Namespace = "http://mynamespace.com/", Name = "AccountingPeriod")]

           [XmlType(TypeName = "AccountingPeriodProxyStub")]

           [Serializable]

           public partial class AccountingPeriodProxyStub : ClientBase, IAccountingPeriod  {

          

                  public AccountingPeriodProxyStub(){

                        

                  }

                 

                  public AccountingPeriodProxyStub(IAccountingPeriod copyObject){

                         SetValuesFromCopy(copyObject);

                  }

                 

                 

                  public void SetValuesFromCopy(IAccountingPeriod copyObject){

                      this._GCRecord = copyObject.GCRecord;

                      this._Oid = copyObject.Oid;

                      this._Created = copyObject.Created;

                      this._Modified = copyObject.Modified;

                      this._Name = copyObject.Name;

                      this._Description = copyObject.Description;

                      this._AccountingPeriodNumber = copyObject.AccountingPeriodNumber;

                      this._FromDate = copyObject.FromDate;

                      this._ThruDate = copyObject.ThruDate;

                      this._InternalOrganization = copyObject.InternalOrganization;

                      this._PeriodType = copyObject.PeriodType;

                      this._OptimisticLockField = copyObject.OptimisticLockField;

                  }

    So, what am I really getting at? Why did I list so many samples?

    What I am trying to make clear is that many users are likley to be like me where they need exacting control over their class definitions. This means we WILL be modifying the templates extensively.

    MY SUGGESTIONS:

    CORE LIBRARIES SHOULD STICK TO PERSISTENCE ONLY FEATURES: INotfyPropertyChanged and other UI related features, or any features not directly related to persistence should be moved into templates and out of the core library. This will offer the most protection from introducing breaking changes and will offer the most flexibility for customers to implement their particular design features.

    NEVER OVERWRITE TEMPLATES: Consider what can be done to make using customized templates as painless as possible. In my opinion, it is disastrous for an upgrade to overwrite anything that may have been customized. I cannot imagine how horrific it would be to have templates overwritten by mistake. I might suggest that the "default" templates be kept in a separate and unused directory and that a tool is created to regenerate (copy back) default templates. Templates should not be overwritten in an upgrade.

    PROVIDE MULTIPLE TEMPLATES: I suggest having multiple templates ranging from minimal (include only persistence related features that are required, no INotifyPropertyChanged, No base classes, no IDataErrorInfo, etc.) to a host of optional "starting" templates. I believe this allows for the easiest comparison of changes between versions. It means that users could most easily find ES persistence related changes. Now, features for INotifyPropertychanged, IDataErrorInfo, ProxyStubs, Custom Base classes, etc. are implmented in starting templates.

    NOTE: MyGeneration needs some changes (IMO) that I belive ES should request.

    1. Its nice to have forms that offer various options for code generation; however, the selected "options" are not persisted. It is simply annoying to reset the options every time. I would prefer to hand modify an option rather than have a popup form that doesn't remeber my settings. Essentially, that is what I do now - hand modify, but its a pain because there is no central location to easily apply settings.

    2. If you look at the code generation, current options are specific to particular templates. It seems really apparent to me that there should be globally applied template options where "bricks" of code could be applied. For example, using a base class. Desiring a base class is common, it seems it could be applied to numerous templates. Why have to manually define this feature for every template. If there were global template options, they could be selected/deselected for any template. Of course, persisting the settings as I mentioned above is really crucial. It would be best if settings could be loaded/unloaded and a default for each template applied.

    Anyway, I am a "rooky" with ES and MyGeneration, but these are my thoughts that I hope they are at least considered.

  •  01-13-2008, 8:50 AM 7603 in reply to 7591

    Re: Suggestion/Feature Request: Separate non-required features within ES templates from "required"

    You have some excellent suggestions here. I have added a link to this post in our enhancements tracking system for consideration as we move to ES2008. We have already discussed at our team meetings how there are some things that can be moved down, e.g. from Employees to esEmployees, or into Core. We also realize there are some things like Constructors that should not be in the generated classes, rather they should be customizable by the user. We have also discussed how we might implement more interfaces, without making our API too clunky or hurting performance. So, your ideas, including the detailed explanation for each, are very welcome.

    As to your general comments, we have a delicate balancing act facing us. Many of our users want something they can install, check a few options, and use without a lot of fuss. Others want to get into customization of the architecture's features in their custom classes, in the templates, and even source code, to meet more personalized requirements. Our goal is to provide an experience that does not require a masters degree in EntitySpaces, before you can generate useful code. But, still has the flexibility, and advanced features, that would require a more thorough understanding EntitySpaces, and could be implemented as needed, without re-writing a lot of existing code. Posts like this can help us understand how best to walk that tightrope.

    As far as not over-writing templates, we have not discussed this, but my initial reaction would be that it would cause a maintenance nightmare for us. It is not unusual that changes in Core require changes to the templates. The assemblies and templates are intimately tied together, and versions need to match. What is contained under the EntitySpaces namespace should be the templates we provide that match the assemblies installed.

    We encourage the use of code generation, and even provide some skeleton templates under the EntitySpaces.Example.Templates namespace to help users get started. They are based on a skeleton template that was generously provided to us from pritcham. The header comments in the TableViewSkeleton contain instructions on what is necessary to take that template, create a new template, in which you would add your custom template code, leaving the original skeleton un-modified, and ready to be re-used.

    But, we discourage the direct modification of EntitySpaces templates. Some of our users have modified EntitySpaces templates to meet their requirements. One of the great things about code generation, and the templates we provide, is that this is even possible. But, while may we provide some general guidance in this area, and sometimes try to answer a specific template coding question, we cannot be expected to support every template variation that users may come up with.

    If a user wants to customize EntitySpaces templates, the onus is on them to see to it they are not over-written. If those changes introduce bugs in the architecture, we cannot guarantee that we can help solve them. My suggestion would be to modify only copies of our templates. To summarize the instructions from the TableViewSkeleton header, copying templates involves a few things.

    1) Open the templates property pane, and click the New Guid button.
    2) Give the template a different namespace. Do not use the EntitySpaces namespace.
    3) Create a folder under the MyGeneration Templates folder, preferably one that matches the namespace.
    4) Click the "Save As" button, and save the template in the new folder. Renaming the template file name would not be necessary, but the name should reflect what the template is for, if you started with one of the skeletons.

    Regarding MyGeneration, unless I've misunderstood your requests, I believe most are already available.

    1) There are two possibilities here.

    a) My general preference for regenerating the Generated Masters is MyGeneration Projects, and wrote up a FAQ on their use here.

    b) For debugging individual templates, where I am re-running the same template over and over, perhaps with minor UI option changes, I prefer to use the caching feature that Mike contributed to DnpUtils. The skeleton templates provided have this feature. Our templates have it removed, so they can be used in projects, without interfering with the project editing process.

    Code:
    Caching template UI 
    (from EntitySpaces.Example.Templates "TableViewSkeleton")
    
    Template Code:
    
    // You may need to comment out the next line, if the
    // template is to be used in a MyGeneration Project.
    DnpUtils.SaveInputToCache(context);
    
    Interface Code:
    
    // You may need to comment out the next line, if the
    // template is to be used in a MyGeneration Project.
    DnpUtils.ReadInputFromCache(context);

    2) I think what you want are MyGeneration Template Groups. If you open the EntitySpaces Generated Master, you will see very little Template code. It is all Interface Code. If you open the properties pane, you'll see that "Type" says "Group", not "Template". That choice adds an extra listbox at the bottom, "Included Template Scripts". Each of those templates will be run in the order listed. The options contained in the template UI from the group template are available to each.

    Great post... keep the feedback coming. We cannot say when, or even if, a particular suggestion might be implemented, or what form it may take. But, we definitely listen to our users, and EntitySpaces would not be where it is today without the suggestions we've gotten from them.


    David Neal Parsons
    www.entityspaces.net
  •  01-14-2008, 9:16 AM 7615 in reply to 7603

    Re: Suggestion/Feature Request: Separate non-required features within ES templates from "required"

    David.Parsons:

    As to your general comments, we have a delicate balancing act facing us. Many of our users want something they can install, check a few options, and use without a lot of fuss. Others want to get into customization of the architecture's features in their custom classes, in the templates, and even source code, to meet more personalized requirements. Our goal is to provide an experience that does not require a masters degree in EntitySpaces, before you can generate useful code. But, still has the flexibility, and advanced features, that would require a more thorough understanding EntitySpaces, and could be implemented as needed, without re-writing a lot of existing code. Posts like this can help us understand how best to walk that tightrope.

    This is why I am trying to share my initial thoughts as an end-user. I think you are also defining what I am noticing: there are two main user types:

    1. As-is Users: customize little and want more than persistence features "out-of-the-box".
    2. Existing Framework Users: Have from basic to extensive business logic frameworks already designed and want ES to do one thing: Handle Persistence - nothing extra because it conflicts wih existing design.

    I am wary of not splitting ES into the two user groups.

    #1 is far more intensive to develop (feature rich), must somehow not quite meet everyones needs exactly (how can it if every user has slightly to majorly different expectations and needs). So, I expect #1, over-time, to turn into its own independent framework.

    #2 is simply ensuring that only the persistence-related features are included. It is far-less feature rich. Users like me find that ES is expanding into areas outside of persistence and while these extra features are helpful to #1 users, they conflict with the frameworks of #2 users. Now, whenever a new version is released, I will have to hope for the best in that I pray some breaking change hasn't been introduced. If I start with the overwritten templates provided in a release, they are already majorly different from my own. I did not slightly tweak them. I have no issues or complaints modifying and adapting with each release to accomodate persistence-related features, but it is already significant to adjust to the non-persistence related features that are intermixed.

    I am not expecting ES to adjust to me, but looking forward is it easy to see that ES is becoming more and more of its own framework and not just a persistence tool? From my experience, framweworks are hard to sell - they are given away. Isn't the framework is usually what defines a business application? Most of the referenced frameworks are offered free (Enterprise Library, CAB, SAB, SOA, etc, etc). Don;t misunderstand me - or I should be carful on what I say. I think its prudent, practical, and potentialy very profitable for ES to expand, but I also belive that a good framework keeps features modulized so they do their purpose independently. I am suggesting careful consideraion to seaparate persistence from business logic (validation, etc), from UI related features (INotifyPropertyChanged, IDataErrorInfo, etc). Mixing them makes maintenance very difficult.

    David.Parsons:

    As far as not over-writing templates, we have not discussed this, but my initial reaction would be that it would cause a maintenance nightmare for us. It is not unusual that changes in Core require changes to the templates. The assemblies and templates are intimately tied together, and versions need to match. What is contained under the EntitySpaces namespace should be the templates we provide that match the assemblies installed.

    We encourage the use of code generation, and even provide some skeleton templates under the EntitySpaces.Example.Templates namespace to help users get started. They are based on a skeleton template that was generously provided to us from pritcham. The header comments in the TableViewSkeleton contain instructions on what is necessary to take that template, create a new template, in which you would add your custom template code, leaving the original skeleton un-modified, and ready to be re-used.

    But, we discourage the direct modification of EntitySpaces templates. Some of our users have modified EntitySpaces templates to meet their requirements. One of the great things about code generation, and the templates we provide, is that this is even possible. But, while may we provide some general guidance in this area, and sometimes try to answer a specific template coding question, we cannot be expected to support every template variation that users may come up with.

    If a user wants to customize EntitySpaces templates, the onus is on them to see to it they are not over-written. If those changes introduce bugs in the architecture, we cannot guarantee that we can help solve them. My suggestion would be to modify only copies of our templates. To summarize the instructions from the TableViewSkeleton header, copying templates involves a few things.

    1) Open the templates property pane, and click the New Guid button.
    2) Give the template a different namespace. Do not use the EntitySpaces namespace.
    3) Create a folder under the MyGeneration Templates folder, preferably one that matches the namespace.
    4) Click the "Save As" button, and save the template in the new folder. Renaming the template file name would not be necessary, but the name should reflect what the template is for, if you started with one of the skeletons.

    I understand your point.  Consider that once someone decides to create custom templates, its done once and then sometime later maybe done again: a lag period is likely. My point being that the details necssary to create custom templates are not too terribly difficult, but its just awkward eneough that its a pain to remember and ensure all the steps are followed properly. It seems MyGeneration could be improved if there were a simple context menu option to create a new base template in the current directory of the treeview. Of course, its complicated by the fact that I want to use a generic ES template as the starting point (Again - it is really, really desirable for me to have a template with only essential features). This would require a change in MyGeneration, but also affects ES. This is just a comment from a new user. Take my comments as you see fit.

    David.Parsons:

    I think what you want are MyGeneration Template Groups. If you open the EntitySpaces Generated Master, you will see very little Template code. It is all Interface Code. If you open the properties pane, you'll see that "Type" says "Group", not "Template". That choice adds an extra listbox at the bottom, "Included Template Scripts". Each of those templates will be run in the order listed. The options contained in the template UI from the group template are available to each.

    I "think" this may be what I want, but I need to experiment. Here is my intial thoughts:

    I choose a "base group" that implements a class structure and generates classes based on my database tables. The output with the "base structure" is minimalistic and even incomplete. For example, one base my not use custom base classes and another might. One base may use copy constructors and another may not.

    After choosing a class structure, its incomplete because a user can potentially choose (for example) to add a "group" that defines the property implmentation type (getters and setter implementations). A user may choose a group that implements INotifyPropertyChanged, or may choose to implement IDataErrorInfo, and may choose to implement WCF related features.

    Ideally, in the long run, I would prefer that a library of templates be developed and any user could choose the structural elements by selecting/deselecting them.

    For example,

    Class Structure Type:
        [x] Use Custom Base Class
        [  ] Do not use Custom Base Class
        [  ]  Use some other Base Type
        Base Form Options:
        [x]  Enable WCF Features
        [  ]  Use OrderBy (***this is a WCF feature and would be greyed out if WCF not enabled)
    Property Implementation Type:
        [  ] Use standard Getter and Setters (no custom features)
        [  ] Use INotifyPropertyChanged
        [  ] Use INotifyPropertyChanged, IDataErrorInfo
        [  ] Use INotifyPropertyChanged, IDataErrorInfo, & SupressEventsOption
        Property Options
        [x]  Enable WCF Features (*** not available if WCF base form not selected)
        // blah blah,

    I think the above explains what I "envision". There are - understandably - dependency issues. If an approach to above is used, this should allow for major "plug-n-play" customization and also - simultaneously- unsure that dependency requirements are met. ES would require at least one choice from each major group to satisfy its dependency requirements. Also notice that I listed WCF features to demonstrate that dependency related to WCF could be addressed even though the ES core itself has no WCF dependency. A user cannot add WCF property features (they should be greyed out and not generated) if the base class structure does not have WCF features enabled. Similarly it could be just as possiblt to require that one or more WCF features are slected if WCF class structure features are enbaled (I.e. The Enble WCF features for property implmentaion may be mandatory if Enable WCF is slected at the class level).

    Does that make it clear what I am suggesting? Again - there is no push, I am not demanding. Its simply an idea I am sharing that may have some real useful potential.

  •  01-14-2008, 9:26 AM 7617 in reply to 7615

    Re: Suggestion/Feature Request: Separate non-required features within ES templates from "required"

    Argh! Forgive my typing - I did not proof read and my brain was a lot faster than my fingers. I wish I had time to correct that - sorry!

     

  •  01-17-2008, 9:21 AM 7660 in reply to 7617

    Re: Suggestion/Feature Request: Separate non-required features within ES templates from "required"

    I don't know if anybody read the last part of my second post, but I am really wondering what others think. Am I whacko? Did anybody even understand what I was suggesting?

     I am trying to look at ES and MyGeneration from more than my perspective, but from the perspective of ES and how things 'could work' for all customers.

    I see the benefits of new users  getting framework specific features implemented, and I see problems with the need to customize features where some or many may conflict. The more features ES adds, the more I suspect users will want or need to customize the result for their specific needs.

     So, I am sitting here experimenting and drastically modifying templates (to experiment and because I do have features that are required and not currently included).

    My idea was to allow for modulized templates where features could be customized much like Dell runs their assembly line. Each customer can request a specific DVD, or CPU, or Power Supply, etc and the Dell line allows for each choice to be added specifically for the needs of each respective customer. Of course, certain features are required like a CPU, hard drive, etc or the shipped computer would fail and Dell's sytem prevents such catastrophies. My suggestion was to consider such a modulized approach. Currently, it looks like it could be done, but most features are hard-wired into the templates (I see a feature I want n one template and I simply cannot select it or unslect it in another), and there is no checking to ensure at least one implementation of a feature is implemented.

     I certainly understand it would take some time to implement such a model, but does it seem worth it for a long-term goal? Do you see the suggestion as a benefit? Or... Do you see problems with the idea? Or... Do you have some alternative that seems to make more sense?

    I think open discussion is a healthy way to find out. Simply put: I am just trying to toss an idea up in the air and am hoping people take shots at it. Maybe something useful will be left over.

    TIA

     

     

  •  01-17-2008, 10:06 AM 7661 in reply to 7660

    Re: Suggestion/Feature Request: Separate non-required features within ES templates from "required"

    I am totally on board with your suggestions. We will be putting out a road-map for ES2008 very soon, my hope is by the weekend of Jan 26th. Our plan is to have our own code generation system that will be very easy to use, code in, and debug, and yes, customizable with a stack of templates, we are listening (sorry for not replying)

    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  01-17-2008, 10:21 AM 7662 in reply to 7660

    Re: Suggestion/Feature Request: Separate non-required features within ES templates from "required"

    Hi Trevor

    Firstly, to answer your "did anyone read..." - yup - I certainly did, I did mean to add a reply but to be honest I've been busy with other projects and not been able to look at my EntitySpaces based work for a while.

    Anyway, I agree that it would be an incredibly useful approach to be able to modularise (sp) the templates so that you can effectively "pick and mix" what features/functionality is needed from in the generated code (it would also make user contributions a little easier to incorporate I think) - I know when the validation code was added in that I had to adjust my coding as I'd already implemented it myself - as with IDataErrorInfo if I recall correctly, so in my case at least it would have been very useful to be able to "switch off" the production of this code.

    As to the amount of work involved in amending the templates and core code, I think it might take a fair bit of work to compartmentalise everything in such a way that any pre-requisites required for the optional extras to run in any combination (i.e. I want IDataErrorInfo but not validation for example) but I'll leave it to the ES team to answer that one.

    In summary - I think it would be a very useful progression but obviously it depends on how this may impact on potential sales etc (I don't see it impacting on existing customers as you'd effectively just pick all options to generate what is already being generated if that makes sense).  Obviously it wouldn't make sense for the guys to put effort into something that could damage the sales of the product (although personally I don't think that would happen). So I suppose it depends on how practical it would be for the team to implement and whether they think it's worth going down that road rather than the road of adding more features etc.

    Cheers

    Martin

View as RSS news feed in XML