11 Replies - 7986 Views - Last Post: 27 March 2016 - 10:08 AM

#1 Kurissu   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 19
  • Joined: 28-September 15

Using the Factory and Repository patterns.

Posted 23 March 2016 - 02:52 PM

I have been given the task of designing a layered model for a membership registration use case. At first I was under the impression that I had a firm grasp of the Factory and Repository patterns, that was until I needed to bring the two together within the same object oriented framework. Here is what I have so far...

Spoiler


So my main difficulty is coming to a final decision as to which classes should be associated with MemberRepository. The previous associations for MemberRepository were the Member subclass and the MemberController class. The problem with this arrangement was that the MemberRepository class has no assoccation with the MemberFactory class, which surely would be needed so that any newly created Member object can be sent straight from the MemberFactory class to the mediator of the business logic and the database layer (i.e. MemberRepository). To support the need of the association of MemberFactory and MemberRepository is the reverse procedure of retrieving aggregated infomation from the database layer and encoding the information into a Member object.

Having associations between MemberRepository and three other classes seems like avoidable coupling. So I'm fishing for potential solutions, one idea is to have MemberRepository associated with MemberList. So that when a Member object is created by MemberFactory (newly registered or encoded from the database) it is automatically added to the member_list array. And finding a previously registered Member would involve accessing the MemberList class before entering the MemberRepository, that way the member_list array will be searched first before any contact with the external database is made, which seems potentially time saving in the event that the sought after member was previously queried during the same run time.

I feel that my representation of this idea through the diagram is flawed. Should MemberRepository have a direct association with MemberFactory at this stage? And if so, that would put the coupling back to three associations (database included).

I would greatly appreciated any thoughts and advice on this matter.

Is This A Good Question/Topic? 0
  • +

Replies To: Using the Factory and Repository patterns.

#2 Bench   User is offline

  • D.I.C Lover
  • member icon

Reputation: 945
  • View blog
  • Posts: 2,464
  • Joined: 20-August 07

Re: Using the Factory and Repository patterns.

Posted 24 March 2016 - 11:56 AM

I think your first problem might be the fact that you are "trying to bring the two together". Take a step back from your model, and consider the Single Responsibility Principle (SRP).

Then consider the responsibilities of different patterns in your current design:
  • A Factory is responsible for creation of objects.
  • A Repository is responsible for object storage (Persistence).
  • A Controller is responsible for UI logic of a single View.

In keeping with SRP, which in that list of classes should take a newly created Member, maybe do some additional checking/validation, and then pass it into the repository? (Answer - None of them!)

Your factory certainly should have no knowledge of your repository, nor should it care about preventing duplication of data or validating inputs; the factory should only create (and initialise) objects without asking questions. Similarly, your repository should have no knowledge of your factory, nor should it be validating, because its only interest is in simple unhindered Read/Write operations.

In some very simple cases (i.e. UI applications where only a single view exists), some people might choose to put that logic inside their Controller, but that wouldn't be good for reuse nor would it be a clean separation of concerns.

Consider adding a new class, which acts as part of the 'glue', responsible for your member creation logic.
class MemberBuilder
{
    private MemberFactory factory_;
    private MemberRepository repository_;

    public Status CreateIfNotExists(string name)
    {
        Status status = Status.None;

        if (repository.DoesMemberExist(name))
        {
            status = Status.MemberAlreadyExists;
        }
        else
        {
            Member member = factory_.CreateMember(name);
            repository_.Add(name);
            status = Status.MemberCreated;
        }

        return status;
    } 
} 
You could think of MemberBuilder in the above class as part of your Business Logic Layer (The factory also technically exists in that layer), and your repository as part of your Data Access Layer.

I would expect the factory to be fairly simple/straightforward e.g.
class Factory
{
    public Member CreateMember(string name)
    {
        Member member = new Member();
        member.SetName(name);
        return member;
    }
} 
Again, forcing your factory to do anything more than that would mean it's no longer really just a factory - it would end up being a Factory+Creation logic (or, in other words, a full blown chunk of application/domain logic, which might also include some validation, etc.).

The other effect of changing your design this way would be for the UI Controller to have a reference to the MemberBuilder instead of the Factory -
class Controller
{
    MemberBuilder memberBuilder_;

    public Controller(MemberBuilder memberBuilder)
    {
        memberBuilder_ = memberBuilder;
    }
} 

This post has been edited by Bench: 24 March 2016 - 11:56 AM

Was This Post Helpful? 2
  • +
  • -

#3 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7463
  • View blog
  • Posts: 25,113
  • Joined: 05-May 12

Re: Using the Factory and Repository patterns.

Posted 24 March 2016 - 12:45 PM

Now try following through with that logic... How will the Repository instantiate an instance of the Member without knowing about the Factory?

