4

I'm having an aggregate-root called Person. The person also has an Address. The relation between these Classes is ManyToOne (Many Persons share the same Address).

This means that when I'm creating a new Person with a specific address using a factory, I'd have to check if a same address already exists in the database and use an exisiting address for the user.

This requires my factory to have access to an Address-Repository (or directly to the database). Is this allowed? And if not, what would be a better approach to do this?

//EDIT My solution is now the following:

I have a class PersonService which holds the logic to register a person. The method register() already takes an Address-Object which is created by an AddressFactory. The Addressfactory has access to an AddressRepository to check, whether the entered address already exists or not. Here's the code:

public class PersonService{

  @Inject private PersonRepository pRepo;

  public Person register(Name name,..., Address address){
      //check if same person exists,
      //create person, persist person
      return person;
  }
}

public class AddressFactory{
   @Inject AddressRepository aRepo;

   public Address create(String street, int number, ...){
      //check if address with attribues exists in repo,
      //if not create new address
      return address;
   }
}

and in some bean this method is called like this:

personService.register(new Name("test"),..., addressFactory.create("Some street", 1,...))

What do you think?

user1727072
  • 309
  • 4
  • 14
  • Just for clarification - you're talking about deducing an existing address from what the user enters, right ? Will you ask the user if (s)he wants to pick that address or silently equate it with the specified address ? – guillaume31 Apr 08 '13 at 15:00
  • silently equating is the idea. – user1727072 Apr 09 '13 at 07:02

2 Answers2

4

This means that when I'm creating a new Person with a specific address using a factory, I'd have to check if a same address already exists in the database and use an exisiting address for the user.

If you follow the Single Responsibility Principle to the letter, you shouldn't do that. PersonFactory isn't supposed to create Addresses but Persons.

Even less so when Address creation includes complex logic such as retrieving an Address in the database that resembles more or less the address that was filled in by the user (if that's really what you want). You should delegate that to another object.

guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • 2
    In this case the [SRP](http://epic.tesio.it/doc/manual/solid_principles.html#about_single_responsibility) requires that the PersonFactory changes only when the logic to create Person's instance changes too. It doesn't mean that it should only execute a single **new**. Moreover, it **is** delegating the Address access to another object: the Address's repository. – Giacomo Tesio Apr 08 '13 at 13:29
  • 3
    It's delegating Address access indeed, but not the logic that will conditionally create an Address if it doesn't exist. To me that's one more reason to change, one more responsibility. – guillaume31 Apr 08 '13 at 14:52
  • 3
    I agree, and I would add that the object the logic to verify whether a given address exists would normally be the application service which handles creation of a person. – eulerfx Apr 08 '13 at 16:54
  • 2
    @user1727072 I wouldn't include the `Address` existence logic in `AddressFactory`, instead as @eulerfx pointed out I'd let the Person creation Service coordinate calls to `AddressRepository` and `AddressFactory` and use the resulting Address to create the `Person`. – guillaume31 Apr 09 '13 at 11:50
1

Yes, as far as the factory is used by the Person's repository (and not by the Person itself), it's a valid solution.

However you should consider if, in your domain model, the Person really need their address to ensure the business invariants. If not, remove the address from the person and use a PersonDTO specifically defined for such projective scope.

Community
  • 1
  • 1
Giacomo Tesio
  • 7,144
  • 3
  • 31
  • 48
  • I just noticed that you wrote ".. the factory is used by the persons repository". But my question isthe other way around: Can the factory use a repository to test if an equal object is already stored in the database? – user1727072 Apr 08 '13 at 11:52
  • @user1727072 you asked if a factory, in the Person's repo can use an Address repo. And this is fine. – Giacomo Tesio Apr 08 '13 at 11:57