I am confused about Domain Driven Design Approaches. From the sources on net I understood it is way of segregating your Domain Objects
and Database Objects
but I don't understand the difference between two.
For an example lets take the code of Polls example in django tutorial, there are two models Polls
and Choice
.
Are these domain level objects
or database level objects
?
Is there a need for DDD with an ORM?
If yes, can you provide a good situation where you need to use DDD approach with an ORM
For example, this is the model
class Polls(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
DDD approach code I have seen people writing
class PollService(object):
def __init__(self, poll_repository):
self.poll_respository = poll_respository
def update(self, poll_id):
poll = self.poll_respository.fetch_by_id(poll_id)
poll.question += '?'
self.poll_respository.update(poll)
#assume that the following code works?
class PollRepository():
def __init__(self, db):
self.db = db
def update(self, poll):
try:
self.db.session().add(poll)
self.db.session.commit()
except Exception:
self.db.session.rollback()
Is this a correct approach? I see a lot of redundant code here but people say that Polls
is a domain level object and it should not directly talk to database?
Does DDD always comes with a DDD-reposiotry ? Why we need a DDD repository if we have an ORM
Another approach
views.py
def update_poll(poll_id):
poll = models.Polls.objects.get(poll_id)
poll.question += '?'
poll.save()
What is wrong with this approach?
Django is tailored towards the use of the Active Record Pattern as described on this Django Design Philosophy page.
Your second example follows this pattern - the model itself has its properties, behaviour and data access contained within.
You can still use this pattern in a more DDD-like way, if you push more behaviour onto the model. e.g. in your example, a more effective use of the pattern would be to wrap the line
poll.question += '?'
in an intention revealing method on the poll object, so that the update_poll
method is:
views.py
def update_poll(poll_id):
poll = models.Polls.objects.get(poll_id)
poll.add_question()
poll.save()
This has the advantage of separating the business logic (pushed into the model) from the application flow logic (the update_poll
method)
Although I'd suggest using a name that actually illustrates the intent or purpose of the method rather than just add_question.
But even if you do this, you are still using the Active Record pattern, not pure DDD.
DDD and an ORM are attempting to solve different problems. ORMs provide a convenient way of abstracting the set-like record-oriented world of databases in a more object oriented fashion.
DDD is an approach to assist with modelling complex real world situations in code.
Many DDD systems use ORMs to solve the infrastructure concerns of retrieving and persisting from the database (sometimes wrapping the ORM in a repository for a variety of reasons), but the DDD focus is on the domain models and how suitably they model the domain under consideration.
So - in your example, the benefits of DDD are difficult to see, as the business logic is so relatively simple.
I recommend reading the authoritive source on DDD - Domain Driven Design by Eric Evans for a language agnostic overview of the approach and the situations where it adds value.
You ask:
Can you update me with one good example where using DDD with an ORM makes sense
and
If we use ORM I think there is no need for a DDD-repository
I think a better way to think about it is - when using an ORM, the ORM is the repository. You ask it for a model and it returns a model. That is the purpose of a repository. When people wrap it in a class called 'repository' it is usually because they want to do one of a few things:
This overview of the repository pattern provides another good writeup of the ddd repository pattern.