Or should the Repository also have a reference to the MemberBuilder?
Was This Post Helpful? 2
  • +
  • -

#4 Bench   User is offline

  • D.I.C Lover
  • member icon

Reputation: 945
  • View blog
  • Posts: 2,464
  • Joined: 20-August 07

Re: Using the Factory and Repository patterns.

Posted 25 March 2016 - 02:28 AM

View PostSkydiver, on 24 March 2016 - 07:45 PM, said:

Now try following through with that logic... How will the Repository instantiate an instance of the Member without knowing about the Factory?

Or should the Repository also have a reference to the MemberBuilder?

Just to be clear, the OP mentioned 'layered' architecture, so I inferred that Member is an application object rather than a data entity. I don't really see much benefit in having plain-old-data entities being created by factories (particularly if the repository is an ORM, the creation logic is probably already hidden away). If the repository needs to create a Member as an entity to store directly into the underlying structure, then the factory is probably unnecessary.
Was This Post Helpful? 1
  • +
  • -

#5 Kurissu   User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 19
  • Joined: 28-September 15

Re: Using the Factory and Repository patterns.

Posted 25 March 2016 - 03:15 AM

Thank you both for your comments. Bench, the Member Factory was said to reside in the domain layer by my Lecturer due to its lack of application logic. Do you say that it's tecnically a business logic layer object due to its existence being for the purpose of creating
Member
objects?

Also one of my motivations was to ensure separation of concern within my design, however using the role controller
MemberController
seems contradictory of my intentions. However I am also concerned with the high coupling that would come with the more modular use case controllers. There seems to be a consequence of using either, I wonder which one would have more of a negative impact.



I've modified the design to account for a
MemberBuilder
that ensures the separation of concerns between
MemberFactory
and
MemberRepository
. Is this new design a representation of what you had in mind?

Also to clarify the repository is ORM. :)

Double post: apologies for the incorrect use of code tags effecting the readability of my post.
Was This Post Helpful? 0
  • +
  • -

#6 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7463
  • View blog
  • Posts: 25,113
  • Joined: 05-May 12

Re: Using the Factory and Repository patterns.

Posted 25 March 2016 - 06:33 AM

View PostBench, on 25 March 2016 - 05:28 AM, said:

View PostSkydiver, on 24 March 2016 - 07:45 PM, said:

Now try following through with that logic... How will the Repository instantiate an instance of the Member without knowing about the Factory?

Or should the Repository also have a reference to the MemberBuilder?

Just to be clear, the OP mentioned 'layered' architecture, so I inferred that Member is an application object rather than a data entity. I don't really see much benefit in having plain-old-data entities being created by factories (particularly if the repository is an ORM, the creation logic is probably already hidden away). If the repository needs to create a Member as an entity to store directly into the underlying structure, then the factory is probably unnecessary.


When I first read that, it made sense, but the more I thought about it things started to fall apart for me. Following your logic, then I would have something like this:
class MemberRepository {
    public void Insert(MemberDataObject member) {
        :
    }

    public IEnumerable<MemberDataObject> GetAll() {
        :
    }
}

class MemberDataObject {
    public int ID { get; set; }
    public string Name { get; set; }
    :
}

class MemberApplicationObject {
    public int ID { get; set; }
    public string Name { get; set; }
    :
}



I can't pass in a MemberApplicationObject directly to/from the MemberRepository. I'll have to map the fields of the MemberApplicationObject into a MemberDataObject. So what value am I now getting from using an ORM? Is the object relational mapping just now a convenient way to avoid the drudgery of writing SQL code?

This made me re-think my idea of the Repository pattern because my understanding of that pattern is that it is suppose to hand out domain objects, not data objects. Repository from Martin Fowler's site says:

Quote

Repository
:
A system with a complex domain model often benefits from a layer, such as the one provided by Data Mapper (165), that isolates domain objects from details of the database access code. In such systems it can be worthwhile to build another layer of abstraction over the mapping layer where query construction code is concentrated. This becomes more important when there are a large number of domain classes or heavy querying. In these cases particularly, adding this layer helps minimize duplicate query logic.

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.


Is that idea of the Repository pattern wrong? Or is it just outdated and modern Repository patterns use data objects going in and out?
Was This Post Helpful? 1
  • +
  • -

#7 Bench   User is offline

  • D.I.C Lover
  • member icon

Reputation: 945
  • View blog
  • Posts: 2,464
  • Joined: 20-August 07

Re: Using the Factory and Repository patterns.

Posted 25 March 2016 - 11:49 AM

View PostSkydiver, on 25 March 2016 - 01:33 PM, said:

class MemberRepository {
    public void Insert(MemberDataObject member) {
        :
    }

