Запрошенное мнение: для статических значений лучше использовать Enums или Entities?

Я пытаюсь решить дилемму, которая мучила меня последние несколько месяцев.

Моя Мы с коллегами полностью не согласны по технической проблеме, и мне хотелось бы узнать мнение нашего любимого сообщества по этому поводу.

Вкратце:

Предпочтительнее ли использовать перечисления (с потенциально атрибутами, такими как «Описание») , или использовать сущности (со свойствами Name и Description)?

Подробно:

В нашей модели предметной области у нас есть много мини-сущностей, которые содержат только Id, Name и Description. В 95% случаев Описание совпадает с Именем.

Для пояснения я возьму один из многих примеров: в нашей сущности Security у нас есть свойство AssetClass. AssetClass имеет статический список значений («Капитал», «Облигация» и т. Д.) И не изменяется из интерфейса или чего-либо еще.

Проблема в том, что вы хотите получить все ценные бумаги вместе с активом. класса "Bond" скажем, NHibernate должен будет присоединиться к таблице AssetClass ... и, учитывая, что AssetClass - не единственное подобное свойство, вы можете представить себе влияние на производительность всех этих объединений.

Наше текущее решение: (которое Я не согласен с):

В нашем коде есть несколько жестко запрограммированных экземпляров AssetClass со всеми соответствующими значениями и идентификаторами (например, Equity с Id 1, Bond с Id 2 и т. Д.), Которые соответствуют тому, что находится в базе данных. :

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");
}

Мы также создали специальный тип NHibernate (код ниже, если вам интересно), который позволяет нам избежать NHibernate, выполняющего соединение, путем загрузки этого жестко запрограммированного экземпляра вместо обращения к базе данных для его получения:

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<T> : PrimitiveType where T : class, IUniquelyNamed, IIdentifiable
    {
        private readonly PrimitiveTypeFactory<T> _factory;

        public PrimitiveTypeBase() : base(SqlTypeFactory.Int32)
        {
            _factory = new PrimitiveTypeFactory<T>();
        }

        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();
        }
    }
}

Мое решение : (с чем я согласен: -))

Замена этих сущностей на перечисления, и если нам когда-нибудь понадобится поле описания, используйте атрибут. У нас также может быть ограничение на базу данных, чтобы убедиться, что вы не можете хранить случайные значения, не соответствующие перечислению.

Их аргумент против использования перечислений:

  • Это не объект, поэтому вы не можете расширить его, он не объектно-ориентированный и т. д.
  • Вы не можете легко получить описание или иметь "правильные английские" имена (с пробелами или символами), такие как "My Value" (которое в перечислении будет "MyValue" ")
  • Перечисления отстой
  • Атрибут отстой

Мой аргумент против нашего текущего решения:

  • У нас может быть несоответствие между идентификаторами в коде и тем, что находится в базе данных
  • Это намного сложнее поддерживать (мы должны быть абсолютно уверены, что все жестко запрограммированные значения, которые у нас есть, также присутствуют в базе данных)
  • Атрибуты и перечисления не плохи при правильном использовании и для статических значений, подобных этим
  • Для «правильных английских» имен , мы также можем использовать атрибут с некоторым методом расширения для его использования.

А что ВЫ думаете?

7
задан Antoine Jaussoin 19 August 2011 в 09:02
поделиться