Questions about Encapsulated Java Collections

38 views
Skip to first unread message

CRG

unread,
Sep 3, 2010, 6:56:56 AM9/3/10
to Growing Object-Oriented Software
GOOS mentions a preference for creating domain concepts around
primitive types and collections. In the latter case, there are
possibilities for encapsulating typical collection operations. For
example, in an auction, Bids, or BidHistory, could replace Set<Bid>.
Bids could have methods like:

* Bid lowestSince(Date)
* Bid forItem(Item)
* Bids losing() //returns the same type with a subset of losing only
* Bids winning()
* Bids lost()
* Bids won()
* Bids sortedBy(Comparator<Bid>)

If you apply Domain Driven Design patterns, you might even add
Specifications:

* Bids satisfying(BidSpecification)

Encapsulated collections could inherit from a generic type that
provides operations (searching, sorting) on an underlying Java
collection.

Where would an object of Bids originate?

In an eBay like system that keeps up with all Bidders, it could come
from a BidsRepository with methods like:

Bids forBidder(Bidder)

and then Bids could be used anywhere in the application without other
objects necessarily having to make a call back to BidsRepository.

In this case, I do see a potential for duplication. In DDD a
BidRepository often provides the methods I gave to Bids.

So in general, should an encapsulated collection know how to refresh
itself from a datastore, replacing or using the notion of a
Repository? Should it, as mentioned above, be a product of a
Repository?

Nat Pryce

unread,
Sep 3, 2010, 8:07:50 AM9/3/10
to growing-object-o...@googlegroups.com
I don't like using "Repositories" because they violate te domain model
(I know they are popular among DDD followers but I think DDD doesn't
take domain modelling far enough!).

Auctions have no concept of "repository"; it's a technical concern
leaking into and polluting the domain of auctions. If I want to model
a collection of domain-things I look for the appropriate concept in
the domain. I often model that as an interface in the application
domain model and then implement it in memory (wrapping a collection)
or using some underlying technology in an adapter layer that maps
domain concepts onto technical concepts.

In GOOS, for example, we introduce an AuctionHouse to represent one
collection of Auctions, being run by some organisation, and a
Portfolio as another collection of Auctions that the user is bidding in.

We deliberately did not call either AuctionRepository, because the
word Repository is vague and has no meaning in the domain, because we
try to avoid naming classes after patterns, and because it wouldn't
distinguish between the two quite different collections of auctions.

--Nat

www.natpryce.com

J. B. Rainsberger

unread,
Sep 3, 2010, 7:48:12 PM9/3/10
to growing-object-o...@googlegroups.com
On Fri, Sep 3, 2010 at 09:07, Nat Pryce <nat....@gmail.com> wrote:

> We deliberately did not call either AuctionRepository, because the
> word Repository is vague and has no meaning in the domain, because we
> try to avoid naming classes after patterns, and because it wouldn't
> distinguish between the two quite different collections of auctions.

I hadn't thought about this, Nat, but it seems to me that *Repository
represents yet another structurally accurate name begging for us to
refactor it into more intention-revealing classes, such as
AuctionHouse and Portfolio. Very nice.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca ::
http://blog.thecodewhisperer.com
Diaspar Software Services :: http://www.diasparsoftware.com
Author, JUnit Recipes
2005 Gordon Pask Award for contribution to Agile practice :: Agile
2010: Learn. Practice. Explore.

Christopher Gardner

unread,
Sep 3, 2010, 10:14:04 PM9/3/10
to growing-object-o...@googlegroups.com
I'm coming to that realization as well.

Lance Walton

unread,
Sep 5, 2010, 6:56:59 AM9/5/10
to Growing Object-Oriented Software
Hi all.

In many ways, I find the notion of 'DAO' or 'Repository' as a naming
scheme bizarre. My introduction to OO was on a 1 week course in 1995.
The tutor had a long history in OO development and the central thrust
was to identify domain objects and to represent them directly, at
least abstractly. Essentially, his method was that of Booch, but he
had a much longer experience than that.

I remember the question of databases, etc., coming up and his answer
was that there is almost always something in the domain that
represents the users' notion of where there data is stored. That
'search for the right name' idea has stuck with me.

I'm writing a blog about this at the moment, so I won't preempt what
I'm writing. Suffice it to say that the notion of 'DAO' as a class
naming idiom is hideous, except perhaps when the DAO classes are
implementations of a better named abstraction and it is that
abstraction that is known to the rest of the system.

