Application Service Layer - how to write API method interfaces - php

How do people design their service layer interfaces?
I'm programming a large web application (in PHP) and we're using MVC, and programming thin controllers e.g. (pseudo code follows)
public savePersonAction() {
$input = filter($_GET);
... input validation ...
$result = $this->_service->savePerson( ? );
... etc
}
Should savePerson in the service take an argument of the entire $input structure or context (in PHP, an associative array)?
E.g. this -
public function savePerson(array $input) {
or should one separate out all the input fields and provide a "hard" interface e.g.
public function savePerson($title, $firstName, $lastName, $dateOfBirth, ... etc.. for many more) {
Thanks.
Paul

If you're going to follow the MVC spirit your savePerson method should not accept the raw input. It shouldn't be directly coupled with the format of the data coming from the ui. Instead it should accept input defined in the terms of your service domain, like a "person" object. (This could just be an associative array like Cobby suggested). It would be the job of the controller's action method to map the raw input to the format required by the service.
The benefit of this extra translation step is that it isolates your service (model) from the ui. If you implement a different ui, you don't need to change the service interface. You just need to write new controllers (and views, of course).
While your example like savePerson($title, $firstName, $lastName...) is the right idea, it's usually a bad sign when you have methods with more than 2 or 3 arguments. You should be able to group related arguments into some kind of higher-level object.

My MVC applications are structured like this:
Controller -> Service -> ORM/other library
To answer your question, typically in your controller you will be getting form data as an array, i.e. $form->getValues() or something similar. In terms of maintainability it's best if your Services except arrays as arguments, that way if you add another field to a form, you only have to update the form and the service, your controller can remain untouched and still work.
So I think go with your first example:
public function savePerson($personArray);
Furthermore, you shouldn't need a "hard" interface because your form library will take care of validation/filteration/sanitization so we can assume that the associative array will be valid, plus the method definition will get ridiculously long with named parameters.

I would separate out all the input fields and provide a "hard" interface in Service e.g.
public function savePerson($title, $firstName, $lastName, $dateOfBirth) {...}
Its cleaner and there are no assumptions needed.

Related

Passing variables to methods with often changing parameter list

I am using a MVC model in php.
The controller is sending data to the model and sometimes it expects something back.
As I write my webpage I add utilities which needs more information from the model. Mostly it makes controller pass more arguments to the model interface. The problem is that model interface mostly only passes those variables to another methods, so the parameter list should be changed in a few places. This obviously is unacceptable so how should it be handled?
I think that passing the array of data isn't the best idea because it can make it uncontrollable. Anything could add anything to that.
Currently I am using another solution. I create special class to handle this. Every one of them derives from a class containing something like "getAsArray()" method. I think that creating a special class for nearly every controller need is a waste of time and resources so here is my question: What is the best solution to this problem? What are the common ideas?
Controller
public function addUser(){
$this->load->model("User");
$username = $this->someWayOfGettingData("username");
$email = $this->someWayOfGettingData("email");
$password = $this->someWayOfGettingData("password");
$this->User->insert($username, $email, $password);
}
Model
private function someMethodOperatingOnData($username, $email, $password){
$answer = $this->queryAdd($username, $email, $password);
return $answer;
}
public function insert($username, $email, $password){
return $this->someMethodOperatingOnData($username, $email, $password);
}
What's the problem: When I decide to add another information about user (e.g. gender) I have to update the list of parameters in
insert($username, $email, $password);
someMethodOperatingOnData($username, $email, $password);
queryAdd($username, $email, $password);
to:
insert($username, $email, $password, $gender);
someMethodOperatingOnData($username, $email, $password, $gender);
queryAdd($username, $email, $password, $gender);
So I have to update every function passing those variables. I could use an array:
insert($arrayOfData);
someMethodOperatingOnData($arrayOfData);
queryAdd($arrayOfData);
But anywhere anything can add or remove those variables and I don't want that to happed.
I can think of different strategies for this:
1) As you are currently doing, create a custom class, instantiate it with your parameters, pass it over. However, since parameter list keep changing, your plain-old-data classes are going to be moving targets, i.e. costly.
2) You can create a dictionary and put those parameters into this dictionary and pass it along. It is an anti-pattern in the OO world, but it could be a reasonable solution for you.
3) In Django world, one of the best practices is to pass the request altogether. This approach keeps your method signatures clean. This is more favorable compared to #2 above.
I hope it helps.
EDIT
I am not a PHP guy. Think about dictionaries as key value pairs. In PHP, arrays are actually key-value pairs. So, you can use arrays in PHP lingo, or Dictionaries in other languages like Smalltalk. So this option still holds, although the terminology I picked was not 100% correct, the idea or principal is still the same.
The following is an excerpt from the book named Two Scoops of Django section 9-2:
For many utility functions, we are taking an attribute or attributes
from the django.http.HttpRequest (or HttpRequest for short) object and
gathering data or per- forming operations. What we’ve found is by
having the request object itself as a primary argument, we have
simpler arguments on more methods. is means less cognitive overload
of managing function/method arguments: just pass in the HttpRequest
object!
EDIT2
I have just seen the edit you made to your question. So, from the example you gave, what seems to be happening is you have a user class. As time passes by, there might be a need to add more properties to the user class. For example, 20 years ago, there was no such property as MobilePhone, but now it is almost mandatory. So, naturally the best way is to add that member property to your User class. Instantiate it with proper data and pass the User object, not individual user properties Until you can instantiate a User Object, you can pass around the request Object as mentioned in #3, afterwards, you can use the User object. I believe this is your best route.
Cheers,

