Исключительные бросаемые конструкторы и инициализация. Лучшая практика - PullRequest
1 голос
/ 13 июля 2010

У меня есть класс DataProvider (DAL), для которого в качестве параметра требуется год. Используется так:

using (var provider = new DataProvider(year))
{
   provider.SomeRepostitory.DoSomethingUsefull(); 
}

Код конструктора DataProvider имеет дело с конфигурацией, поэтому он может генерировать исключения. И исключение бросаемых конструкторов не рекомендуется. Поэтому я добавил метод Init и поместил туда весь бросаемый код:

var provider = new DataProvider();
provider.Init(year);

Но теперь есть две строки кода вместо одной, и, поскольку поставщик многократно создавал код, я поместил эти две строки в статический метод Fabric:

using (var provider = DataProvider.Create(year))
{
  ...
}

Это нормально или есть лучшее решение?

Заранее спасибо!

Ответы [ 4 ]

3 голосов
/ 13 июля 2010

Код конструктора DataProvider имеет дело с конфигурацией, поэтому он может генерировать исключения.И конструкторы с исключительными исключениями не рекомендуются.

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

Конструктор, генерирующий исключение, является гораздо лучшим API для программирования, чем использование отдельного метода инициализации (лично я ненавижу двухфазную инициализацию; второй вызов так легко забыть).Если нет веской причины избегать этого, я бы просто сделал проверки в конструкторе.

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

2 голосов
/ 13 июля 2010

Я думаю, что вполне разумно иметь фабричный метод, который выполняет некоторую инициализацию объекта. Если вы не должны использовать объект без инициализации, сделайте конструктор частным (или защищенным), чтобы только статический метод в классе мог вызывать конструктор.

0 голосов
/ 13 июля 2010

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

0 голосов
/ 13 июля 2010

Вы можете получить метод Init, возвращающий this, если хотите объединить вызовы. Как:

var provider = new DataProvider().Init(year);

Но если у вас есть для вызова .Init(), тогда стиль фабричного метода может быть более полезным.

...