Note that there are some explanatory texts on larger screens.

plurals
  1. POOpinion requested: for static values, is it better to use Enums or Entities?
    primarykey
    data
    text
    <p>I'm trying to solve a dilemna that has been nagging me for the last few months.</p> <p>My colleagues and I completely disagree on a technical problem, and I would like our beloved community's opinion on the matter.</p> <h2>In a nutshell:</h2> <p>Is it preferable to use enumerations (with potentially attributes on them such as "Description"), or use entities (with Name and Description properties)?</p> <h2>In details:</h2> <p>In our domain model, we've got a lot of mini-entities which only contain an Id, a Name, and a Description. 95% of the time, the Description is equal to the Name.</p> <p>For the sake of the explanation I'm going to take one of the many example: in our Security entity, we have an AssetClass property. An AssetClass has a static list of values ("Equity", "Bond", etc.) and does not change from the interface or anything else.</p> <p>The problem with that, is when you want to get all securities with an asset class of "Bond" say, NHibernate will have to join on the AssetClass table... and considering AssetClass is not the only property like that, you can imagine the performance impact of all those joins.</p> <h2>Our current solution: (which I disagree with):</h2> <p>We have in our code some hard-coded instances of AssetClass with all their respective values and Ids (i.e. Equity with Id of 1, Bond with Id of 2 etc.), which match what's in the database:</p> <pre><code>public partial class AssetClass { static public AssetClass Equity = new AssetClass(1, "Equity", "Equity"); static public AssetClass Bond = new AssetClass(2, "Bond", "Bond"); static public AssetClass Future = new AssetClass(3, "Future", "Future"); static public AssetClass SomethingElse = new AssetClass(4, "Something else", "This is something else"); } </code></pre> <p>We also made a special NHibernate type (code below if you are interested) that allow us to avoid NHibernate doing a join by loading that hard-coded instance instead of going to the database to get it:</p> <pre><code>using System; using System.Data; using System.Data.Common; using NHibernate.Dialect; using NHibernate.SqlTypes; using NHibernate.Type; namespace MyCompany.Utilities.DomainObjects { public abstract class PrimitiveTypeBase&lt;T&gt; : PrimitiveType where T : class, IUniquelyNamed, IIdentifiable { private readonly PrimitiveTypeFactory&lt;T&gt; _factory; public PrimitiveTypeBase() : base(SqlTypeFactory.Int32) { _factory = new PrimitiveTypeFactory&lt;T&gt;(); } public override string Name { get { return typeof(T).Name; } } public override Type ReturnedClass { get { return typeof(T); } } public override Type PrimitiveClass { get { return typeof (int); } } public override object DefaultValue { get { return null; } } public override void Set(IDbCommand cmd, object value, int index) { var type = value as T; var param = cmd.Parameters[index] as DbParameter; param.Value = type.Id; } public override object Get(IDataReader rs, int index) { return GetStaticValue(rs[index]); } public override object Get(IDataReader rs, string name) { return GetStaticValue(rs[name]); } private T GetStaticValue(object val) { if (val == null) { return (T)DefaultValue; } int id = int.Parse(val.ToString()); T entity = _factory.GetById(id); // that returns, by reflection and based on the type T, the static value with the given Id if (entity == null) { throw new InvalidOperationException(string.Format("Could not determine {0} for id {1}", typeof (T).Name, id)); } return entity; } public override object FromStringValue(string xml) { return GetStaticValue(xml); } public override string ObjectToSQLString(object value, Dialect dialect) { var type = value as T; return type.Id.ToString(); } } } </code></pre> <h2>My solution: (which I agree with :-))</h2> <p>Replacing those entities by enums, and if we ever need a Description field, use an attribute. We could also have a constraint on the database to make sure you can't store random values that don't match an enum.</p> <h2>Their rational against using enumerations:</h2> <ul> <li>This is not an object, so you can't extend it, it's not object oriented, etc.</li> <li>You can't get the description easily, or have "proper english" names (with spaces or symbols) such as "My Value" (which on an enum would be "MyValue")</li> <li>Enums sucks</li> <li>Attribute sucks</li> </ul> <h2>My rational against our current solution:</h2> <ul> <li>We can have a mismatch between the ids in the code and what's in the database</li> <li>It's a lot harder to maintain (we need to make absolutely sure that every hard-coded values we have are also there in the database)</li> <li>Attributes and enums don't suck if used properly and for static values like these</li> <li>For "proper english" names, we can also use an attribute, with some extension method to consume it.</li> </ul> <p>Now, what do <strong>YOU</strong> think?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload