Ted Epstein | 19 Aug 16:43

Maps in Public Interfaces Considered Harmful


Hi,

I'm new to this group, and don't mean to start a flame war with this
somewhat provocative subject line.

But I've been working on a complex domain model that will be available
as part of a runtime framework.  Some of the developers working on this
have prototyped public interfaces that return maps, or dictionaries. 
I've instinctively avoided using maps in public APIs, and have recently
had to examine my reasons for this more closely, for discussion within
the team.

In thinking through this, I'm increasingly of the opinion that maps
shouldn't be regarded as first-class modeling abstractions, and in most
cases shouldn't be exposed through public APIs.  Before I get to the
reasons for this, I'm looking for some pointers from the DDD community
to past discussions, blog entries, references, etc.   I did a cursory
search of this mail group and a a few google searches, but didn't come
up with much.

Is this something that has been discussed or addressed in DDD, modeling
or API design literature?  Any background information would be much
appreciated.

Thanks and Best Regards,

  - Ted Epstein

------------------------------------
(Continue reading)

moffdub | 20 Aug 03:10
Favicon

Re: Maps in Public Interfaces Considered Harmful

I may not be able to give you a lavishly rigorous answer. I agree with
your hypothesis on the condition that technical abstractions like maps
and dictionaries have no meaning in the in which domain you are working. 

That being said, I think they are generally appropriate as internal
implementation details only, and even then, you need to make sure they
don't impede the readability of the code for which they're being used.
On that last point, you can only take it so far; eventually, you do
need to actually write "computer" code.

--- In domaindrivendesign <at> yahoogroups.com, "Ted Epstein"
<Ted.Epstein@...> wrote:
>
> 
> Hi,
> 
> I'm new to this group, and don't mean to start a flame war with this
> somewhat provocative subject line.
> 
> But I've been working on a complex domain model that will be available
> as part of a runtime framework.  Some of the developers working on this
> have prototyped public interfaces that return maps, or dictionaries. 
> I've instinctively avoided using maps in public APIs, and have recently
> had to examine my reasons for this more closely, for discussion within
> the team.
> 
> In thinking through this, I'm increasingly of the opinion that maps
> shouldn't be regarded as first-class modeling abstractions, and in most
> cases shouldn't be exposed through public APIs.  Before I get to the
> reasons for this, I'm looking for some pointers from the DDD community
(Continue reading)

moffdub | 20 Aug 03:15
Favicon

Re: Maps in Public Interfaces Considered Harmful

--- In domaindrivendesign <at> yahoogroups.com, "moffdub" <moffdub@...> wrote:
> I agree with
> your hypothesis on the condition that technical abstractions like maps
> and dictionaries have no meaning in the in which domain you are
working. 

That should read: "... no meaning in the domain in which you are
working." Sorry about that.

------------------------------------

Alasdair Gilmour | 20 Aug 12:08

Re: Maps in Public Interfaces Considered Harmful

If you're using generics then I'm not sure I agree with this. e.g.
 
public Map<Customer, List<Order>> getAllOrdersByCustomer() {..}
 
seems relatively clear to me as returning "a mapping of each customer to a list of orders", which makes sense even at a non-technical level. The alternative of, for example, creating a CustomerToListOfOrdersMapping class to do the same thing seems to introduce extra clutter for not much gain ...
 
IMHO the objective is not necessarily producing code that a non-technical business user can just sit down and read, even though you are trying to establish and maintain a common ubiquitous language.
 
Alasdair
 
> Hi,
>
> I'm new to this group, and don't mean to start a flame war with this
> somewhat provocative subject line.
>
> But I've been working on a complex domain model that will be available
> as part of a runtime framework. Some of the developers working on this
> have prototyped public interfaces that return maps, or dictionaries.
> I've instinctively avoided using maps in public APIs, and have recently
> had to examine my reasons for this more closely, for discussion within
> the team.
>
> In thinking through this, I'm increasingly of the opinion that maps
> shouldn't be regarded as first-class modeling abstractions, and in most
> cases shouldn't be exposed through public APIs. Before I get to the
> reasons for this, I'm looking for some pointers from the DDD community
> to past discussions, blog entries, references, etc. I did a cursory
> search of this mail group and a a few google searches, but didn't come
> up with much.
>
> Is this something that has been discussed or addressed in DDD, modeling
> or API design literature? Any background information would be much
> appreciated.
>
>Thanks and Best Regards,
>
>- Ted Epstein
__._,_.___

Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___
jasonmeckley | 20 Aug 14:17
Gravatar

Re: Maps in Public Interfaces Considered Harmful

I find maps are just not expressive. for the example
Map<Customer, List<Order>> getAllOrdersByCustomer()
I would opt to return an array of customers. the customer would
encapsulate the orders.
Customer[] GetAllCustomersWithOrders();

