Паттерн voter injection: взаимодействие без хардкода

В моей практике часто возникают ситуации, когда в программе один объект должен определённым образом реагировать на другие объекты. То есть – решать, взаимодействовать с ними или игнорировать. Например, когда объект принимает сообщения от других объектов, и должен решать – отреагировать на конкретное сообщение или пропустить его. Понятно, что в простейшем случае достаточно это захардкодить: допустим, объект user реагирует на все сообщения про этого юзера. Но что делать, если ситуация сложнее, и реакции должны быть динамическими? (например, если ваши объекты порождаются фабрикой). Для этого у меня есть некий паттерн, который я называю voter injection. Continue reading “Паттерн voter injection: взаимодействие без хардкода”

Customer-driven dependency injection: отдаём поток выполнения программы в руки клиенту

Многие из вас знакомы с паттернами снижения “сильносвязанности” кода программного продукта, такими как внедрение зависимостей. В качестве простого примера – объект класса Logger, который не указан явно, а подсовывается в ходе выполнения кода. В зависимости от задач, условий, текущего окружения и так далее – конфигурирование позволяет подсунуть в нужное место тот или иной логгер – и писать хоть в файлы, хоть в базу, хоть в очередь rabbitmq. Вам достаточно делать Logger.write(data), и дальше алгоритм конкретного внедрённого обработчика будет применён к указанным данным.

Однако мы все привыкли обманываться, считая имеющееся у нас “dependency injection” отличным способом понизить связанность. Да, мы убрали алгоритмы во внедряемые компоненты, но мы по-прежнему задаём их либо в коде, либо в аннотациях (в случае PHP/Symfony), либо в конфигурационных файлах окружения. И мне не давала покоя мысль – как отдать такое конфигурирование в руки клиенту (другими словами – сделать его управляемым “на ходу”), при этом не применяя костылирование и не изобретая велосипед. В этом посте я хочу поделиться с вами паттерном, решающим эту задачу, который мне почему-то не встретился в литературе, но его удалось наработать в ходе локальных экспериментов. Continue reading “Customer-driven dependency injection: отдаём поток выполнения программы в руки клиенту”