Design Question: Which is Better practice? (part 2)
I've got a web interface from which I will gather user data (username,pass,email,etc..) and the backend has to provision these data into 3 other systems (SystemA, SystemB, SystemC).
The provisioning is being done by 3 different APIs one for each system (A,B and C).
My current design in the backend looks something like this:
interface ProvisionData
{
public function createUser();
public function deleteUser();
public function changePassword();
}
class SystemA_API_wrapper implements ProvisionData
{
public function createUse开发者_JAVA技巧r(){ ... }
public function deleteUser(){ ... }
public function changePassword(){ ... }
}
class SystemB_API_wrapper implements ProvisionData
{
public function createUser(){ ... }
public function deleteUser(){ ... }
public function changePassword(){ ... }
}
class SystemC_API_wrapper implements ProvisionData
{
public function createUser(){ ... }
public function deleteUser(){ ... }
public function changePassword(){ ... }
}
Each of the System*_API_wrapper has different implementation of createUser() (and the rest) functions.
In the frontend I've created a kind of proxy class which I feed with the data gathered from the web interface.. It looks like:
class provisionProxy
{
public $sA = null;
public $sB = null;
public $sC = null;
//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);
}
}
Does anyone have any suggestion or a better practice?
(I've already posted the same question but due to technical problems I can't login to my old account, so the question is revised and posted again under my new account. Original question can be found here: Design Question: Which is Better practice? - thanks)
Based on the assumption that you can't change your three backend systems to all access a central system for user management (which would be better), the only change I would suggest is for your proxy, where you are hard coding calls to each of your three systems - it would be better to create a list of ProvisionData objects in your constructor and then in your delete/create calls, loop through that list and call the appropriate method on each.
This means that if, at some point in the future, you have to add system D to this, then that can be done with a change in a single place.
(My PHP skills are a bit ropy, so won't attempt to provide the code).
The design looks good, but adding all ProvisionData
objects to a list as suggested by Paddy is absolutely must if you want to get any sort of benefits out of your abstraction. That applies even if the three external systems are fixed and will never change. Additionally, separating the operation
to be performed from the object that performs it (aka Command pattern) will make transactional support and undo behavior possible.
Consider this example - Since you would require consistency of data across all your systems, there will be some sort of transactions involved is my guess. If there's a createUser()
operation and one system is down, you wouldn't want the user to be created on the other two systems, so the entire operation should fail from your proxy's point of view. It's easier to deal with these operations in a list vs individually checking each item. With a list, in pseudocode:
/*
* 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);
}
A list basically allows grouping external subsystems as a whole thus adding another level of abstraction for yourself, and operations such as all
and any
start making a lot of sense than individual checks. Separating the operation adds further benefits.
You can use Observer pattern for making your frontend data be processable by backend systems independently from their number, which might change.
精彩评论