Also, replacing the 'DAO' suffix with 'Repository' doesn't suddenly
make it a domain concept. Is this what Eric Evans really meant to
happen?

Regards,

Lance

Steve Freeman

unread,
Sep 5, 2010, 1:37:00 PM9/5/10
to growing-object-o...@googlegroups.com
Every time I think this kind of naming isn't that important, I get reminded why it is.

I did some refactoring on my last project on some code which had been written by someone in the Spring camp: lots of DAO's, Service's, etc. I don't remember the detail, but I changed one name from XXXService to something more relevant to the domain (let's say a GribbleFoo). All of a sudden, it was obvious that some of the behaviour was in the wrong place. The language in the code didn't make sense any more because GribbleFoo's don't do that. A little Intellj magic and the result was much cleaner.

I've often seen GribbleService types become a bloated dumping ground for everything to do with Gribbles, because there's no criteria for what they /don't/ do.

S.

Christopher Gardner

unread,
Sep 5, 2010, 2:38:31 PM9/5/10
to growing-object-o...@googlegroups.com
This thread has certainly got me interested in going "beyond" DDD and
Spring pattern naming conventions. I've been on many projects,
including my current, that have the layout that Steve describes. I am
very interested in seeing more examples that buck these naming
conventions and focus on real domain concepts. I'm still reading
GOOS, but does anyone on this forum have samples (in addition to
AuctionHouse and Portfolio) of encapsulated collections that do more
than hold a collection and, now from Steve's response, GribbleFoo's
refactored to not be a blob of functionality? Would love to see a
couple of blog entries (hint, hint).

Lance Walton

unread,
Sep 5, 2010, 3:37:50 PM9/5/10
to growing-object-o...@googlegroups.com
The thing is that AuctionHouse, Portfolio and GribbleFoos don't just hold a collection; they are first and foremost AuctionHouses, Portfolios and GribbleFoos.

Sure, the implementation might be to hold a collection, but what does the rest of the codebase think of them?

Another example that came up in a recent project is that of an 'order management system'. Naturally, this system had Orders, and the first three attempts (before we got there) had OrderDAO, OrderService, etc. Given that we could start again, we introduced an OrderBook (which was an interface) and lived happily within the domain. This had an implementation called HibernateOrderBook and another called OrderBookView (that did some filtering and sorting), but all the domain ever saw was an OrderBook.

Another example from the same system was that the original attempts had User, UserDAO, UserService, etc. Now users are frequently problematic in a system, because their is no 'user' in the domain. There were, however, sales-people. So we also had SalesForce as a domain model concept.

Finally, from the same system, the sales force talked to clients. Once again, there was Client (good), ClientDAO and ClientService. We had Client and ClientBook.

Regards,

Lance

Christopher Gardner

unread,
Sep 5, 2010, 4:34:10 PM9/5/10
to growing-object-o...@googlegroups.com
Lance,

A DAO or Repository typically has many query methods that provide
services for many tenants, e.g., OrderDAO.findFor(SalesForce). A
typical answer to that query would be a Collection<Order>. In your
case, does OrderBook fulfill the same responsibilities, or is it
something with which a domain concept, such as Client or SalesForce,
directly has an association that is unique to it? In other words, is
OrderBook a concept for a specific set of orders for a specific
client?

Lance Walton

unread,
Sep 6, 2010, 5:21:16 AM9/6/10
to growing-object-o...@googlegroups.com, growing-object-o...@googlegroups.com
The OrderBook is where, in an earlier age, Orders would be managed by a scribe. All of the scribe's behaviours were given to the OrderBook.

We sometimes did things such as gave the SalesForce implementation a reference to the OrderBook so that clients of the SalesForce didn't need an OrderBook as well (e.g. SalesForce.listOrders() forwards to OrderBook.list()). This was very much done as it made sense, to reduce coupling, etc.

But remember that OrderBook, SalesForce, etc. are interfaces, so how one particular implementation works is completely unknowable from any client code.

Regards,

Lance

Sent from my iPhone

Christopher Gardner

unread,
Sep 7, 2010, 9:11:38 PM9/7/10
to growing-object-o...@googlegroups.com
Lance,

How might the interface look to get a SalesForce or an OrderBook
reference from a datastore? What class would be responsible for a
query such as:

return all SalesForce's with OrderBooks of less than $1 million last year

Thanks.

On Mon, Sep 6, 2010 at 5:21 AM, Lance Walton

