Moldable Collection Wrapper

**Context:** Within your application domain, you not only have to deal with individual domain objects, but also composite entities (e.g., a book of notebook pages, a website of web pages), and collections of entities (e.g.,the result of query). page

**Problem:** How can you effectively provide custom tools for various kinds of collections of domain entities?

**Forces:** Collections are generic data structures with generic views that are not necessarily informative for your domain. Collections of domain entities may occur in various forms and contexts, such as the state of a composite object, or the result of a query. Providing custom views for each of these can be tedious and lead to much duplicated code.

**Solution:** Wrap collections of domain objects in a dedicated group wrapper, and give it dedicated views, actions and searches. In case there are multiple composite entities or collections that should share the same custom tools, factor these out into a common abstract superclass or Trait.

**Steps:** Create a dedicated wrapper for a collection of domain entities. An example is `WebPageGroup`, which wraps a collection web pages.

Have the collection wrapper use the `TGtGroupWithItems` trait. This trait has an items slot for the wrapped collection, and provides a large number of Collection methods to make the trait user behave like a Collection.

WebPageGroup

In case there are other classes that share views, actions and searches with the collection wrapper, consider putting these in a shared trait as well. For example, a website is also a collection of pages. We put the shared views and other behavior in the trait `TWebPageGroup`. The trait users are `AWebsite` and `WebPageGroup`.

TWebPageGroup

Wherever you need to show a collection of these objects, just forward the view to the wrapper to avoid duplicating the view code. See `TWebPageGroup>>#gtReachablePagesFor:`. If you have gtSearches, be sure they return the collection wrapper and not the raw collection, using the sendCategory: message, for example, `TWebPageGroup>>#gtSpotterForPageContents:`.

**Consequences:** Composite domain objects and collections of domain objects can be molded to support custom tools. Query results can be similarly molded. Wrapped collections can be made plug-compatible with raw collections.

**Related patterns:** A collection wrapper is similar to a Moldable Data Wrapper, since it also serves to make raw data moldable. The difference lies in the specifics of making the wrappers behave like collections, and make sure that any collections returned by queries are also wrapped.