    public IEnumerable<MemberDataObject> GetAll() {
        :
    }
}

class MemberDataObject {
    public int ID { get; set; }
    public string Name { get; set; }
    :
}

class MemberApplicationObject {
    public int ID { get; set; }
    public string Name { get; set; }
    :
}



I can't pass in a MemberApplicationObject directly to/from the MemberRepository. I'll have to map the fields of the MemberApplicationObject into a MemberDataObject. So what value am I now getting from using an ORM? Is the object relational mapping just now a convenient way to avoid the drudgery of writing SQL code?
I think it depends whether the object has any behaviour. I agree in that (simple) scenario where the MemberApplicationObject does nothing more than store a couple of fields/properties that it's redundant.

However, consider the scenario where the application object(s) have added behaviour on top; the ORM will impose a set of relationships based on the entity model - but that's not necessarily going to work for your Domain Object model.

For example, a modern ORM might (correctly) represent a data relationship using inheritance between two entities which have no behavioural connection - e.g. an Animal/Dog/Frog might share some data properties, but trying to fit operations such as "Swim" and "Bark" into that heirarchy can be problematic.

As a domain model like that gets bigger you could start running into more problems with 'godlike' base-classes, bloated interfaces, etc. IMO this is the main reason to keep data entities separate from domain entities; it frees up those domain entities to define OO relationships which support their behaviour; and makes life easier when sourcing data from several entities. I find the design gets particularly messy when I need one object inside the repository to 'query' that repository for some data; in that scenario I'd prefer to avoid that kind of 'circular' referencing and keep the data separate from the objects.

Also, these days it's increasingly common for the repository to live inside a service behind a RESTful API, instead of every application having direct access to the underlying ORM. There might be good reasons to prevent particular information stored in those entities from being exposed publicly. A good example would be any sort of data relating to security and privacy. So for REST APIs at least, it's useful to map the DB entities on to a DTO.

View PostSkydiver, on 25 March 2016 - 01:33 PM, said:

This made me re-think my idea of the Repository pattern because my understanding of that pattern is that it is suppose to hand out domain objects, not data objects. Repository from Martin Fowler's site says:

Quote

Repository
:
A system with a complex domain model often benefits from a layer, such as the one provided by Data Mapper (165), that isolates domain objects from details of the database access code. In such systems it can be worthwhile to build another layer of abstraction over the mapping layer where query construction code is concentrated. This becomes more important when there are a large number of domain classes or heavy querying. In these cases particularly, adding this layer helps minimize duplicate query logic.

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.


Is that idea of the Repository pattern wrong? Or is it just outdated and modern Repository patterns use data objects going in and out?

Not necessarily wrong; I can see the rationale for doing things that way using the early/primitive Data Mappers which do little more than de-serialising the results of a custom SQL query (i.e. where the DB Schema/relationships aren't imposed as a restriction on the Domain Object structure). In a way, those sorts of mappers were actually more flexible than modern ORMs which are more like schema wrappers. But for modern ORMs I think it's too restrictive to really work (so in that regard, maybe somewhat outdated):

  • In most modern ORMs, the "Repository" and "Data Mapper" which Fowler mentions are one and the same thing.
  • OO Design principles and modern thinking about OO has evolved, with a lot of credence now given to SOLID.
  • Fowler's book was written in an era before the days of Microservices and RESTful APIs.

Each one of those items presents some part of the problem when the repository is the kind of ORM which reflects the schema directly, using automatic bindings to represent one-to-one and one-to-many relationships in terms of object relationships such as Inheritance/Composition/Aggregation. These seem to be extremely common nowadays; definitely a lot more common than in 2003 at least, when most ORMs were "just" straightforward data mappers).

I think another indicator of how far we've come is that Fowler also warned in his book about the Anaemic Domain Model "Anti-pattern", except these days I don't think many people really consider it an anti-pattern any more. It's sometimes considered to be completely in-keeping with SOLID principles.
I'm not even sure that Fowler himself would always consider it an anti-pattern any more - in light of tools like Hibernate and EF; but I can understand at the time a lot of "OO" code tended to be written in a procedural/C style. He was trying to fight against the mentality of writing everything as a standalone/static function with public members everywhere with no cohesion whatsoever. (So in some regards he's still right that it's a potential anti-pattern).

From a SOLID/OO point of view, the argument for those "anaemic" models would be that the relationships represented in the ORM code exist solely to support the relational/SQL mappings, and are not necessarily an indicator of how the domain objects can/should be related or represented. (i.e. like the Animal/Frog/Dog I mentioned above)

Also, when your repository code is auto-generated using a "Database First" ORM it's impossible for those objects to be changed by the programmer (which is more an argument against auto-generated code IMO) - though unfortunately auto-generated code seems to be everywhere still. However, the flipside where the DB is generated from classes isn't much better - any changes to those classes may potentially effect the mapping or the schema, which just makes those classes harder to use. In either case, the easiest thing to do IMO is just leave them as data objects.

