5

I am integrating Zend Framework and Doctrine 2, and I am discovering the Service layer.

Now I understand (am I wrong ?) that I have 2 architectures possible :

  • A model, where classes contain domain logic, i.e. properties + getters/setters + complex methods
  • A lightweight model, where classes contain properties + getters/setters and a Service layer, containing domain logic, and modifying the model classes

What are the pros/cons of each ?

It seems weird to me to lose OOP by putting domain logic as external to the model, so I don't understand why use a Service layer.

contrebis
  • 1,287
  • 1
  • 11
  • 20
Matthieu Napoli
  • 48,448
  • 45
  • 173
  • 261

1 Answers1

14

What makes you think your Service Layer is external to your model? It isn't. In fact, it's a central part of your model, along with entities, repositories, etc.

If you're using Doctine2, you'll want a service layer. One reason is that you don't want your Entities knowing about the EntityManager (hurts testability). Another is that you also don't want your controllers driving the EM (it's not the controllers job to know about persistence).

I typically use an architecture where the service layer is the controller's interface to the model. The service layer exposes functions that operate on entities (either taking them as parameters, or returning them, or both). Persistence of entities is hidden by the service layer. Either the service class drives the EM and repositories itself, or delegates it to some other code that the controller will never know exists.

So the service layer provides and API that controllers can to use to manipulate your business data.

timdev
  • 61,857
  • 6
  • 82
  • 92
  • Great and clear answer thanks, though I have trouble understanding why loosing the OOP... What I mean is I think `$user->generatePassword()` is *better* than `$userService->generatePassword($user)` because the method applies to the user, it's not a "function" applied to a parameter... That's what I mean by "external". For me it's similar as the difference between OOP (objects and methods on objects) and function programming. With the service layer, the object is just a data container... – Matthieu Napoli May 01 '11 at 19:57
  • @matthieu if your `generatedPassword()` method only generates a random string then it is fine to have that method in your Entity; it doesn't pose any external, persistence related dependencies. – Cobby May 02 '11 at 00:52
  • 1
    @matthieu - Entity's *are* data-containers - they're just "fancy" (because they can have methods to manipulate or report on their internal state). generatePassword() might be fine -- as long as it doesn't rely on some external thing. For instance, if generatePassword() just generates 8 random characters, and assigns that string to $this->password (or passes it to $this->setPassword() which then hashes it appropriately), that's fine. It's fine because it only affects the user's password, and nothing else. Now, if you wanted to email the user their new password, you'd want to do that – timdev May 02 '11 at 05:53
  • [... continued] elsewhere. If you want to discuss this further, shoot me an email at tim-at-.com - this site is not designed for a back-and-forth conversation (but luckily, email is). – timdev May 02 '11 at 05:59
  • 2
    Or an external blog post with comment thread so that others - like me, hint, hint - could benefit from the exchange. I am very interested in this discussion. ;-) – David Weinraub May 02 '11 at 08:04
  • Great thanks i'm starting to getting it ! I'm reading a lot about the Service layer (though there's not a lot regarding PHP compared to Java) – Matthieu Napoli May 03 '11 at 07:55
  • @Matthieu Just to elaborate on @timdev's previous comment about `generatePassword`. Say for example you had a simple class called `String` that contained generic string functions, like `slugize()`, `hash()` and `generatedRandomString()`. It is also totally acceptable for an Entity to utilize such a class as it isn't related to persistence. – Cobby May 03 '11 at 13:06
  • 1
    @Cobby - Exactly. More particularly, it's okay because those functions don't have external side effects. At least in my projects, I don't allow entities to do things like send email. In fact, I probably wouldn't allow them to access an external read-only API directly. – timdev May 03 '11 at 19:40
  • @MatthieuNapoli thanks I've found this discussion very helpful in refining my thinking. Some of timdev s comments will become guiding principles for how my app is architected. Interested in following along your reading on Services. Are you willing to post a couple of links here? – Steve Aug 05 '14 at 23:14