Lance Walton

unread,
Sep 8, 2010, 3:00:09 AM9/8/10
to growing-object-o...@googlegroups.com
Ah, we're talking across each other.

Imagine having a SalesPersonDAO, OrderDAO and ClientDAO. These are not business domain concepts, so we don't like referencing them from the business domain model (henceforth referred to as THE domain model). So one solution is to have a service layer that gets references to those DAOs, pulls what is needed out of them in order to do each piece of functionality and then, maybe passes control to whatever Orders, SalesPerson or Client that it has retrieved.

Instead of that, imagine making SalesPersonDAO implement SalesForce, OrderDAO implement OrderBook and ClientDAO implement ClientBook (it may not actually be implemented this way, but nothing else in the system will care now as long as you make sure the interface isn't leaking details of the DAOness). Package the SalesForce, OrderBook and ClientBook with the domain model because they can rightfully be viewed as part of the domain model. You now have persistence layer classes implementing domain model interfaces.

Now, you might still need a service layer which has references to these things as an entry point to your system and to coordinate activity between diverse parts of the domain model, but you can also pass SalesForce, OrderBook and ClientBook into whatever domain model methods you call so that the domain model can rummage around in the SalesForce, OrderBook and ClientBook as it needs to. This keeps the knowledge of how the domain model does its work local to the domain model, rather than distributing it between the domain model and the service layer.

Another solution to passing those objects into the domain model is to inject them at the point that the domain model objects are bought into existence from persistence. Hibernate lifecycle events can do this, for example. But even though I've done this on one project and it worked pretty well, I'm not sure if it's elegant or a horrible bodge and I have a sense of dirtiness about it.

With regard to the query you ask about: we only had one SalesForce who's OrderBook was being maintained, so it wouldn't have made sense for us. However, if we wanted to use the OrderBook or SalesForce interfaces to provide some subset of the whole, then we'd just put a method on whichever of OrderBook or SalesForce that made sense at the time and give it some appropriate name. That's a judgement based on what you have in scope at the time, minimising coupling, etc. Whether this returned an instance (or collection of instances )of SalesForce or not we'd make a judgement of on a case by case basis. If we did do that, the implementation of that SalesForce implementation for this purpose would again be down to judgement.

By the way, we didn't shy away from putting findById() type methods on these interfaces. Maybe if we'd spelled that as Chaucer would have done it would have retained the flavour of it :-) But there's nothing in principle that ties a numeric id to the notion of a relational (or other kind of technological) database. Raffle tickets, buses and the works of J.S.Bach are all uniquely numbered without there being a 'database'.

But the central point of this is to allow the domain model access to the abstraction without fhe domain model is becoming intimate with knowledge of the persistence layer. Everything else is a problem left for the reader :-)

Regards,

Lance

Nat Pryce

unread,
Sep 12, 2010, 4:31:43 PM9/12/10
to growing-object-o...@googlegroups.com
Relating this to the Ports and Adapters architecture we describe in GOOS: the SalesForce is in the application domain model.  The Hibernate library is a "port" domain, interfacing to a typically out-of-process RDBMS (via JDBC, which is also a port domain). And a HibernatedSalesForce lives in an adapter domain, that connects the application domain model to Hibernate and thence to a relational database server.

The static relationships are like this (I hope the Unicode art comes through ok):

                   [Application Bootstrap]
                           ↓               ↓
[Persistence Adapter] → [Hibernate]
                 ↓
[Application Domain Model]

(A similar diagram showing static relationships of the Ports & Adapters architecture never made it into GOOS because of lack of time)

The application bootstrap instantiates objects in the technical domains (e.g. persistence) and application domain model, and connects them via objects it instantiates from the adapter domains.  And then disappears in a puff of garbage collection leaving the objects running and doing their thing.  So there is less need for a service layer that mediates between quite passive objects.  I think of it more as a introduction agency than a mediation service.

--Nat
--
http://www.natpryce.com

Christopher Gardner

unread,
Sep 12, 2010, 4:37:28 PM9/12/10
to growing-object-o...@googlegroups.com
This looks like the Dependency Inversion Principle.

Nat Pryce

unread,
Sep 12, 2010, 4:48:15 PM9/12/10
to growing-object-o...@googlegroups.com
Yes.  Definitely an application of the DIP.

--Nat
--
http://www.natpryce.com
Reply all
Reply to author
Forward
0 new messages