Я признаю, что я не тестировал много модулей... но я бы хотел. С учетом сказанного, у меня очень сложный процесс регистрации, который я бы хотел оптимизировать для более легкого модульного тестирования. Я ищу способ структурирования своих классов, чтобы я мог легче их протестировать в будущем. Вся эта логика содержится в рамках MVC, поэтому вы можете предположить, что контроллер является корневым где все создается из.
Чтобы упростить, я задаю вопрос, как настроить систему, в которой вы можете управлять любым количеством сторонних модулей с обновлениями CRUD. Эти сторонние модули - все RESTful API, и данные ответа хранятся в локальных копиях. Что-то вроде удаления учетной записи пользователя должно было бы инициировать удаление всех связанных модулей (которые я называю поставщиками). Эти поставщики могут иметь зависимость от другого провайдера, поэтому порядок удаления/создания важен. Мне интересно, какие шаблоны проектирования я должен использовать для поддержки моего приложения.
Регистрация охватывает несколько классов и хранит данные в нескольких таблицах db. Здесь порядок разных поставщиков и методов (они не статики, просто написаны так для краткости):
-
Provider::create('external::create-user')
инициирует регистрацию на определенном этапе конкретного провайдера. Синтаксис двойного двоеточия в первом параметре указывает, что класс должен инициировать создание наproviderClass::providerMethod
. Я сделал общее предположение, чтоProvider
будет интерфейсом с методамиcreate()
,update()
,delete()
, которые все остальные провайдеры будут реализовывать. Как это создается, скорее всего, вам нужно помочь. -
$user = Provider_External::createUser()
создает пользователя во внешнем API, возвращает успех, и пользователь получает его в моей базе данных. -
$customer = Provider_Gapps_Customer::create($user)
создает клиента в стороннем API, возвращает успех и сохраняет локально. -
$subscription = Provider_Gapps_Subscription::create($customer)
создает подписку, связанную с ранее созданным клиентом в стороннем API, возвращает успех и сохраняет локально. -
Provider_Gapps_Verification::get($customer, $subscription)
извлекает строку из внешнего API. Эта информация хранится локально. Другой звонок, который я пропускаю, чтобы держать вещи краткими. -
Provider_Gapps_Verification::verify($customer, $subscription)
выполняет внешний процесс проверки API. Результат которого хранится локально.
Это действительно подавленный образец, поскольку фактический код использует по меньшей мере 6 внешних вызовов API и более 10 локальных строк базы данных, созданных во время регистрации. Не имеет смысла использовать инъекцию зависимостей на уровне конструктора, потому что мне может потребоваться создать экземпляр 6 классов в контроллере, не зная, нужны ли они мне всем. То, что я хочу выполнить, было бы чем-то вроде Provider::create('external')
, где я просто указываю начальный шаг, чтобы начать регистрацию.
Ключ проблемы
Итак, как вы можете видеть, это всего лишь один образец процесса регистрации. Я строю систему, в которой у меня могло бы быть несколько сотен поставщиков услуг (внешние модули API), которые мне нужно для регистрации, обновления, удаления и т.д. Каждый из этих провайдеров связан с учетной записью пользователя.
Я хотел бы создать эту систему таким образом, чтобы указать порядок операций (шагов) при запуске создания нового поставщика. Другими словами, позвольте мне указать, какая комбинация провайдеров/методов запускается следующей в цепочке событий, поскольку создание может охватывать так много шагов. В настоящее время у меня есть эта цепочка событий, происходящих через шаблон subject/observer. Я хочу потенциально переместить этот код в таблицу базы данных, provider_steps
, где я перечисляю каждый шаг, а также следующий success_step
и failure_step
(для откатов и удалений). Таблица выглядит следующим образом:
# the id of the parent provider row
provider_id int(11) unsigned primary key,
# the short, slug name of the step for using in codebase
step_name varchar(60),
# the name of the method correlating to the step
method_name varchar(120),
# the steps that get triggered on success of this step
# can be comma delimited; multiple steps could be triggered in parallel
triggers_success varchar(255),
# the steps that get triggered on failure of this step
# can be comma delimited; multiple steps could be triggered in parallel
triggers_failure varchar(255),
created_at datetime,
updated_at datetime,
index ('provider_id', 'step_name')
Здесь так много решений... Я знаю, что я должен одобрять композицию над наследованием и создавать некоторые интерфейсы. Я также знаю, что мне, вероятно, понадобятся фабрики. Наконец, у меня много дерьмовой модели домена, которая здесь происходит... поэтому мне, вероятно, нужны классы бизнес-домена. Я просто не уверен, как собрать их всех вместе, не создавая полного беспорядка в моем стремлении к святому Граалю.
Кроме того, где было бы лучшее место для запросов db?
У меня уже есть модель для каждой таблицы базы данных, но мне интересно знать, где и как создавать экземпляры конкретных методов модели.