foreach(Customer customer in GetAllCustomersWithOrders())
foreach(Order order in Customer.Orders)
{
}

--- In domaindrivendesign <at> yahoogroups.com, "Alasdair Gilmour"
<alasdairg@...> wrote:
>
> If you're using generics then I'm not sure I agree with this. e.g.
> 
> public Map<Customer, List<Order>> getAllOrdersByCustomer() {..}
> 
> seems relatively clear to me as returning "a mapping of each
customer to a
> list of orders", which makes sense even at a non-technical level. The
> alternative of, for example, creating a
CustomerToListOfOrdersMapping class
> to do the same thing seems to introduce extra clutter for not much
gain ...
> 
> IMHO the objective is not necessarily producing code that a
non-technical
> business user can just sit down and read, even though you are trying to
> establish and maintain a common ubiquitous language.
> 
> Alasdair
> 
> > Hi,
> >
> > I'm new to this group, and don't mean to start a flame war with this
> > somewhat provocative subject line.
> >
> > But I've been working on a complex domain model that will be available
> > as part of a runtime framework. Some of the developers working on this
> > have prototyped public interfaces that return maps, or dictionaries.
> > I've instinctively avoided using maps in public APIs, and have
recently
> > had to examine my reasons for this more closely, for discussion within
> > the team.
> >
> > In thinking through this, I'm increasingly of the opinion that maps
> > shouldn't be regarded as first-class modeling abstractions, and in
most
> > cases shouldn't be exposed through public APIs. Before I get to the
> > reasons for this, I'm looking for some pointers from the DDD community
> > to past discussions, blog entries, references, etc. I did a cursory
> > search of this mail group and a a few google searches, but didn't come
> > up with much.
> >
> > Is this something that has been discussed or addressed in DDD,
modeling
> > or API design literature? Any background information would be much
> > appreciated.
> >
> >Thanks and Best Regards,
> >
> >- Ted Epstein
>

------------------------------------

Epstein, Ted (IT | 20 Aug 21:16

RE: Maps in Public Interfaces Considered Harmful

Thanks for the replies.  From what I'm hearing, this seems to be a topic that hasn't been fully explored yet, so I'll offer my perspective on it.
 
There are at least three different ways of using Maps:
 
1. A concrete map implementation can be used internally to enforce a uniqueness constraint and provide optimized lookup of objects.
 
2. A public method can return a map interface, usually by returning a member variable that holds the internal state, as in case 1.  There are two different variations on this:
    a. Returning an immutable map that is only used to inspect the state of the map.
    b. Returning a mutable map that can be used to add and remove map entries.
 
3. To the extent supported by the modeling language, maps can be used in a conceptual domain model.
 
I think the first use of maps, as an private implementation detail, is completely benign.  The second and third uses are problematic, for a variety of reasons.
 
Developers approaching the conceptual model from an object-oriented programming perspective are often tempted to use a map as part of the conceptual model.  UML allows this in the form of qualified associations:
 
 
This says that the association of Portfolio to Position is "keyed" by some value called ProductID, which may or may not be the same as the ProductID attribute that we see in Position.  (See below...)  It also implies that, within a given Portfolio, there is at most one Position for any given product, though I'm not sure how to differentiate scenarios where a product resolves to a single Position vs. a collection of Positions.
 
From a conceptual modeling perspective, I think this construct has problems:
 
- Qualified associations are conceptually ambiguous. They may suggest certain cardinality or uniqueness constraints, but those should be made explicit as part of the conceptual model. Leaving that information in a map suggests that each map is its own little entity, an arbitrary association of some (typically primitive) key with some value, when in fact it is obscuring a deeper meaning.

- Information can be "hidden" inside keys without being properly attributed to a first-class entity in the model. In the above example, it wouldn't be uncommon to see ProductID omitted from the Position entity, because it's provided in the map.  This is bad practice. Maps in pubic interfaces are, at best, a programmatic convenience rooted in the "truth" of the model. We shouldn't be using maps to define truths that are not otherwise evident.

So I would argue that, instead of a qualified association, we should use an explicit uniqueness constraint.

(Note:  the constraint could be expressed in OCL, or maybe through some more compact and visual notation.  I'm using plain english here mainly because it's what I know. ;-)  )

This would also accommodate a more nuanced use case where Product ID resides on a separate Product entity, referenced by Position.  It would also accommodate multiple uniqueness constraints over the same association.  For example, if positions were ranked by some criteria (say "watch list priority"), it might also be the case that no two positions on a single portfolio can have the same rank.

Separately, there is the issue of whether Maps should be exposed through public APIs.  I would argue that they shouldn't be, for related reasons:

