Question

I'm trying to keep my entities persistence and service-ignorant, but I'm running into a snag when it comes to BLOB- and file-correspondent properties of entities. Say I have, within an aggregate, an entity like such (kept basic for example):

class Attachment
{
    private $_ownerId;
    private $_filename;
    private $_type;
    private $_size;

    public function __construct ($ownerId, $filename, $type, $size)
    {
        $this->_ownerId = $ownerId;
        $this->_filename = $filename;
        $this->_type = $type;
        $this->_size = $size;
    }

    // some getters, etc.
}

Approaches I have considered or am considering:

  1. Creating a service interface, 'FileProvider' or something, with a method similar to load (Attachment $file), whose implementors know how to obtain and return the binary of the file
    • This allows for multiple implementations of the data access logic (FileProviderMysql, FileProviderDirectory, FileProviderRemoteFTP, etc.)
    • This seems to fit Eric Evans' description of a service class as an object that encapsulates behavior that does not seem to fit within entities or value objects
    • There are also examples in Evans' book where service classes encapsulate access to an awkward or legacy interface with a simplified, intention-revealing interface
  2. Possibly inject an implementation of said interface into the entity itself so the entity's contents can be obtained on-the-fly with the same syntax as any of its other properties
    • This way, the repository (or its current strategy) for the aggregate will have the ability to inject the service implementation that corresponds to the current storage implementation, freeing clients and application services from making that call
    • However, I am unsure of whether an entity should really 'know' about a service interface

Would someone with experience in this scenario please weigh in and help me come to a decision? I want to make sure that the work I am doing will hold up. Thank you...

Was it helpful?

Solution

I would go with approach 1 and it can either be a domain service or a repository. Either way, access to the BLOB corresponding to an Attachment is encapsulated.

It is also important to consider the points at which you need access to the BLOB. Is it needed for any domain-related behavior? Or is it more of an infrastructural concern?

UPDATE

The benefit of approach #2 is that of increased encapsulation of behavior associated with the entity. If in this case Attachment references a service for loading the blob, this entity can be passed around with the knowledge that no additional dependencies will be needed. This can also seem like a more natural approach. Since the Attachment entity provides access to other fields, why not the blob?

However, this approach suffers several drawbacks. Having entities reference services or repositories is generally discouraged because it can result in crossed responsibilities and it makes reasoning about the behavior of the entity more difficult, especially if the dependency is itself an abstraction. Instead, it is better to determine use cases where the BLOB is required, and reference this service in the code implementing those use cases, usually the surrounding application service.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top