How to achieve layer separation without mixing my Repository with my API Service?

(There is a TL;DR: at the bottom)
I have a PDF produced via MVC pattern. I am working with an existing code, which was a bit of a mess, but now I am seeing a pattern emerge.
Currently, I have a Controller class, and inside I have many many separate functions, roughly one function per page. Each function does something like this:
function showPage()
{
//get some data from repository
$data1 = $this->repository->getData1();
$data2 = $this->repository->getData2();
//pass that data to the PDF API class, aka "the view"
//and the class takes care of creating PDF pages
//with the appropriate data
$this->pdfApi->showView($data, $data2);
}
The above achieves a clean separation between Repository (which only returns data), the PDF API service (which receives the data and doesn't need to care or maintain data retrieval constructs. And Controller which pretty much just asks for Data, and passes it to PDF API. And all was well until I came across this problem:
Problem
Most every page has a "footer" with a message, and a "Proposal Number" that needs to be displayed on the page. Sometimes it also has other pieces of data. Since PDF API class has no data in itself, someone has to pass that data to PDF API. I have been passing the above to pieces of information every time as part of function parameters but it became inconvenient -- there are too many parameters to pass and they are cluttering up the code.
Try at Solution
To reduce the clutter in parameter passing, In my Controller I have created pulled data (via Repository) for variables such as $footerText and $proposalNumber and then used them I populate PDF API's own class properties. Side-effect of this is that now my PDF API has the relevant bits of data embedded directly in the API (which I consider to be undesirable, since data layer now imposes into API class)
So far I have resisted the temptation to just pass the entire Repository object to PDF API because that will do very much the same - mix data layer and API Layer, plus, API layer will have unrestricted access to Data, which can also be undesirable.
Actual Problem
When I want clean layer separation, my code is cluttered with multiple function parameter passing.
When I pass the entire Repository to my API class, I mix data and API layers, and API layer gets too much freedom to use Repository class.
Can I somehow achieve layer separation without the clutter or "mixing layers" issues identified above?
If you like to see code, here is some code below of my various unsuccessful tries :)
TL;DR: My various unsuccessful tries to keep layers separate or to reduce clutter proved to be unsuccessful
//in Controller - Exhibit 1
//Separation achieved with only data parameter passing tying layers together
//but, too much clutter -- too many parameters
//maximum layer separation but lots of annoying data passing
$data1 = $this->repository->getData1();
....
$data24 = $this->repository->getData24();
$this->pdfApi->showView($data1, $data2, $data3, ... );
//in Controller - Exhibit 2
//Layers are mixed - my data is now tied into API
//in constructor
$data1 = $this->repository->getData1();
....
$data24 = $this->repository->getData24();
$this->pdfApi->setData1($data1);
$this->pdfApi->setData24($data24);
//inside function (API already has data as part of its own vars):
$this->pdfApi->showView();
//in Controller - Exhibit 3
//layers are mixed -- entire Repository got into my API
//in constructor
$repo = new Repository();
$this->pdfApi->setRepository($repo);
//inside function (API has full Repository access gets its own data and more):
$this->pdfApi->showView();
I think the Exhibit 1 is most correct.
//inside Controller
$data = array(
'data1' => $this->repository->getData1(),
//...
'data24' => $this->repository->getData4()
):
$this->pdfApi->showView($data);
I say this because a popular framework, ZF2, which I use, also ascribes to the same pattern.
//inside Controller
$data = array(
'message' => 'Hello world',
);
$view = new ViewModel($data);
In my case the View is the PDF API

Which pattern to use and how to use it when I have Controller, Business Logic, and Repository?