- Map-based APIs are not self-describing. While Map<Integer, Allocation> may conceptually relate an AllocationID to the Allocation having that ID, that relationship is not evident in the type, nor in the method signatures (put, containsKey, etc.) that operate on it. The Integer just looks like an arbitrary primitive value. We can use names of contextual objects to help clarify: For example, the getter that retrieves the map could be called getAllocationIdToAllocationMap(), and/or we could create a new class called AllocationId that wraps around the Integer value. But these may not be optimal choices. The more complex and nested the map structure, the more this problem of self-description manifests.

- Mutable maps are not fully encapsulated, and can be corrupted by client programs. In the above example, the underlying concptual model is that the context object exposing the map has a collection of Allocations, and a client program can retrieve an Allocation by its AllocationId. Accordingly, an internal constraint must hold that the AllocationId used as the key in any given map entry must be that of the Allocation that is the value for that entry. But the map doesn't enforce this business logic. It only enforces the uniqueness of the key.

- Maps tend to be used as special cases where there is only one lookup function (though you can expose multiple maps), where the lookup function only has one parameter, and where the parameter is unique over the value set (though the map value can be a Collection). While this meets the needs of simple use cases, lookups are potentially useful for a much broaderset of cases. If maps don't meet all of those cases, then exposing them through a public API tends to produce APIs that are unnaturally divergent.

In cases where a map is used as the internal representation, I'd favor a solution that exposes the map by a combination of two or maybe three methods:  (1) a getter that returns an immutable list of values; (2) a lookup method that returns the value(s) for a given key; and, if appropriate, (3) an add method that adds a new value, and populates the internal map according to the appropriate business rules.  In most cases, this add method won't need the keys, since the keys are derived directory or indirectly from the value being added.

So, do people generally agree that these guidelines help to keep the conceptual model and programming APIs closer to the business domain?
 
Thanks,
 
 - Ted

From: domaindrivendesign <at> yahoogroups.com [mailto:domaindrivendesign <at> yahoogroups.com] On Behalf Of Alasdair Gilmour
Sent: Wednesday, August 20, 2008 6:11 AM
To: domaindrivendesign <at> yahoogroups.com
Subject: Re: [domaindrivendesign] Maps in Public Interfaces Considered Harmful

If you're using generics then I'm not sure I agree with this. e.g.
 
public Map<Customer, List<Order>> getAllOrdersByCustomer() {..}
 
seems relatively clear to me as returning "a mapping of each customer to a list of orders", which makes sense even at a non-technical level. The alternative of, for example, creating a CustomerToListOfOrdersMapping class to do the same thing seems to introduce extra clutter for not much gain ...
 
IMHO the objective is not necessarily producing code that a non-technical business user can just sit down and read, even though you are trying to establish and maintain a common ubiquitous language.
 
Alasdair
 
> Hi,
>
> I'm new to this group, and don't mean to start a flame war with this
> somewhat provocative subject line.
>
> But I've been working on a complex domain model that will be available
> as part of a runtime framework. Some of the developers working on this
> have prototyped public interfaces that return maps, or dictionaries.
> I've instinctively avoided using maps in public APIs, and have recently
> had to examine my reasons for this more closely, for discussion within
> the team.
>
> In thinking through this, I'm increasingly of the opinion that maps
> shouldn't be regarded as first-class modeling abstractions, and in most
> cases shouldn't be exposed through public APIs. Before I get to the
> reasons for this, I'm looking for some pointers from the DDD community
> to past discussions, blog entries, references, etc. I did a cursory
> search of this mail group and a a few google searches, but didn't come
> up with much.
>
> Is this something that has been discussed or addressed in DDD, modeling
> or API design literature? Any background information would be much
> appreciated.
>
>Thanks and Best Regards,
>
>- Ted Epstein

NOTICE: If received in error, please destroy and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error.

__._,_.___

Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___
Alasdair Gilmour | 20 Aug 14:37

Re: Maps in Public Interfaces Considered Harmful

Yes, I would quite possibly do the same, depending on the model. This was just a contrived example to argue that returning a Map need not necessarily be a bad thing per se: I don't think it makes things hard to follow.
 
> I find maps are just not expressive. for the example
> Map<Customer, List<Order>> getAllOrdersByCustomer()
> I would opt to return an array of customers. the customer would
> encapsulate the orders.
> Customer[] GetAllCustomersWithOrders();
>
> foreach(Customer customer in GetAllCustomersWithOrders())
> foreach(Order order in Customer.Orders)
> {
> }
__._,_.___

Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___
Carfield Yim | 20 Aug 19:14

Re: Maps in Public Interfaces Considered Harmful

If the map or dictionaries are the  structure of  the object, this
probably not a good design.

