1

From all the tutorials I've read the service layer only seems to only have one or two methods in it so I am unsure whether services are only supposed to be lightweight/skinny as opposed to fat with as many methods as you need

If I have a Post domain object and have a PostService class is this what you are ment to do from within a controller if you wanted to delete a post:

$postService = $this->serviceFactory->build('post');
$postService->deletePost($id);

and the deletePost() method inside the PostService is something like:

$postMapper = $this->dataMapperFactory->build('post');
$post = $postMapper->fetchById($id);
// Check if the post exists
// Check if it belongs to this user
// Some other checks
$postMapper->delete($post);

Is that correct? Essentially are domain objects just value objects and all the work gets done in the service layers?

Any help would be great thanks.

tereško
  • 56,151
  • 24
  • 92
  • 147
ibanore
  • 1,430
  • 1
  • 12
  • 24
  • Why don't you use an ORM like [Doctrine](http://www.doctrine-project.org/projects/orm.html)? Your service layer would then invoke access to your ORM rather than managing the entire process – hohner Feb 17 '13 at 13:21
  • 1
    Because he's a developer and understand that ORMs have very limited use-case. – tereško Feb 17 '13 at 13:22
  • @tereško ORMs aren't for and written by developers? Very limited use-case? Symfony? ZF2 with Doctrine 2? Rails with ActiveRecord? – hohner Feb 17 '13 at 13:33
  • @hohner , do you have even vagues grasp on what are the usecases for employing ORM (especially active-record based ORMs)? – tereško Feb 17 '13 at 13:42
  • 1
    @tereško Fast development and avoidance of repetition. Having something which, for example, automatically maps query results to an object (rather than manually doing so everywhere). I think this is an area which solicits a lot of subjective debate, so trying to enforce your own purist ideas as 'objective fact' might not be that beneficial to the OP. – hohner Feb 17 '13 at 14:00
  • @tereško There are many situations where relying on an ORM is much more sensible than architecting your own DAL; for me it's like using short-hand instead of manually specifying my own queries. I don't think it's a case of laziness, just time/resource management in a lot of cases – hohner Feb 17 '13 at 14:03
  • 3
    So .. since you obviously have no idea what are the usecase of ORMs, let me explain it to you. First group are the "mayfly projects" (usually as part of marketing campaigns), which you write quickly and never expand on or revisit. Then there are fast prototyping, when you generate throw-away code, which will be later replaced,if concept is approved. And the third group are applications where domain entities only perform basic CRUD operations and have no domain or relational logic in them. – tereško Feb 17 '13 at 14:07

1 Answers1

3

It seems, that part of your problem is actually in the mappers. IMHO, mappers should not be responsible for creating the domain objects. So, your example code actually should look more like:

$mapper = $this->dataMapperFactory->build('post');
$post = $this->domainObjectFactory->build('post');

$post->setId( $id );
$mapper->fetch($post);
// Check if the post exists
// Check if it belongs to this user
// Some other checks
$postMapper->delete($post);

Also, most of those "other checks" are actually done on the domain object. For example:

if ( $post->belongsTo($user) )
{
    ...
}

The role of the service is "application logic", which is a term to describe interaction between domain objects and the mappers. It is also common that service interact with other services.

As a side-note

Having a PostService makes no sense to me. Service are supposed to represent major segments of domain business logic in the model layer.

  • you have Recognition service instead of UserService and LoginService.
  • you have Content service instead of DocumentService and CommentService and UserService

Oh.. and also, you to not need to add ..Service or ..Controller postfixes anymore. PHP has namespaces now.

Community
  • 1
  • 1
tereško
  • 56,151
  • 24
  • 92
  • 147
  • So, how does this work? You get an empty `post` from the DO factory and then the mapper fills that object with relevant data? Does it return the object, or act on the argument as a reference? Also, how would you retrieve multiple posts in this setup? `$posts = $this->domainObjectFactory->build('postCollection'); $posts->setIds( $someArrayOfIds ); $mapper->fetch($posts);`, or something? It all seems a bit contrived and cumbersome. But I am interested to hear you elaborate a bit more, although I'm aware this might not be the proper place to discuss this further. – Decent Dabbler Feb 17 '13 at 13:50
  • Thanks. I used to do it your way, create the DO first and set the ID, maybe I will start doing that again. Do I do the `$post->belongs..` part in a Service layer method or a DO method? If I don't have a `PostService` do I have to do the work/checks I currently have in it in the controller? I can't think of where else that bit of code would go. – ibanore Feb 17 '13 at 13:50
  • @fireeyedboy , you can always go to the PHP chat room. As for your code example, you are confusing "domain objects" with "domain object collections". They are not the same thing. For a quick explanation you can read this post: http://stackoverflow.com/a/11943107/727208 – tereško Feb 17 '13 at 13:56
  • @tereško Clever stuff! It's clear enough for me already. I like it. Upvoted. :) – Decent Dabbler Feb 17 '13 at 14:18
  • @David , the point i was trying to make was that you do not create services for one single domain object. Instead your service should provide abstract borders for different parts of functionality in the model layer. As for the controllers, there should not be any business logic in the controllers. Controllers only take the user request and distribute the data to multiple services and (sometimes) to the view instances. – tereško Feb 17 '13 at 15:15