With the introduction of OO language features in the ABL, tried and proven OO design patterns can now be more readily leveraged in the development of OpenEdge applications. Discussion of some of the more common OO design patterns can also serve as a useful way of introducing more OO concepts to the PSDN/OpenEdge community. One of the more common and simpler OO design patterns is the Repository pattern.
The Repository Pattern is a very popular way to abstract a domain model from the underlying data mapping and data access by providing access to domain objects (business objects) via a collection interface. For example, the business objects can form collections under a single repository object such as:
end interface.
The data access/mapping and data update for the domain objects in these collections is performed by an underlying set of Data Access Objects.
There has been some prior debate about the pros and cons of a true domain model approach versus a static business object approach. I would be very interested to hear people's experiences with the domain model approach if they have tried it - both good and bad, and people's thoughts about the benefits and drawbacks.
Phil
With the introduction of OO language features in the ABL, tried and proven OO design patterns can now be more readily leveraged in the development of OpenEdge applications.
Only if people starting writing .cls files instead of .p, .i, and .w ... which doesn't seem to be a very broad movement yet. Still, I heartily applaud your point.
The Repository Pattern is a very popular way to abstract a domain model from the underlying data mapping and data access by providing access to domain objects (business objects) via a collection interface.
I'm not sure that we are starting off with the same sense about what a Repository is all about. It is the Finder and Mapper (or other versions of implementing the data access layer) which provide the abstraction and isolation of the domain model from the data access. To me, the function of a Repository is more that of a cache.
"A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection." from http://www.martinfowler.com/eaaCatalog/repository.html
In this sense, the Repository provides a function not unlike the -B database cache, isolating the program which is using or creating the data from the need to manage the actual physical update to and from disk.
Thus, it seems to me that a Repository is, in effect, a Collection with an active hidden aspect in which it manages the persistence of any changes made to it. This means that we have two different questions or topics here, i.e., the Collection itself, and any issues related to this behind-the-scenes synchronization.
Collections as such are unquestionably useful, even necessary in some form. This is one of the reasons why one of my first framework projects in 10.1A was a set of generic Collection and Map Classes ( http://www.oehive.org/CollectionClasses ). The biggest negative about that implementation is simply a certain inelegance which results from not having generics and/or object versions of primitives so that one needs rather more specific classes than one would wish.
The one issue of "taste" I see about the use of generic Collection Classes like this versus domain-specific Collection Classes is the necessity of casting the generic object in the collection to a specific domain before being able to do operations on it. The flip side is that a handful of Collection and Map classes suffice to handle a very large percentage of the need at a huge savings in development and a great uniformity of operation.
As to the hidden operations, I think this depends a great deal on context. If one has a collection of ... to take a potential example from the AuthEdge context ... Dealers, i.e., something that one expects to remain highly static and where there might be a need to validate and drill down while in a context where dealer information would need to come remotely, then a Repository seems like a good solution. It can be primed at start up or first use.
Off the cuff, I would say that the big potential issue with an "active" collection would be transaction atomicity on updates. If I make a change to an object in a local collection with the expectation of this change being persisted, do I really want to rely on some behind the scenes update process or do I want to use an explicit SaveChanges operation on the domain object which can be directly enclosed within a transaction including any related or dependent changes. My inclinations, being paranoid, leans toward the latter.
Perhaps you are getting at something else, however?
The Repository Pattern is a very popular way to
abstract a domain model from the underlying data
mapping and data access by providing access to domain
objects (business objects) via a collection
interface.
I'm not sure that we are starting off with the same
sense about what a Repository is all about. It is
the Finder and Mapper (or other versions of
implementing the data access layer) which provide the
abstraction and isolation of the domain model from
the data access. To me, the function of a Repository
is more that of a cache.
Yes, but whichever underlying data access/caching mechanism that is used, the domain model is still presented as a conceptually simple set of of collections accessed from a root Repository object. Sure, these objects in these collections could be cached... or if not yet resident in cache then retrieved from the database into a cache.
"A Repository mediates between the domain and data
mapping layers, acting like an in-memory domain
object collection." from
http://www.martinfowler.com/eaaCatalog/repository.html
That's right. There's a number of Fowler's patterns that I believe are relevant and could be readily applied in an implementation of OERA-based OpenEdge application.
In this sense, the Repository provides a function not
unlike the -B database cache, isolating the program
which is using or creating the data from the need to
manage the actual physical update to and from disk.
That's a great analogy... especially for those folks more familiar with traditional Progress/OpenEdge than OO. The collection interface approach to accessing domain objects is also conceptually significant.
Thus, it seems to me that a Repository is, in effect,
a Collection with an active hidden aspect in which it
manages the persistence of any changes made to it.
This means that we have two different questions or
topics here, i.e., the Collection itself, and any
issues related to this behind-the-scenes
synchronization.
Sure.
Collections as such are unquestionably useful, even
necessary in some form. This is one of the reasons
why one of my first framework projects in 10.1A was a
set of generic Collection and Map Classes (
http://www.oehive.org/CollectionClasses ). The
biggest negative about that implementation is simply
a certain inelegance which results from not having
generics and/or object versions of primitives so that
one needs rather more specific classes than one would
wish.
It certainly would be nice to have generics and/or more suitable primitive data types in the ABL to make the implementation of collections a little less awkward (although I've read several harsh criticisms of generics). Some syntactic sugar which would certainly be nice to have. But a saving grace would be that if the implementation faithfully follows the model, then regenerating the code from the model to a later version of ABL should be reasonably straight forward.
The one issue of "taste" I see about the use of
generic Collection Classes like this versus
domain-specific Collection Classes is the necessity
of casting the generic object in the collection to a
specific domain before being able to do operations on
it. The flip side is that a handful of Collection
and Map classes suffice to handle a very large
percentage of the need at a huge savings in
development and a great uniformity of operation.
Casting to the generic object is not ideal but it works.
As to the hidden operations, I think this depends a
great deal on context. If one has a collection of
... to take a potential example from the AuthEdge
context ... Dealers, i.e., something that one expects
to remain highly static and where there might be a
need to validate and drill down while in a context
where dealer information would need to come remotely,
then a Repository seems like a good solution. It can
be primed at start up or first use.
Preloading some collections on startup is certainly an interesting idea. I could also imagine that if combined with some flexible configuration options then this idea should almost be a no-brainer.
Off the cuff, I would say that the big potential
issue with an "active" collection would be
transaction atomicity on updates. If I make a change
to an object in a local collection with the
expectation of this change being persisted, do I
really want to rely on some behind the scenes update
process or do I want to use an explicit SaveChanges
operation on the domain object which can be directly
enclosed within a transaction including any related
or dependent changes. My inclinations, being
paranoid, leans toward the latter.
I agree. It's my inclination also. But I believe that the SaveChanges operation on a specific domain object (and dependents) is conceptually simpler and simpler to implement atomic transactions than the SaveChanges on a static business entity component which accepts a potentially large and complex PDS.
Perhaps you are getting at something else, however?
No. I just wanted to stimulate some discussion about the possible approaches that the advent of OO opens up. I would also be interested in discussing the various approaches to underlying data access/persistence mechanism.
Phil
Yes, but whichever underlying data access/caching mechanism that is used, the domain model is still presented as a conceptually simple set of of collections accessed from a root Repository object.
I get the sense that you are contrasting something with something else and I'm not sure what the two pieces are.
or if not yet resident in cache then retrieved from the database into a cache.
I.e., potentially lazy resolution.
That's right. There's a number of Fowler's patterns that I believe are relevant and could be readily applied in an implementation of OERA-based OpenEdge application.
Amen! ... at least if one starts programming in .cls ... unlike PSC!
The collection interface approach to accessing domain objects is also conceptually significant.
Again, I get the sense of contrast ... but not sure between what and what.
although I've read several harsh criticisms of generics
I view them as one of those things to be used carefully, like method overloading. They are very handy, even key, in making a compact, clean, simple framework, but one is less sure one wants the typical domain programmer fiddling with them.
hen regenerating the code from the model to a later version of ABL should be reasonably straight forward.
At least if one can keep people from breaking the link to the model!
the SaveChanges operation on a specific domain object (and dependents) is conceptually simpler and simpler to implement atomic transactions than the SaveChanges on a static business entity component which accepts a potentially large and complex PDS.
Of course, the SaveChanges ultimately has to be at the level of atomicity, no matter how complex that might be. However, a SaveChanges method in some complex object can certainly be composed of multiple SaveChanges calls on simpler objects.
I would also be interested in discussing the various approaches to underlying data access/persistence mechanism.
I have done some work on this with the aim of publishing it, but at this point I think I will have to wait until 10.1B FCS since I would want the model to include the structure I posted in the example to the beta forum.
I get the sense that you are contrasting something
with something else and I'm not sure what the two
pieces are.
No, not really. , "Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects". I'm just emphasizing the "collection-like interface for accessing domain objects".
or if not yet resident in cache then retrieved
from the database into a cache.
I.e., potentially lazy resolution.
Fowler's "Lazy Load" pattern is definitely relevant to the data access going on behind the Repository abstraction.
That's right. There's a number of Fowler's
patterns that I believe are relevant and could be
readily applied in an implementation of OERA-based
OpenEdge application.
Amen! ... at least if one starts programming in .cls
... unlike PSC!
I'm sure there will be more .cls examples after 10.1B FCS.
although I've read several harsh criticisms of
generics
I view them as one of those things to be used
carefully, like method overloading. They are very
handy, even key, in making a compact, clean, simple
framework, but one is less sure one wants the typical
domain programmer fiddling with them.
I definitely agree. Generics are very powerful but could be more than enough rope for some.
hen regenerating the code from the model to a
later version of ABL should be reasonably straight
forward.
At least if one can keep people from breaking the
link to the model!
Some good tools can solve that. Enterprise Architect anyone.
the SaveChanges operation on a specific domain
object (and dependents) is conceptually simpler and
simpler to implement atomic transactions than the
SaveChanges on a static business entity component
which accepts a potentially large and complex
PDS.
Of course, the SaveChanges ultimately has to be at
the level of atomicity, no matter how complex that
might be. However, a SaveChanges method in some
complex object can certainly be composed of multiple
SaveChanges calls on simpler objects.
Of course.
I would also be interested in discussing the
various approaches to underlying data
access/persistence mechanism.
I have done some work on this with the aim of
publishing it, but at this point I think I will have
to wait until 10.1B FCS since I would want the model
to include the structure I posted in the example to
the beta forum.
Yes. I think a lot of people are waiting for FCS. There should be quite a flurry of writing and publishing once it does.
Phil
I'm just emphasizing the "collection-like interface for accessing domain objects".
OK, why are you emphasizing it. To me, one is likely to need both individual domain objects and collections thereof. Some collections will be transitory and some will behave like a repository.
That's what I expected after 10.1A FCS.
Generics are very powerful but could be more than enough rope for some.
Some people only need a short piece of string!
Some good tools can solve that. Enterprise Architect anyone
Somehow, I am skeptical that even EA has unbreakable round trip engineering ... someone will figure out how to break it in the same way that people edit files that then can no longer be read by the AppBuilder.
There should be quite a flurry of writing and publishing once it does.
I'll attempt to do my part ... we'll see who else does. It isn't as if there is such an overwhelming raft of new OO stuff in 10.1B that one couldn't do any reasonable work until it comes along. The only reason for me to wait on the data access piece is that I rather like that thing I did in the example posted.
I'm just emphasizing the "collection-like
interface for accessing domain objects".
OK, why are you emphasizing it. To me, one is likely
to need both individual domain objects and
collections thereof. Some collections will be
transitory and some will behave like a repository.
I am emphasizing it because those who are new to OO are probably unfamiliar with a domain object model approach (which is distinctly different from the business logic component approach), collections, and collection interfaces to access domain objects. Of course we will need both domain object classes and collections. And yes, collections will be used in other ways besides providing a means to access domain objects via the repository pattern.
I'm sure there will be more .cls examples after
10.1B FCS.
That's what I expected after 10.1A FCS.
There will always be disagreements over priorities and allocation of resources.
Somehow, I am skeptical that even EA has unbreakable
round trip engineering ... someone will figure out
how to break it in the same way that people edit
files that then can no longer be read by the
AppBuilder.
Skepticism is healthy. EA's round-trip engineering is certainly not unbreakable. But it is quite functional and reasonably robust... certainly to the extent that there are few objections using it to keep code and model in sync.
There should be quite a flurry of writing and
publishing once it does.
I'll attempt to do my part ... we'll see who else
does. It isn't as if there is such an overwhelming
raft of new OO stuff in 10.1B that one couldn't do
any reasonable work until it comes along. The only
reason for me to wait on the data access piece is
that I rather like that thing I did in the example
posted.
I'll do a search through the beta forum and have a look what you have posted to date concerning data access.
Phil
There will always be disagreements over priorities and allocation of resources.
Perhaps OO needs a specific champion ...
EA's round-trip engineering is certainly not unbreakable. But it is quite functional and reasonably robust... certainly to the extent that there are few objections using it to keep code and model in sync.
I don't suppose there are any ABL examples we can look at and play with ...
I'll do a search through the beta forum and have a look what you have posted to date concerning data access.
It's here:
http://www.psdn.com/library/thread.jspa?threadID=2460&tstart=0
Note that the focus of the use case is not data access, but that is the context. The part I liked was the domain class.