Using MVC I have something like this:
class Controller
{
//returns View
function indexAction()
{
$data = $this->getData($this->id);
$view = new ViewModel();
$view->setVariable('data' => $data);
//used to render HTML template + data above later on
return $view;
}
//gets data from DB
//currently also does business-proprietary computation on data
function getData($id)
{
//repository/dao pattern
$data = $this->repository->getData($id);
//Business Logic "derivation"
foreach ($data as $datum)
{
//that does not go into "Controller
//that does not go into "Repository"
//but where does it go? - that's my question
$derivedData[] = (new Business())->doLogic($datum);
}
return $derivedData;
}
}
Recap
I used Controller to get my data out of DB using Repository pattern, then placed received data into view. But business-related computations are left stranded.
Question
Where do I place my business logic computations that act on the data gotten from repository? The derived data which is to return to Controller later, to be placed into View?
My personal choices of architecture are usually to:
Have small controllers as thin as I can, doing only session and general right checking
Services that are handling all business logic, one (one classe yes) per potential feature I need
Services are querying repositories, and eventually manipulate the data in and out, but usually no Controller, nor view will do a ->save() anywhere.
This means that those services are usually designed to be independent from the database and easier to be tested because they only take care of one and only one task.
In your example, the whole function getData will be a service that I would call GetCarDataById. This assuming that you manipulate Cars, I don't like to leave data wandering alone.
EDIT: to make it clear, this kind of approach is not MVC to some definition, most people interpret MVC as putting all code either in controller, either in repositories (model). To others view, MVC doesn't mean that you have other classes, what I call services, and actually most of my code lives here.
The MVC pattern is clear for me.
From wikipedia:
The model directly manages the data, logic and rules of the
application. A view can be any output representation of information,
such as a chart or a diagram. Multiple views of the same information
are possible, such as a bar chart for management and a tabular view
for accountants. The third part, the controller, accepts input and
converts it to commands for the model or view.
Answering your question. The modifications goes in the model domain.

Controller as Service - How to pass and return values in an advanced case?

Using Symfony, I am displaying a table with some entries the user is able to select from. There is a little more complexity as this might include calling some further actions e. g. for filtering the table entries, sorting by different criteria, etc.
I have implemented the whole thing in an own bundle, let's say ChoiceTableBundle (with ChoiceTableController). Now I would like to be able to use this bundle from other bundles, sometimes with some more parametrization.
My desired workflow would then look like this:
User is currently working with Bundle OtherBundle and triggers chooseAction.
chooseAction forwards to ChoiceTableController (resp. its default entry action).
Within ChoiceTableBundle, the user is able to navigate, filter, sort, ... using the actions and routing supplied by this bundle.
When the user has made his choice, he triggers another action (like choiceFinishedAction) and the control flow returns to OtherBundle, handing over the results of the users choice.
Based on these results, OtherBundle can then continue working.
Additionally, OtherOtherBundle (and some more...) should also be able to use this workflow, possibly passing some configuration values to ChoiceTableBundle to make it behave a little different.
I have read about the "Controller as Service" pattern of Symfony 2 and IMHO it's the right approach here (if not, please tell me ;)). So I would make a service out of ChoiceTableController and use it from the other bundles. Anyway, with the workflow above in mind, I don't see a "good" way to achieve this:
How can I pass over configuration parameters to ChoiceTableBundle (resp. ChoiceTableController), if neccessary?
How can ChoiceTableBundle know from where it was called?
How can I return the results to this calling bundle?
Basic approaches could be to store the values in the session or to create an intermediate object being passed. Both do not seem particularly elegant to me. Can you please give me a shove in the right direction? Many thanks in advance!
The main question is if you really need to call your filtering / searching logic as a controller action. Do you really need to make a request?
I would say it could be also doable just by passing all the required data to a service you define.
This service you should create from the guts of your ChoiceTableBundleand let both you ChoiceTableBundle and your OtherBundle to use the extracted service.
service / library way
// register it in your service container
class FilteredDataProvider
{
/**
* #return customObjectInterface or scallar or whatever you like
*/
public function doFiltering($searchString, $order)
{
return $this->filterAndReturnData($searchString, $order)
}
}
...
class OtherBundleController extends Controller {
public function showStuffAction() {
$result = $this->container->get('filter_data_provider')
->doFiltering('text', 'ascending')
}
}
controller way
The whole thing can be accomplished with the same approach as lipp/imagine bundle uses.
Have a controller as service and call/send all the required information to that controller when you need some results, you can also send whole request.
class MyController extends Controller
{
public function indexAction()
{
// RedirectResponse object
$responeFromYourSearchFilterAction = $this->container
->get('my_search_filter_controller')
->filterSearchAction(
$this->request, // http request
'parameter1' // like search string
'parameterX' // like sorting direction
);
// do something with the response
// ..
}
}
A separate service class would be much more flexible. Also if you need other parameters or Request object you can always provide it.
Info how to declare controller as service is here:
http://symfony.com/doc/current/cookbook/controller/service.html
How liip uses it:
https://github.com/liip/LiipImagineBundle#using-the-controller-as-a-service

