In terms of the logic for the calculateIncomeTax method, it sounds  
like that is going to be on the server. This means that the client  
version of the Person class will primarily be a proxy to the server.  
Therefore, it doesn't necessarily need to be "rich" because the logic  
is not inside the class itself, but instead defined somewhere else.  
All that you are gaining using a "rich" approach is that you get to  
interact with just the Person class. Once you get to this point, there  
is very little difference between this methodology and using anemic  
domain and services.

On the flip-side, if you put the logic into the Person class itself  
rather than on the server, you end up with a headache when the tax  
laws change and you need to push out a new version of the Person class.

I guess that is my main point. The "rich" domain folks talk about  
putting logic and data in the same place. But when the logic gets  
complex or changes frequently, you _have_ to pull it out into a  
service that conforms to an interface. Then it makes sense to put that  
logic on another server so that it can be re-used and can scale. Then  
you start looking at ways of swapping in new implementations of that  
interface at runtime to make updates easier. And you think about  
service discovery and all that jazz and BAM, your client is anemic.  
You've pulled the logic as far away from the data as you could. Now,  
you can still have a "rich" domain on the server. However, if you run  
into similar cases on the server, you'll just do it again.

I also think this only applies in certain places. Those are business  
domains with business logic. If it looks like to could ever be  
distributed, I say make it anemic and service based.

-bp




On Nov 7, 2008, at 4:51 PM, Gili Tzabari wrote:

