Это - определенный загруженный вопрос, но я склонен соглашаться, что огромные суммы конфигурации XML действительно не составляют много преимущества. Мне нравится, когда мои приложения максимально легки на зависимостях, включая значительные платформы.
Они упрощают код много времен, но у них также есть издержки в сложности, которая делает разыскивание проблем довольно трудным (я видел такие проблемы на собственном опыте и прямой Java, я был бы намного более удобным контактом с).
я предполагаю, что это зависит от стиля немного, и чем Вы довольны..., Вам нравится управлять Вашим собственным решением и обладать преимуществом очень хорошо знания его или полагаться на существующие решения, которые могут оказаться трудными, когда конфигурация не является просто правильной? Это - весь компромисс.
Однако конфигурация XML является определенным моим главным объектом неприязни... Я стараюсь избегать его любой ценой.
Я полагаю, что некоторые из этих свойств, вероятно, связаны друг с другом. Я могу предположить, что, вероятно, существуют группы свойств, которые определяют независимые аспекты счета-фактуры, которые имеют смысл как группа.
Вы можете рассмотреть возможность создания индивидуальных интерфейсов, которые моделируют различные аспекты счета-фактуры. Это может помочь определить методы и свойства, которые работают с этими аспектами, более согласованным и легким для понимания образом.
Вы также можете комбинировать свойства, имеющие определенное значение (адреса, местоположения, диапазоны и т. Д.), В объекты которые вы агрегируете, а не как отдельные свойства одного большого класса.
Имейте в виду, что абстракция, которую вы выбираете для моделирования проблемы, и абстракция, необходимая для связи с какой-либо другой системой (или бизнес-процессом), не обязательно должны быть одинаковыми. Фактически, часто бывает продуктивно применять шаблон моста , чтобы позволить отдельным абстракциям развиваться независимо.
если ничего не помогает, по крайней мере разделите класс на несколько частичных классов, чтобы было удобнее читать. это также облегчит команде параллельную работу над разными частями этого класса.
удачи :)
Словарь? почему бы и нет, но не обязательно. Я вижу тег C #, у вашего языка есть отражение, хорошо для вас. В моем коде Python было несколько таких слишком больших классов, и отражение мне очень помогает:
If an entity has a hundred unique attributes than a single class with a hundred properties is the correct thing to do.
It may be possible to split things like addresses into a sub class, but this is because an address is really an entity in itself and easily recognised as such.
A textbook (i.e. oversimplified not usable in the real world) invoice would look like:-
class invoice:
int id;
address shipto_address;
address billing_address;
order_date date;
ship_date date;
.
.
.
line_item invoice_line[999];
class line_item;
int item_no.
int product_id;
amt unit_price;
int qty;
amt item_cost;
.
.
.
So I am surpised you dont have at least an array of line_items in there.
Get used to it! In the business world an entity can easily have hundreds and sometimes thousands of unique attributes.
Вы можете попробовать LINQ, он автоматически сгенерирует свойства. Если все поля распределены по нескольким таблицам, и вы можете создать представление и перетащить его в свой дизайнер.
Похоже, для конечного результата вам нужно создать объект счета-фактуры примерно со 100 свойствами. У вас есть 100 таких объектов на каждый случай? Возможно, вам понадобится фабрика, класс, который будет выставлять счет с меньшим набором параметров. Для каждого сценария, в котором релевантны соответствующие поля счета-фактуры, можно добавить другой заводской метод.
Я использовал Dictionary
он поставляется с целым набором функций, которые могут его обрабатывать, его легко преобразовывать в другие структуры, легко хранить и т. Д.
Вы не должны руководствоваться чисто эстетическими соображениями.
Согласно вашим комментариям, объект в основном является объектом передачи данных, используемым устаревшей системой, которая ожидает наличия всех полей.
Если нет реальной ценности в создании этого объекта из частей, что именно достигается за счет сокрытия его функции и назначения?
Это могут быть веские причины:
1 - Вы собираете информацию для этого объекта из различных системы и части относительно независимы. В этом случае имеет смысл составить окончательный объект, исходя из соображений процесса.
2 - У вас есть другие системы, которые могут использовать различные подмножества полей этого объекта. Здесь повторное использование является мотивирующим фактором.
3 - Существует вполне реальная возможность создания системы выставления счетов следующего поколения, основанной на более рациональной конструкции. Здесь расширяемость и эволюция системы являются мотивирующим фактором.
Если ни одно из этих соображений не применимо к вашему случаю, тогда в чем смысл?
Хммм ... Все ли они действительно имеют отношение конкретно , а только к счету? Обычно я видел что-то вроде:
class Customer:
.ID
.Name
class Address
.ID
.Street1
.Street2
.City
.State
.Zip
class CustomerAddress
.CustomerID
.AddressID
.AddressDescription ("ship","bill",etc)
class Order
.ID
.CustomerID
.DatePlaced
.DateShipped
.SubTotal
class OrderDetails
.OrderID
.ItemID
.ItemName
.ItemDescription
.Quantity
.UnitPrice
И все это связывает:
class Invoice
.OrderID
.CustomerID
.DateInvoiced
При печати счета объедините все эти записи вместе.
Если вы действительно должны иметь один класс с более чем 100 свойствами, может быть лучше использовать словарь
Dictionary<string,object> d = new Dictionary<string,object>();
d.Add("CustomerName","Bob");
d.Add("ShipAddress","1600 Pennsylvania Ave, Suite 0, Washington, DC 00001");
d.Add("ShipDate",DateTime.Now);
....
Идея здесь состоит в том, чтобы разделить ваш на логические единицы. В приведенном выше примере каждый класс соответствует таблице в базе данных. Вы можете загрузить каждый из них в специальный класс на уровне доступа к данным или выбрать их с помощью объединения из таблиц, в которых они хранятся, при создании отчета (счета-фактуры).
Было бы слишком много столбцов, если бы ваш класс / таблица, в которой вы их храните, начинает нарушать правила нормализации.
По моему опыту, было очень трудно получить такое количество столбцов при правильной нормализации. Примените правила нормализации к широкой таблице / классу, и я думаю, у вас будет меньше столбцов на объект.
Если ваш код действительно не использует многие из атрибутов во многих местах, я бы вместо этого взял словарь.
Наличие реальных свойств имеет свои преимущества (тип- безопасность, обнаруживаемость / интеллигентность, возможность рефакторинга), но это не имеет значения, если весь код получает их из другого места, отображает в пользовательском интерфейсе, отправляет в веб-службу, сохраняет в файл и т. д.
Это считается плохим ОО-стилем, но если все, что вы делаете, это заполняете объект свойствами, чтобы передать их для обработки, и обработка только считывает свойства (предположительно для создания какого-то другого объекта или обновления базы данных), возможно, вам нужен простой объект POD, имеющий все общедоступные члены, конструктор по умолчанию и никаких других методов-членов. Таким образом, вы можете рассматривать его как контейнер свойств, а не как полноценный объект.
Вы можете попытаться «нормализовать» его, как таблицу базы данных. Может быть, поместите все свойства, связанные с адресом, в класс Address
, например, - затем добавьте свойство BillingAddress
и MailingAddress
типа Address
в свой Счет-фактура
класс. Эти классы могут быть повторно использованы и позже.
В этой статье вы можете найти несколько полезных идей о свойствах, названных Стивом Йегге. универсальный шаблон дизайна .
Всегда ли вам нужны все возвращаемые свойства? Можете ли вы использовать проекцию с любым классом, потребляющим данные, и генерировать только те свойства, которые вам нужны в данный момент.
Очевидно, что неправильный дизайн присутствует в системе, которую вы отправляете - ни один счет-фактура не содержит более 100 свойств, которые нельзя сгруппировать в подструктуру. Например, в счете-фактуре будет клиент, а у клиента - идентификатор и адрес. Адрес, в свою очередь, будет содержать улицу, почтовый индекс и т. Д. Но все эти свойства не должны напрямую относиться к счету-фактуре - в счете-фактуре нет идентификатора клиента или почтового индекса.
Если вам нужно создать класс счета-фактуры со всеми этими свойствами, непосредственно прикрепленными к счету-фактуре, я предлагаю создать чистый дизайн с несколькими классами для клиента, адреса и всего прочего, а затем просто оберните этот хорошо спроектированный граф объектов толстым классом счетов-фактур, не имеющим хранилища и самой логики, просто передавая все операции графу объектов позади.
Если вы пытаетесь создать шлюз таблиц для уже существующей таблицы из 100 столбцов для этой другой службы, список или словарь могут быть довольно быстрым способом начать работу. Однако, если вы принимаете входные данные из большой формы или мастера пользовательского интерфейса, вам, вероятно, придется проверить содержимое перед отправкой в удаленную службу.
Простой DTO может выглядеть так:
class Form
{
public $stuff = array();
function add( $key, $value ) {}
}
Шлюз таблиц может быть больше похоже на:
class Form
{
function findBySubmitId( $id ) {} // look up my form
function saveRecord() {} // save it for my session
function toBillingInvoice() {} // export it when done
}
И вы можете довольно легко расширить это в зависимости от того, есть ли у вас варианты счета. (Может оказаться целесообразным добавление метода validate () для каждого подкласса.)
class TPSReport extends Form {
function validate() {}
}
Если вы хотите отделить свой DTO от механизма доставки, поскольку механизм доставки является общим для всех ваших счетов, это может быть легко. Однако вы можете оказаться в ситуации, когда существует бизнес-логика в отношении успеха или неудачи счета. И здесь я, наверное, ухожу в сорняки. Но именно здесь и ОО-модель может быть полезной ... Я заплачу копейки, что будут разные счета и разные процедуры для разных счетов, а если представление счетов не работает, вам понадобятся дополнительные процедуры: -)
class Form {
function submitToBilling() {}
function reportFailedSubmit() {}
function reportSuccessfulSubmit() {}
}
class TPSReport extends Form {
function validate() {}
function reportFailedSubmit() { /* oh this goes to AR */ }
}
Примечание Дэвид Лайвлис отвечает: это хорошее понимание. Часто поля в форме представляют собой собственные структуры данных и имеют свои собственные правила проверки. Таким образом, вы можете довольно быстро моделировать составные объекты. Это позволит связать каждый тип поля с его собственными правилами проверки и обеспечить более строгую типизацию.
Если вам действительно нужно пройти проверку, часто бизнес-правила представляют собой совершенно иное моделирование, нежели формы или DTO, которые их предоставляют. Вы также можете столкнуться с логикой, ориентированной на отделы и имеющей мало общего с формой. Важно исключить это из проверки самой формы и процесса (ов) отправки модели.
Если вы организуете схему за этими формами, вместо таблицы со 100 столбцами, вы, вероятно, разбейте записи по идентификаторы полей и значения всего в несколько столбцов.
table FormSubmissions (
id int
formVer int -- fk of FormVersions
formNum int -- group by form submission
fieldName int -- fk of FormFields
fieldValue text
)
table FormFields (
id int
fieldName char
)
table FormVersions (
id
name
)
select s.* f.fieldName from FormSubmissions s
left join FormFields f on s.fieldName = f.id
where formNum = 12345 ;
Я бы сказал, что это определенно тот случай, когда вы захотите пересмотреть свой подход, пока не найдете что-то удобное. Надеюсь, у вас есть некоторый контроль над такими вещами, как схема и ваша объектная модель. (Кстати ... эта таблица известна как `` нормализованная ''? Я видел варианты этой схемы, обычно организованные по типу данных ...