1

I'm immersing myself in DDD and have a question regarding what belongs to the domain, and what is an infrastructure concern.

A simplified example to describe the domain:

One of the contexts in the App is regarding convenience functionality that allows users to examine web pages for certain information. i.e..

"A user wants to examine a web page and determine whether the phrase "lorem ipsum" appears and in what location."

We will use Selenium as the underlying technology for matching the phrase.

Before diving into DDD I would have created a Class like below (Python below but language shouldn't matter):

class Page:
def __init__(self, url, environment, driver):
    self.environment = environment
    self.url = url
    self.driver = driver    // Selenium Driver


def contains_phrase(self, phrase):
    self.driver.get(self.environment.url + self.url_suffix)  // Selenium Command
    ...

This entity is now dependent on selenium, and is no longer a pure object (POCO, POJO etc). This doesn't feel correct to me in DDD.

My understanding is that the the selenium expressions also don't belong in the Application Service layer, as this would bloat the class / method and the service layer should ideally be thin.

Does this then belong in the Infrastructure layer? Much like a Repository with persistence code living there. Something like:

class PageAutomator:
...
def does_page_contain_phrase(self, page, phrase):
    self.driver.get(self.environment.url + self.url_suffix)  // Selenium Command

Does this sound like the correct direction? And if so?:

This means the Page entity is starting to tend towards an anaemic model, and is becoming a simple DTO. If so is this entity even necessary any more?

Is it acceptable for the Application Service layer to call the Infrastructure layer directly and perform some action (to perform a use case) without the involvement of any entities (and hence the domain) at all? Even if taking more of a Transaction Script approach, my understanding is the Selenium functionality still shouldn't live in the domain?

Or (and I'm new to DDD) I'm complete way off base, in which case any advice or suggestions are very welcome.

Thanks

aL_eX
  • 1,453
  • 2
  • 15
  • 30
Steven
  • 823
  • 8
  • 25
  • _...and is no longer a pure object (POCO, POJO etc)._ DDD isn't about POCOs or POJOs (unless you use cqrs/es), its about behavior on entities. A POCO/POJO by its definition contains no dependencies and **no behavior**. So its the opposite of what you want with DDD (except for commands and queries and event messages of course). Rule of thumb: If it requires a dependency (database access etc) it doesn't belong into your domains aggregate. typically you abstract infrastructure (MVC, UI, Database frameworks) and just use abstract interfaces (or equivalents in your language) in your domain – Tseng Jan 24 '18 at 15:24
  • @Tseng it looks like you're confusing POJOs with DTOs. [POCOs/POJOs](https://en.wikipedia.org/wiki/Plain_old_Java_object) can actually have behavior. – guillaume31 Jan 26 '18 at 09:48
  • @guillaume31: [POCO](https://en.wikipedia.org/wiki/Plain_old_CLR_object): _In essence, a POCO does not have any dependency on an external framework and generally **does not have any attached behaviour**._ Models with behavior are generally called Rich-Domain Models in context of DDD – Tseng Jan 26 '18 at 13:08
  • @Tseng No, that's a misconception. Please read the Wikipedia article on POJOs, it basically says the opposite of the one on POCOs. – guillaume31 Jan 26 '18 at 13:12
  • In the context of DDD, the term POCO has historically been correlated with the notion of persistence ignorance of Entities. Entities **do** have behavior. See this answer for instance: https://stackoverflow.com/a/13632709/329660 – guillaume31 Jan 26 '18 at 13:16
  • Thanks for the discussion. Yes, maybe POJO / POCO was not the correct terminology to use. Basically my concern was that an external technology (Selenium) was being leveraged within the Domain. The Page is mostly concerned with encapsulating Selenium expressions. – Steven Jan 29 '18 at 18:18
  • Both responses help me out, so the first response as the answer. – Steven Feb 01 '18 at 18:28
  • An alternative could be something like `page.containsPhrase(phrase, searchEngine)`. Some may not like this approach because entities are not "pure" and might perform IO by delegation, but that approach is suggested by Vaughn Vernon in his red book. I'd say it puts more emphasis on the ubiquitous language and it may be easier to find out what kind of behaviors can be performed with a `Page`. @guillaume31 any thoughts? – plalx Feb 02 '18 at 19:01
  • @Steven I was referring to Tseng's use of POCO, not yours (which was appropriate). – guillaume31 Feb 05 '18 at 12:21
  • @plalx not really :) I'm actually wondering if Rich Domain Model is an appropriate pattern for so technology-dependent functionality. – guillaume31 Feb 05 '18 at 12:26

2 Answers2

1

My understanding is that the the selenium expressions also don't belong in the Application Service layer, as this would bloat the class / method and the service layer should ideally be thin.

Yes, you are correct. Selenium expressions should stay inside the Infrastructure because they are technology specific.

This means the Page entity is starting to tend towards an anaemic model, and is becoming a simple DTO. If so is this entity even necessary any more?

If the domain is anemic (please read 'simple') then the model will be also anemic.

Anemia has a meaning when we consider the Write part of the application, when the behavior stays in the Domain services when it should stay inside the Aggregate.

If so is this entity even necessary any more?

If your thing has a lifespan (it has an identity;it is created, modified and then dies) then yes, an Entity is necessary. If the behavior is missing (because the domain is simple), you could have a CRUD Entity and not a full-blown DDD Aggregate. You can take other strategic or tactical DDD decisions (like Bounded contexts and Context maps).

Is it acceptable for the Application Service layer to call the Infrastructure layer directly and perform some action (to perform a use case) without the involvement of any entities (and hence the domain) at all?

Yes.

Constantin Galbenu
  • 16,951
  • 3
  • 38
  • 54
  • Thanks Constantin. Your responses make sense. As per my comment above, it's the concept of Test Suites and Test Cases (no relation to code testing) which is more likely to belong in the domain. The Page object with Selenium is an implementation and technology specific concern that the Application Service layer can use to execute the tests. It's the tests that have identity as they go from built, to failed, to passed etc. Apologies this detail wasn't provided initially. Sometimes the obvious needs to be pointed out! – Steven Jan 29 '18 at 18:30
0

Searching for a string inside HTML is not business logic so domain driven design should not apply here.

A DTO or a class without behavior representing the page makes sense here.

The "search service" would be an infrastructure concern if there is a need for an abstraction over the Selenium specific implementation or re-usability across applications. If there is no need for that, it would be an application specific service/utility.

Dmitry S.
  • 8,373
  • 2
  • 39
  • 49
  • Thanks Dmitry. Yes, that's where I'm landing, but took reading through some responses to get it straight in my head. We do have the concept of "Tests" and "Suites" which the user can build, merge, and apply to different platforms and environments, which is more appropriate to the domain. The Page class is an abstraction over Selenium to technically execute the tests, so Infrastructure makes sense to me. – Steven Jan 29 '18 at 18:22