>
>
>       I was actually going to bring up #2 myself in the last post but I
> forgot. I believe that in most cases Person.marry(Person other) will
> work but sometimes the implementation requires you to access  
> information
> that spans beyond the state of a single person. Because you never know
> how the implementation might evolve over time I always prefer placing
> such methods at the Persons level. That is, any business logic  
> involving
> a single person goes into Person while logic involving multiple  
> parties
> goes into People. That's just a rule of thumb (feel free to violate it
> if it makes sense).
>
>       With respect to #1 I would suggest injecting two different
> implementations of Persons for the client and server. That is, the  
> code
> lives inside the Persons instance, but the concrete implementation  
> would
> vary.
>
>       Again, I am sort of making this up as I go along but it feels right  
> so far.
>
> Gili
>
> Brian Pontarelli wrote:
>> A few questions:
>>
>> 1. Where is the implementation (actual code) for the /Money
>> calculateIncomeTax();  method located?/
>>
>> 2. Why isn't the /marry()/ method on Person like this: /marry(Person
>> other);/?
>>
>> -bp
>>
>>
>>
>> On Nov 7, 2008, at 3:34 PM, Gili Tzabari wrote:
>>
>>>
>>>
>>> I am actually toying around with a 3rd paradigm. I'm not sure  
>>> whether
>>> it falls under the category of anemic models, rich domain model or
>>> something else. Judge for yourself:
>>>
>>> // Cat + business logic
>>> class Person
>>> {
>>>  private String name;
>>>
>>>  String getName();
>>>  Money calculateIncomeTax();
>>> }
>>>
>>> \-> Key point: all methods operate on the current Person. Unlike  
>>> anemic
>>> models, you store business logic methods at this level so long as  
>>> they
>>> apply to a single Person (i.e. calculateIncomeTax()).
>>>
>>> // CatService + state
>>> class People
>>> {
>>>  private List<Person> people;
>>>
>>>  void marry(Person first, Person second);
>>>  List<Person> getMarriedPeople();
>>> }
>>>
>>> You would reuse the same Person implementation on both client and
>>> server while varying the implementation of People. For your cats
>>> example, you'd have Cat and Cats instead of Cat and CatService.
>>>
>>> Gili
>>>
>>>
>>> Brian Pontarelli wrote:
>>>>> Are you talking about wanting to be able to represent a Cat with
>>>>> fix()
>>>>> on the server and without fix() on the client because of business-
>>>>> logic?
>>>>> Or are you saying that technical limitations might cause fix()  
>>>>> to fail
>>>>> on the client? If it's the latter I argue that it's no different  
>>>>> from
>>>>> the server because even there the DB might become unreachable. If
>>>>> you're
>>>>> arguing the former, then I argue you need different client-side  
>>>>> and
>>>>> server-side Cat interfaces because they are not really the same.
>>>>
>>>> What I'm saying is that the fix method must be different on the  
>>>> client
>>>> and server. This generally means a different class for the client  
>>>> and
>>>> server. If it was the same class on the client and server, all the
>>>> logic would need to be pull out into a well known interface and  
>>>> that
>>>> interface would need to be different implementations on the  
>>>> client and
>>>> server, making the domain just a proxy and not very rich.
>>>>
>>>>
>>>>> I guess I am saying that you shouldn't be passing Rich Domain  
>>>>> Objects
>>>>> over the wire because (from practical experience) the server- 
>>>>> side and
>>>>> client-side interfaces are almost always "different enough" that  
>>>>> you
>>>>> can't share the interfaces. Clients usually contain a subset of  
>>>>> the
>>>>> server methods and might contain some client-only methods. I  
>>>>> believe
>>>>> Rich Domain Objects still hold a lot of value on the server-end,
>>>>> even if
>>>>> you can't pass them to clients. Clients and servers can both run  
>>>>> their
>>>>> own show (with RDO) and communicate over the wire by passing a
>>>>> subset of
>>>>> the state (DTO, REST, whatever you want to call it).
>>>>
>>>> Yeah, we agree on this. You shouldn't be passing around rich domain
>>>> objects because they don't work that way. This incurs a lot of code
>>>> overhead though.
>>>>
>>>>
>>>>> I argue you always need to define the client-server interface by
>>>>> hand.
>>>>> Serializing your state-only Object to the client is very poor
>>>>> practice.
>>>>> One reason is that you're essentially exposing an interface to the
>>>>> client and this needs to be designed and exposed very carefully.  
>>>>> The
>>>>> other reason is that you can't rely on having Java on both ends of
>>>>> the wire.
>>>>
>>>> Not sure what you mean by this. You definitely have to define how  
>>>> your
>>>> client talks to the server and what your server responds with,  
>>>> since
>>>> that is the standard remoting paradigm. In terms of serializing a
>>>> state only object as poor practice, I think you might be confused,
>>>> because that's what you said you should do above with the DTO/REST/
>>>> whatever. DTOs are state objects.
>>>>
>>>> Again, here's a concrete example so we are on the same page:
>>>>
>>>> RDO
>>>> -------
>>>>
>>>> public class ClientCat {
>>>>  @Inject RemoteCatService cs;
>>>>  boolean fixed;
>>>>
>>>>  public void fix() {
>>>>    CatDTO dto = new CatDTO();
>>>>    dto.fixed = this.fixed;
>>>>    this.fixed = cs.fixTheCat(dto);
>>>>  }
>>>> }
>>>>
>>>> public class ServerCat {
>>>>  @Inject EntityManager em;
>>>>  boolean fixed;
>>>>
>>>>  public void fix() {
>>>>    this.fixed = true;
>>>>    em.persist(this);
>>>>  }
>>>> }
>>>>
>>>> public class CatDTO {
>>>>  boolean fixed;
>>>> }
>>>>
>>>> public class Client {
>>>>  public void fixTheCat() {
>>>>    ClientCat cat = DI.makeCat();
>>>>    cat.fix();
>>>>  }
>>>> }
>>>>
>>>> // This class runs on a different server
>>>> public class RemoteCatService {
>>>>  public void fixTheCat(CatDTO dto) {
>>>>    ServerCat cat = DI.makeCat();
>>>>    cat.fixed = dto.fixed;
>>>>    cat.fix();
>>>>  }
>>>> }
>>>>
>>>>
>>>> Anemic
>>>> ----------
>>>>
>>>> public class Cat {
>>>>  boolean fixed;
>>>> }
>>>>
>>>> public class Client {
>>>>  @Inject RemoteCatService cs;
>>>>
>>>>  public void fixTheCat() {
>>>>    Cat cat = new Cat();
>>>>    cat = cs.fixTheCat(cat);
>>>>  }
>>>> }
>>>>
>>>> // This class runs on a different server
>>>> public class RemoteCatService {
>>>>  @Inject EntityManager em;
>>>>
>>>>  public Cat fixTheCat(Cat cat) {
>>>>    cat.fixed = true;
>>>>    em.persist(cat);
>>>>    return cat;
>>>>  }
>>>> }
>>>>
>>>>
>>>> I like the second one personally. Less code and easy to manage.  
>>>> Plus,
>>>> I can pass my Cat around anywhere I want without transforming it  
>>>> into
>>>> other objects. In n-tiered systems, you could potentially pass  
>>>> the Cat
>>>> all the way from the front-end to the last tier and then back up.  
>>>> This
>>>> is how we built most stuff at Orbitz.
>>>>
>>>> -bp
>>>>
>>>>>
>>>>
>>>
>>>
>>>
>>
>>
>>>
>
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to