Является ли метод Initialize запахом кода? - PullRequest
15 голосов
/ 01 ноября 2011

Я сейчас кодирую кучу систем.Они не являются производными от общего интерфейса.

Некоторые примеры систем: MusicSystem, PhysicsSystem, InputSystem и т. Д.

В настоящее время MusicSystem загружает много аудиофайлы в его конструкторе и, как следствие, при первом создании объекта может быть небольшая задержка.

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

Поскольку не всем системам необходим метод Initialize(), который должен искать программистчерез каждую систему, чтобы увидеть, есть ли в классе метод Initialize() и, если да, вызвать его.Это немного громоздко.

Какой подход предпочтительнее с точки зрения общих принципов проектирования?

Ответы [ 16 ]

1 голос
/ 01 ноября 2011

Это совсем не «кодовый запах».Нередко бывает что-то подобное.Например, посмотрите на класс SqlConnection в .NET.Есть конструктор по умолчанию, который не принимает параметров, и есть конструктор, который принимает строку подключения.Тот, который принимает строку подключения, удобен, когда вы хотите подключиться к базе данных и использовать значения по умолчанию для времени ожидания подключения и т. Д. Но если вы хотите изменить эти свойства или если вы хотите иметь готовый экземпляр подключения, но контролировать большеточно, когда он подключен, вы вызываете конструктор по умолчанию, устанавливаете свойства, а затем вызываете Open, когда будете готовы установить соединение.

1 голос
/ 01 ноября 2011

Ваш конструктор может запустить фоновый поток, который выполняет загрузку. Затем все в классе, которому нужно использовать эти данные, просто проверяет, завершена ли асинхронная загрузка, и если нет, то подождите.

Это ускоряет построение классов, скрывает все детали многопоточности от ваших потребителей классов и избавляет от уродливого шаблона init.

1 голос
/ 01 ноября 2011

Если аудиофайлы всегда одинаковы.Вы можете попробовать загрузить их из статического свойства.Как только объект загружает аудио файлы.Они будут доступны всем, если список аудиофайлов хранится в статическом свойстве.

1 голос
/ 01 ноября 2011

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

Тогда вам не нужно проверять наличие специального метода.

0 голосов
/ 22 сентября 2016

Конечно, нет.Согласно указаниям MSDN, конструктор должен выполнять минимальную работу.Следовательно, такие вещи, как распределение ресурсов или инициализация тяжелых объектов, должны быть размещены где-то еще, например Initialize ().

https://msdn.microsoft.com/en-us/library/ms229060(v=vs.110).aspx

Конструкторы не должны выполнять большую работу, кроме захватапараметры конструктора.Стоимость любой другой обработки должна быть отложена до тех пор, пока не потребуется.

0 голосов
/ 01 ноября 2011

Если у вас есть «MusicSystem», которая не имеет смысла (и выражает это путем взрыва) без инициализации, у меня возникают проблемы с пониманием варианта использования для создания экземпляра этого объекта, но не для его инициализации.

Если речь идет о передаче его с места на место, я мог бы предложить взглянуть на Generic Lazy , где вы можете лениво загрузить объект.

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

Что касается запаха кода, лично я считаю методы Initialize () запахом кода. Конечно, не всегда показательно, что что-то не так, но обычно это говорит о том, что возможности для инверсии зависимости упускаются. Если мне нужно что-то создать, а затем вызвать Initialize (), мне интересно, почему я не могу создать экземпляр объекта, а затем передать ему все, что ему нужно для того, чтобы его считали инициализированным (или почему он не требует инициализированного Foo в его конструктор).

...