This post has been edited by Bench: 25 March 2016 - 12:22 PM

Was This Post Helpful? 1
  • +
  • -

#8 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7463
  • View blog
  • Posts: 25,113
  • Joined: 05-May 12

Re: Using the Factory and Repository patterns.

Posted 25 March 2016 - 02:48 PM

Sounds like the weakness of the ORM that is diluting the cohesiveness of the design. If you had a completely object oriented database, would you design things the same way?
Was This Post Helpful? 1
  • +
  • -

#9 Bench   User is offline

  • D.I.C Lover
  • member icon

Reputation: 945
  • View blog
  • Posts: 2,464
  • Joined: 20-August 07

Re: Using the Factory and Repository patterns.

Posted 26 March 2016 - 02:05 PM

View PostSkydiver, on 25 March 2016 - 09:48 PM, said:

Sounds like the weakness of the ORM that is diluting the cohesiveness of the design. If you had a completely object oriented database, would you design things the same way?

I don't think an OO database would change anything really. ORMs such as EF do a very good job of mapping one-to-many and one-to-one relationships into object heirarchies, so when using EF you can't really tell that the underlying DB is SQL Server/MySQL/etc.

The real problem is that data entities often don't map neatly on to behavioural ones.

In both relational and object-oriented models you have issues where it makes sense to model entities such as Animal/Dog/Frog to avoid duplicating the Animal data, but trying to attribute behaviour such as Bark() and Swim() to that same model can break down in more complex programs.
Was This Post Helpful? 0
  • +
  • -

#10 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7463
  • View blog
  • Posts: 25,113
  • Joined: 05-May 12

Re: Using the Factory and Repository patterns.

Posted 26 March 2016 - 04:21 PM

I guess I'm not seeing your point. If I can have a graph of domain objects in memory and the computer and my program design has no issues with it, why can't I throw that graph at an object database and serialize that graph? Why do I suddenly need data entities?
Was This Post Helpful? 0
  • +
  • -

#11 Bench   User is offline

  • D.I.C Lover
  • member icon

Reputation: 945
  • View blog
  • Posts: 2,464
  • Joined: 20-August 07

Re: Using the Factory and Repository patterns.

Posted 27 March 2016 - 04:19 AM

View PostSkydiver, on 26 March 2016 - 11:21 PM, said:

I guess I'm not seeing your point. If I can have a graph of domain objects in memory and the computer and my program design has no issues with it, why can't I throw that graph at an object database and serialize that graph? Why do I suddenly need data entities?

The entire object graph for the whole business layer? I guess that's possible, but how you would control objects whose lifetime doesn't lend itself to persistence in the database? For example, an object might maintain pointers or handles to a network resource; or maybe contain data which belongs to a temporary session. If you serialised the entire object graph, wouldn't you also end up getting all of those things in your database too?

I don't really have any experience using Object-oriented databases, but I wonder how they cope with refactoring? i.e. publishing a new version of the software to existing customers (who want their data preserved) where some classes have been changed/renamed or split out, maybe with relationships changed. Do they have easy ways of coping with that migration process?

From experience with SQL databases I know how much effort it can be to change those schemas with upgrade/rollback scripts for each version (and the drudgery of testing them). I'd hate to have to write those every single time I renamed a class or changed a field/property while fixing a bug or implementing a new requirement; I'd be worried about turning refactoring into a painful task and the overall maintainability of the solution.

I guess that's another 'strength' of splitting the data entities away from the domain objects - you can refactor your domain objects to your heart's content (with unit tests of course) without touching your underlying data schema. Whenever I've worked with data schemas/databases, those structures have always been very stable and set-in-stone; the cost of changing them always seems too high.

This post has been edited by Bench: 27 March 2016 - 04:29 AM

Was This Post Helpful? 0
  • +
  • -

#12 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7463
  • View blog
  • Posts: 25,113
  • Joined: 05-May 12

Re: Using the Factory and Repository patterns.

Posted 27 March 2016 - 10:08 AM

I've used three different ODBMS's. The first two sucked and I've dumped their names from memory. What made them terrible was that I had to either derive from their base class and or I had to implement an interface or explicitly list fields to be serialized. The one that I was impressed with was db4o, which unfortunately has become abandon ware.

It handled class refactoring very well for things that could be derived from seeing before and after objects fields without semantic meanings. And if you were still unhappy with how it was doing things, hooks were present to tweak or completely override all phases of the move to the new schema.

For objects that do not serialize well like network connections, it provides hooks into its serialization/deserialization as well as it's instantiation.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1