Which pattern and how to structure this [Different serviceHandlers, structure and validation]?

Alright so I'm trying to make some sense of all these patterns.
Alright, so I'm coding an applicantion in CodeIgniter which needs to be able to send data about a car and a customer to different types of companies using SOAP, maybe XML, comma-separated and so on.
But they all need the same thing.
I wanna make it as dynamic as possible and make sure it's easy to write tests.
So the service should take a couple of things:
a handler
applicants [1-2]
params
object
I started up creating different classes
Gr8Exp
NordCar
SwePerf
each implementing the interface iServiceRequest
interface iServiceRequest{
/**
* Send the request to the company server.
*/
function sendRequest();
/**
* Saves the response into the database.
*/
function saveResponse();
/**
* Prepares the request to the company, setting info from form and shit.
*/
function prepareRequest();
/**
* Soap, XML, CSV, JSON
* #param type $method
*/
function setRequestHandler(iServiceRequestHandler $handler);
}
Then they need to structure up the Soap, XML, CSV, JSON request depending on what handler i put in.
After those who needed to be validated (not all did) I used:
interface iAdaptServiceRequest{
/**
* Structure the array information and put it into an object structure in the right place.
*/
function structure(array $info);
/**
* Make all the checks for the function
*/
function validateInfo();
}
But I'm stuck, It worked really good when I just used SOAP request; but now. Since I need to format them differently, use a different handler for each type of request or company I don't know what to do.
I could put them i different folders and recreate the class in the different folders. But that's not a good practice since I'm duplicating code all over.
In the end I want to run some chaining like this:
$result = $m->prepareRequest()->sendRequest()->saveResponse();
Any suggestions??
IMHO:
-- create/use a front controller.
-- The front controller determines which request handler to use (JSON, SOAP, XML, etc).
-- The request handler generates a common "Request" object that behaves the same across all interfaces, basically putting variables into a common named format inside a "Request object"
-- It determines which service to send the request to and sends the request object there
-- The service processes the request object and generates a response object
-- The controller creates an appropriate (JSON/SOAP/XML) View object to process the response object into the correct view type and the View outputs your response as that type.
I would use something like yours: $result = $m->prepareRequest('JSON')->sendRequest()->saveResponse();, but specifing what format of data I'm sending.
The method prepareRequest(string $type) would check the format and call another method to convert your data to the respective format.
Something like this:
function prepareRequest(string $type){
if ($type == 'json'){
$this->convert2json();
}
if ($type == 'xml'){
$this->convert2xml();
}
// And so on
}
There is often confusion about the MVC or Observer pattern. This is not a situation in which this pattern is applicable. In the MVC pattern are the View and Model related to one another. The View must update itself based on information of the subject. A view and the underlying tables in a database are a good example. That is not what you want here.
The design pattern which suits this problem is the Builder pattern. The Builder pattern consists of four cooperating classtypes:
1. a Builder,
2. a ReaderManager,
3. a ConverterManager, and
4. a DataObject.
The ReaderManager is using the Interpreter pattern. Conversion can be done using the State pattern. What is the output of the ReaderManager (some DataObject) is the input for the ConversionManager. That can be done using an abstract class instead of an interface (my preference for data focused classes). The Builder connects the ReaderManager with the ConverterManager and takes care of the transport of data.
Some years ago I wrote about design patterns. The builder pattern was one of the patterns I described and this is the link to that page:
http://www.loekbergman.nl/InsideArchitecture/TheProcess/DesignPatterns/Builder
It shows a UML diagram of the pattern.
In the next link you can download a jar with some examples of design patterns. One of them the builder pattern:
http://www.loekbergman.nl/InsideArchitecture/DownloadsAndLicense
I have written this code several years ago, therefor do I give you this code without warranty. (Is that the correct term in this context?)
In the code you can see a folder with the name specifications. That is another example of the Interpreter pattern. (In the Builder pattern there is of course also an example of this pattern).
To be complete is here the link to the MVC - pattern:
http://www.loekbergman.nl/InsideArchitecture/TheProcess/DesignPatterns/Observer
and the Interpreter pattern:
http://www.loekbergman.nl/InsideArchitecture/TheProcess/DesignPatterns/Interpreter

Categories