http://c2.com/cgi/wiki?TellDontAsk

On 8/19/08, Ted Epstein <Ted.Epstein <at> morganstanley.com> wrote:
>
>  Hi,
>
>  I'm new to this group, and don't mean to start a flame war with this
>  somewhat provocative subject line.
>
>  But I've been working on a complex domain model that will be available
>  as part of a runtime framework.  Some of the developers working on this
>  have prototyped public interfaces that return maps, or dictionaries.
>  I've instinctively avoided using maps in public APIs, and have recently
>  had to examine my reasons for this more closely, for discussion within
>  the team.
>
>  In thinking through this, I'm increasingly of the opinion that maps
>  shouldn't be regarded as first-class modeling abstractions, and in most
>  cases shouldn't be exposed through public APIs.  Before I get to the
>  reasons for this, I'm looking for some pointers from the DDD community
>  to past discussions, blog entries, references, etc.   I did a cursory
>  search of this mail group and a a few google searches, but didn't come
>  up with much.
>
>  Is this something that has been discussed or addressed in DDD, modeling
>  or API design literature?  Any background information would be much
>  appreciated.
>
>  Thanks and Best Regards,
>
>   - Ted Epstein
>
>
>
>  ------------------------------------
>
>  Yahoo! Groups Links
>
>
>
>

------------------------------------

Marcos Machado | 20 Aug 02:08

Re: Maps in Public Interfaces Considered Harmful

Hi Ted Epstein,

Agreed. The "map format" (key/value) is very ok, maybe you  just need another abstraction.
Example:
The map "player => cards" would be "player has a deck" , deck implements some interfaces. Now you have the DDD + language framework functionalities.
 
Inté.


Hi,

I'm new to this group, and don't mean to start a flame war with this
somewhat provocative subject line.

But I've been working on a complex domain model that will be available
as part of a runtime framework. Some of the developers working on this
have prototyped public interfaces that return maps, or dictionaries.
I've instinctively avoided using maps in public APIs, and have recently
had to examine my reasons for this more closely, for discussion within
the team.

In thinking through this, I'm increasingly of the opinion that maps
shouldn't be regarded as first-class modeling abstractions, and in most
cases shouldn't be exposed through public APIs. Before I get to the
reasons for this, I'm looking for some pointers from the DDD community
to past discussions, blog entries, references, etc. I did a cursory
search of this mail group and a a few google searches, but didn't come
up with much.

Is this something that has been discussed or addressed in DDD, modeling
or API design literature? Any background information would be much
appreciated.

Thanks and Best Regards,

- Ted Epstein


__._,_.___

Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___
Michael Hunger | 21 Aug 04:04

Re: Maps in Public Interfaces Considered Harmful

I also tend to create real types for such kinds of structures that are kept in collections but are in reality
objects of 
the domain. I had a rather large refactoring last year where there were tons of maps holding either similiar
keys with 
different values as well as deeply nested (up to 4 levels) maps.

In the end we came up with a clean object graph containing just 6 domain objects and their attributes and relationships.
I did a (de)motivator on that:

http://www.jexp.de/demotivators/cascading_collections.jpg
(see also: http://jexp.de/index.php?n=Info.Demotivators)

In qi4j we also switched from having literal maps in our structure models to real types which encapsulate
the maps and 
add all the operations (Law of Demeter, encapsulation, DRY, IoC callbacks - internal iterator) that are
needed by 
callers (business logic) directly onto these classes which became full-flegded members of our design.

You can also then have interfaces exposing these operations and can add several implementations for them
(remote, 
performance critical, cached, simple) if needed. The main advantage is the encapsulation which removes
the need for 
defensive copying and the creation of the domain language on top of these structured collections.

Michael

------------------------------------

Alasdair Gilmour | 21 Aug 11:48

RE: Maps in Public Interfaces Considered Harmful

Hmm. I had been thinking more in terms of Maps as the return types of Repository query methods rather than Entity accessor methods.
 
I agree that using maps to model fundamental relationships between Entities instead of having them expressed directly in the Entities themselves seems wrong. So I guess I agree with the statement that "maps shouldn't be regarded as first-class modeling abstractions". However, in the case of (for example) a Repository method expressing a summary-type query where the relationship between the keys and values is not a fundamental contour of the domain, then I could see the use of a Map fitting reasonably well. These Maps would not need to be immutable either, as they don't in themselves represent a part of the domain.
 
As for Maps returned from an Entity having to be immutable: agreed, but this is no different for any collection (e.g. a List or a Set) returned from an Enity in this way. i.e. all  have to be made immutable to prevent a client blindsiding the Entity by modifying the collection directly.
 
Alasdair
__._,_.___

Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___

Gmane