Хорошо, вот проблема, с которой я сталкиваюсь.
В моем приложении есть классы, в которых есть методы, требующие подключения к базе данных. Я разрываюсь между двумя разными способами разработки классов, оба из которых сосредоточены вокруг внедрения зависимости:
Предоставить свойство для соединения, которое устанавливается вызывающей стороной до вызова метода. Это имеет несколько недостатков.
Каждый метод, полагающийся на свойство соединения, должен проверять это свойство, чтобы убедиться, что оно не равно нулю, оно открыто и не участвует в транзакции, если собирается испортить операцию.
Если свойство соединения неожиданно закрыто, все методы должны либо (1.) вызвать исключение, либо (2.) принудительно открыть его. В зависимости от того, какой уровень надежности вы хотите, подходит любой из этих вариантов. (Обратите внимание, что это отличается от соединения, которое передается методу тем, что ссылка на соединение существует в течение всего времени жизни объекта, а не просто в течение времени жизни вызова метода. Следовательно, изменчивость соединения просто кажется выше для меня.)
Предоставление свойства Connection
кажется (во всяком случае, мне) кричать о соответствующем Transaction
свойстве. Это создает дополнительные накладные расходы в документации, так как вам придется сделать это довольно очевидным, когда транзакция использовалась, а когда - нет.
С другой стороны, Microsoft, похоже, поддерживает всю парадигму установки и запуска.
Требовать, чтобы соединение передавалось в качестве аргумента методу. Это имеет несколько преимуществ и недостатков:
Список параметров, естественно, больше. Это утомительно для меня, в первую очередь в точке вызова.
Хотя соединение (и транзакция) все еще должны быть проверены перед использованием, ссылка на него существует только на время вызова метода.
Точка вызова, однако, совершенно ясна. Совершенно очевидно, что вы должны предоставить соединение, и что метод не будет автоматически создавать его за вашей спиной.
Если метод не требует транзакции (скажем, метод, который только извлекает данные из базы данных), транзакция не требуется. Отсутствует ясность из-за сигнатуры метода.
Если для метода требуется транзакция, очень сбрасывается из-за сигнатуры метода. Опять же, нет недостатка в ясности.
Поскольку класс не предоставляет свойства Connection
или Transaction
, у вызывающих абонентов нет никаких попыток развернуть их до свойств и методов, что обеспечит соблюдение закона Деметры.
Я знаю, это много. Но, с одной стороны, есть Microsoft Way: предоставить свойства, позволить вызывающей стороне установить свойства, а затем вызвать методы. Таким образом, вам не нужно создавать сложные конструкторы или фабричные методы и тому подобное. Также избегайте методов с большим количеством аргументов.
Тогда есть тот простой факт, что, если я выставлю эти два свойства на своих объектах, они будут склонны поощрять потребителей использовать их гнусным образом. (Не то, чтобы я отвечал за это, но все же.) Но я просто не хочу писать дерьмовый код.
Если бы вы были на моем месте, что бы вы делали?