2

I have to program a generic client that uses diverse concrete clients (diverse APIs), all sharing the same interface. I have to log the response of the client.

To accomplish this (logging in background without user having to manually do it), I created these classes:

Request, Response, ClientService, Client1, Client2, ClientInterface.

So, you instantiate ClientService and set the client name, example:

$client = $this->get('clientService')->setClient('client1');

// $data is an associative array
$request = $client->createRequest($data); 

// $response was saved to database by ClientService, before returning it.
$response = $client->doRequest($request); 

ClientService, Client1 and Client2 implements ClientInterface, which has methods doRequest(), createRequest(), getError(), etc, but all ClientService implementation does is to forward the request to the actual client.

I did this to be able to save the response to database automatically, and for this to happen without having to repeat code in all the clients, and to let this concern be in the service, it had to have control over the whole request/response lifecycle.

I wonder if there is a pattern that already describes this scenario.

  • Ok, I see it's not. That set is the one introduced in your previous question – Laiv Dec 15 '16 at 7:28
1

Based on what you are showing the Client class is handling requests, response, database access, and pretty much everything, is a Blob Class which is an anti pattern. So my suggestion is:

  1. Use some pattern like MVC MVP or else to handle the request.
  2. Delegate your database access using DAO pattern, maybe with pdo, or an Active Record.
  3. ClientService should only be acting on the business layer, wrapping several database calls, and abstracting the DAL. Therefore it should implement the Client interface.
  4. Define a good inheritance implementation, if really needed, for Client1 and Client2 classes, and based on that establish you db model. That will enlighten if you need different implementation of the Database Access pattern of your choosing.

Please note that this is fully based on what you posted, maybe with more code, we could be more useful.

1

I created a pattern/implementation I call AdaptiveClient. The code is too lengthy to post here. You can read about it on my website or download on github.

Just as your question describes, AdaptiveClient returns a client that implements a requested interface. So if you want to call a method such as doRequest(request) and have it execute on the optimal server that is currently available you may do it like this:

public class HomeController : Controller
{
    private IAdaptiveClient<IUsersService> client;

    public HomeController(IAdaptiveClient<IUsersService> client)
    {
        this.client = client;
    }

    public async Task<IActionResult> DoSomething(int userID)
    {
        // use an in-process connection to the database if its available otherwise use
        // whatever server is available to handle the request (WebAPI, WCF, etc.):
        Request request = // whatever request is
        SomeThing thing = await client.CallAsync(x => x.doRequest(request));
    }
}

In code above, AdaptiveClient returns a concrete implementation of an example interface IUsersService.

AdaptiveClient allows you to architect your application as n-tier and access your API across LAN or web as necessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.