6

I have a use case where I display variables in a PDF file. But to get there is not simple, but I could do something like this:

/*
 * takes product model number, retrieves, processes, formats values
 * returns $variables, ready to plug-in to view with no further processing
 */
$variables = $this->repository->getVariables($model);

/*
 * View runs PDF Library code and displays variables and their values in a table
 */
$this->sendToView($variables);

Way 1 - Have Repository Do all the work to transform variables

inside getVariables I would do these:

  1. read raw data from database tables (stored expressions)
  2. run data through expression engine (it evaluates the expressions)
  3. format resulting numeric data (i.e. round to 2 decimal points)
  4. add denominations (i.e. mm or inches)
  5. adorn data (put engineering tolerances, or extra wording around variables)
  6. re-group data for consumption by the PDF API engine (the view)

All the work will be done in getVariables and sendToView will then directly plug the variables as PDF API directs, no transformation needed

Way 2 - Use repository to get raw data only

Opposite extreme is have getVariables do #1 only and have separate classes do their own things .. I could end up with

$expressions = $this->repository->getVariables($model);
$solveExpressions = $this->expressionEngine->process($expressions);
$formattedVars = $this->formatter->format($solvedExpressions);
$denominatedData = $this->denom->addMarkers($formattedVars);
$adornedData = $this->adorner->adorn($denominatedData);
$viewReadyData = $this->viewPreparer->prep($adornedData);
$this->sendToView($viewReadyData);

Or I could mix and match the above and stuff the methods into various classes..

My question

How much of the data transformation, formatting, regrouping, polishing, preparation, etc goes into the repository layer?

(That will help me determine what of the data manipulation will need to be done outside of repository layer, and maybe even what of the data manipulation is to be done in the view layer - i.e. simple regrouping of data for easier way to plug into a table)

P.S. What am I trying to do (data manipulation)

Without focusing on code, in the context of the question, what I am doing is this -- starting with expressions stored in database:

a = 5
b = a + 3

Then I end up with solved expressions:

a = 5
b = 8

Then I do a series or formatting and adorning like so:

8 => 8.00 => 8.00mm => 8.00mm +/-0.01

where during the above is stays in a form similar to

array(
    'a' => '5.00mm +/-0.01',
    'b' => '8.00mm +/-0.01'
);

For the view I transform that into

array(
    0 => array(
        'description' => 'a',
        'value' => '5.00mm +/-0.01'
    ),
    1 => array(
        'description' => 'b',
        'value' => '8.00mm +/-0.01'
    )
);

And I wish to write the above into modern OOP code.

  • Does it make sense to just add an intermediate layer in between? – Teimpz Nov 28 '16 at 17:38
  • If you want to do it OO you need to focus on the "why", not on the "what/how" like above. Start with classes, not functionality. – qwerty_so Nov 28 '16 at 18:07
  • yes .. but that's pretty arbitrary. I am curious to see if there is a best practice. I was told before that something like "using a Data-Access-Object or a Repository to retrieve raw data from Database" is anemic ... and I might as well convert it into an object that's usable by my application without any further transformation. Thus ... it may be good to do data transformation from raw to business object in the repository. But in my case it is less clear what my business object is – Dennis Nov 28 '16 at 18:08
  • @Thomas, I am not sure how to use your approach. . can you give me a starting example? – Dennis Nov 28 '16 at 18:09
  • 1
    A user requesting it is a requirement. The "why" is in the business/use case. You need to model towards this, not against a single requirement. Basically the answer from kayess is fine. But the whole story is more complex. You should model the use cases first, before starting to model classes. – qwerty_so Nov 28 '16 at 22:02
3

Based on your comments, I would highly recommend you to not get fooled by so called best practices and other wizardry. Primarily you should choose a way to implement your solution in a way that helps:

  • your stakeholders/boss to reach business goal using your solution - the code in place.
  • you and your team to be able to fastly respond to the arisen problem/task, in a way that everyone understands

You also write about anemia and business object. Please prove me wrong but I fail to percieve any behaviour or business logic in the set of method calls. They just seem to doing a series of data transformation, without any validation or so. I have a gut feeling that it's used for some sort of reporting, but the true intention is not really clear.

The only useful thing I could help you with is, to examine your code, capture the technical areas and split them up to modules those have explicit boundaries. The Separation of concerns design principle can help here drawing the boundaries:

  • Repository: held responsible for reading and writing the data in your data store
  • Expression engine: evaluating the data
  • Formatter: formatting and adorning
  • Output to viewing: convert/represent the above to a given output form

Each of these modules should be responsible for their own set of concerns. Create classes with respective methods that does what are respectively responsible for and nothing more. Whenever you encapsulate these concerns into set of modules you are also increasing cohesion and may even help the testability of your code.

  • user selects a product, values for product are created and are written to the database for a particular order. After that, every time the order is pulled up in the system, those values are displayed. It's not reporting really but... viewing an order. Use case may be called "Display an order". part of that use case is "display values for that product". In a way all of the above is just a complicated way to show values as part of that use case – Dennis Nov 28 '16 at 21:30
  • Well, if you have a clearly defined use case it's good as it reflects a business use case. You could although implement it in a way that clearly communicates the business use case that could utilise commands and queries. The "display values for that product" is definitely a query, which you could decorate with formatting, etc. – kayess Nov 29 '16 at 9:09

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.