Вопрос о дизайне: Какая практика лучше? (часть 2) - PullRequest
2 голосов
/ 12 января 2010

У меня есть веб-интерфейс, с которого я буду собирать пользовательские данные (имя пользователя, пароль, электронная почта и т. Д.), И бэкэнд должен предоставлять эти данные в 3 другие системы (SystemA, SystemB, SystemC).

Предоставление выполняется 3 различными API, по одному для каждой системы (A, B и C).

Мой текущий дизайн в бэкэнде выглядит примерно так:

<code>
interface ProvisionData
{
    public function createUser();
    public function deleteUser();
    public function changePassword();<br>
}

<code>
class SystemA_API_wrapper implements ProvisionData
{
    public function createUser(){ ... }
    public function deleteUser(){ ... }
    public function changePassword(){ ... }
}</p>

<p>class SystemB_API_wrapper implements ProvisionData
{
    public function createUser(){ ... }
    public function deleteUser(){ ... }
    public function changePassword(){ ... }
}</p>

<p>class SystemC_API_wrapper implements ProvisionData
{
    public function createUser(){ ... }
    public function deleteUser(){ ... }
    public function changePassword(){ ... }
}

Каждый из System * _API_wrapper имеет различную реализацию функций createUser () (и остальных).

Во внешнем интерфейсе я создал своего рода прокси-класс, который я передаю с помощью данных, собранных из веб-интерфейса. Это выглядит так:


class provisionProxy
{
    public $sA = null;
    public $sB = null;
    public $sC = null;</p>

<pre><code>//constructor instantiates all System*_API_wrapper objects
public function __construct() {        
     $sA = new SystemA_API_wrapper();
     $sB = new SystemB_API_wrapper();
     $sC = new SystemC_API_wrapper();
}

// proxy function deleteUser calls deleteUser() of each of 
// our APIs 
public function deleteUser($username, $password) {
     $this->sA->deleteUser($username, $password);         
     $this->sB->deleteUser($username, $password);
     $this->sC->deleteUser($username, $password);
}

}

У кого-нибудь есть какие-либо предложения или лучшая практика?

(Я уже отправил тот же вопрос, но из-за технических проблем не могу войти в свою старую учетную запись, поэтому вопрос отредактирован и снова опубликован под моей новой учетной записью. Исходный вопрос можно найти здесь: Вопрос о дизайне: Какая практика лучше? - спасибо)

Ответы [ 3 ]

3 голосов
/ 12 января 2010

Исходя из предположения, что вы не можете изменить свои три бэкэнд-системы на все, чтобы получить доступ к центральной системе управления пользователями (что было бы лучше), единственное изменение, которое я бы предложил, это для вашего прокси, где вы жестко программируете для каждой из ваших трех систем - было бы лучше создать список объектов ProvisionData в вашем конструкторе, а затем в вызовах delete / create выполнить цикл по этому списку и вызвать соответствующий метод для каждой.

Это означает, что если в какой-то момент в будущем вам придется добавить к этому систему D, то это можно сделать с помощью изменения в одном месте.

(Мои навыки PHP немного нелепы, поэтому я не буду пытаться предоставить код).

1 голос
/ 13 января 2010

Дизайн выглядит хорошо, но добавление всех ProvisionData объектов в список, как это было предложено Пэдди, абсолютно необходимо, если вы хотите получить какие-либо преимущества от своей абстракции. Это применимо, даже если три внешние системы являются фиксированными и никогда не изменятся. Кроме того, отделение operation, которое должно быть выполнено, от объекта, который его выполняет (он же шаблон команды ), сделает возможным поддержку транзакций и отмену поведения.

Рассмотрим этот пример. Так как вам потребуется согласованность данных во всех ваших системах, я предполагаю, что в них будут участвовать какие-то транзакции. Если есть операция createUser() и одна система не работает, вы не хотели бы, чтобы пользователь создавался в двух других системах, поэтому вся операция должна завершиться неудачей с точки зрения вашего прокси. С этими операциями легче иметь дело, чем с индивидуальной проверкой каждого элемента. Со списком, в псевдокоде:

/*
 * systems object represents a list of systems
 * execute() and undo() are methods in the systems object
 * 
 * result represents the result of performing an operation on some systems
 * successfulSystems represents systems in which the operation was successful
 */
operation = new Operation("createUser", ["param 1", "param 2", ..])
result = systems.execute(operation);
// if operation failed in any of the systems
if(result.FAILURE) {
    // then undo the operation on systems where it did succeed
    result.successfulSystems.undo(operation);
}

Список в основном позволяет группировать внешние подсистемы в целом, добавляя, таким образом, еще один уровень абстракции для себя, и такие операции, как all и any, начинают иметь больше смысла, чем отдельные проверки. Разделение операции добавляет дополнительные преимущества.

0 голосов
/ 13 января 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...