Well I’ve seen many examples of domain models, but almost all of them are simple enough(about 2-4 data fields), so the model has a constructor that takes all the parameters and initialize its properties inside this constructor. Below is such an example from Mathias Verraes’ DDD example:
class Employee{
private $name;
private $position;
private $salaryScale;
public function __construct($name, $position, $salaryScale){
$this->name = $name;
$this->position = $position;
$this->salaryScale = $salaryScale;
}
// business logic omitted
}
But in reality, most domain models are much more complex and some can easily have more than 5 or even more than 10 data fields. I tried my best to make sure no table contains more than 15 columns, but I cannot make it any less than this for some tables. For instance, my Message domain model contains 9 fields, and some domain models have up to 12-13:
class Message extends DomainModel{
private $id
private $sender;
private $recipient;
private $title;
private $content;
private $dateSent;
private $dateModified;
private $outbox;
private $status;
// methods omitted
}
So if I instantiate this domain model by simply passing all the data fields as parameters, the constructor will have at least 9 parameters. I dont know what you think, but to me a method should not accept more than 6 arguments, or it looks like code smell to me. This article on stackoverflow agrees with me:
http://stackoverflow.com/questions/7962398/having-lots-of-parameters-in-a-constructor
And the question then is, how can I create and build a fully loaded domain model that has a lot of data fields. Right now I have repositories creating an empty domain model first, and then call the setters to inject each data field to the model. However, since I have already moved to domain driven design, these setters will be removed soon. The presence of setters breaks encapsulation, and I should not rely on them anyway. So I will have to change this to another technique of constructing my domain models.
The above stackoverflow article suggests the approach of builder design pattern, but it doesnt work well with PHP since this language has no inner/nested class support like Java. Even using a model builder class, the builder still needs to use setter methods to initialize private properties for domain model, so I end up with the setters once again(which I plan to remove). The issue is that there’s no good way to make the data fields accessible to the model and the model builder, without making them public(Java’s private inner class or C++'s friend class can solve this problem, but we dont have such methodologies in PHP). I dont use any public properties, it breaks encapsulation completely. I know Doctrine uses reflection to make private properties public when initializing them, but I doubt its a good solution either, as @TomB pointed out that using reflection to break encapsulation is not clever:
Another possible solution is also from the stackoverflow article, in which Necromancer and Sahil Muthoo suggested that one could create value objects and decompose the domain object into 2-3 value objects, which each value objects hold another small number of data. I do sometimes apply this approach, such as decomposing user data into user, userprofile, userexperience domain objects. However, it only works in ideal situation when its quite obvious and convenient to group related data fields into value objects or smaller domain models. In my example code above, I fail to see any of these fields can be grouped into value objects. Consequently, this approach only works at minor circumstances, and cannot be applied universally.
What do you think? How am I supposed to construct and build domain model objects that contain a lot of data fields? How would you solve this problem in practice?