Дизайн класса: индексированный список или несколько свойств? - PullRequest
1 голос
/ 31 июля 2009

Время от времени я сталкиваюсь с этим во время проектирования класса ... когда у меня есть несколько свойств одного типа в объекте. Возьмите несколько примеров:

У пользователя несколько адресов. Мы можем сделать

IDictionary<string, Address> Addresses; // Addresses["BusinessAddress"];

или

Address BusinessAddress; 
Address ShippingAddress;

Продукт имеет родственные продукты, по разным категориям. Мы можем сделать

IDictionary<string, IList<Product>> Related; // Related["Available"];

или

IList<Product> Available;
IList<Product> Required;

Пользователю назначено несколько ролей. Мы можем сделать

IList<Role> Roles;

или

bool IsAdmin;
bool IsSales;

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

public class ProductCategories { public static string Available = "Available"; }

Но все же гораздо хуже читать «product.Available», чем «product.Related [ProductCategories.Available]».

Существуют и другие соображения, например, что проще / лучше сопоставить с ORM (например, NHibernate).

Но вопрос в том, есть ли известные предпочтения? Дизайн статей и / или книг на эту тему? Реальные мировые практики, которые люди здесь испытали?

Например, мы можем объединить оба мира ... пусть IList и bool IsAdmin делают "return Roles.Contain (Role (" Admin "));". Но это выглядит уродливо для меня.

Или, в случае IDictionary, мы не можем иметь более 1 адреса на тип; и если мы сделаем

IDictionary<string, IList<Address>>

это сходит с ума по простым адресам, где нам не нужны множители. Но если мы используем BillingAddress, ShippingAddress и IList для MultipleAddress, у нас будет гораздо более детальный контроль над нашими адресами ... с Intellisense и т. Д.

Ответы [ 2 ]

1 голос
/ 31 июля 2009

Поскольку вы упоминаете доменно-управляемый дизайн (DDD), книга с тем же названием содержит рекомендации для Интерфейсы выявления намерений . Наличие диктонары объектов Domain ни в коем случае не является показателем намерений, поэтому по одной этой причине я настоятельно рекомендую не использовать словари.

Словари в основном следует использовать для предоставления API, где вызывающие абоненты будут иметь возможность добавлять и извлекать значения, или для API-интерфейсов инфраструктуры очень общего назначения, где вам нужно иметь возможность работать с очень гибким набором ситуаций.

Это не относится к DDD. Представьте, что вы не написали этот класс самостоятельно, а затем включили свойство «Адреса на основе словаря» из своего примера. Как бы вы узнали, какие типы адресов он содержит? Вам придется взглянуть на код реализации или прочитать документацию.

Если, с другой стороны, у вас есть свойство BusinessAddress и свойство ShippingAddress, для потребителя API сразу становится ясно, что доступно.

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

Если вам действительно нужен Словарь (или, лучше, список), потому что иногда вам нужно перебирать все адреса (или что-то еще), вы можете сделать это, выставив свойство только для чтения, которое предоставляет перечислитель обоим - что-то вроде это:

public Address BusinessAddress { get; set; }
public Address ShippingAddress { get; set; }

public IEnumerable<Address> Addresses
{
    yield return this.BusinessAddress;
    yield return this.ShippingAddress;
}
0 голосов
/ 31 июля 2009

Это зависит. Если вашему приложению нужно разрешить пользователям добавлять адреса, то обязательно используйте словарь Address es.

...