[kforge-dev] domainmodel API design suggestions

John Bywater john.bywater at appropriatesoftwarefoundation.org
Fri Nov 17 17:51:30 UTC 2006


Jo Walsh wrote:

>dear Rufus, John, thankyou both for indulging me in pair- and triad-
>programming sessions last week and enduring my barrage of stupid
>questions and answering many of them.
>  
>

Jo, your questions weren't at all stupid. It's fantastic to have you 
involved. But there were a number of things that happened during this 
iteration which were quite stupid, things I either don't want to 
continue or don't want to continue with. Things which I found 
"challenging" during this iteration include:

1. Starting the iteration unable to plan, due to broken development 
systems: due to our policy of "eating our own dog food" combined with 
inadequate acceptance testing by the Product Owner of the product before 
upgrading the production service on which we depend. "Eating your own 
dog food" in a way that means that when the product is broken the 
process is also broken is an element of instability which must be and 
can only be stablised by rigourous acceptance testing of the product 
before it is considered ready for, and put into, production. Product 
Owners who don't have time to do rigourous acceptance testing don't have 
time to double up as software developers on the same project. Writing 
acceptance tests is the best way to take the work out of this repetitive 
task. But nevertheless, it is quite stupid to have things "poisoned" in 
this way.

2. Degrading the quality of the system for no good reason: it is 
regressive to worsen the names of the domain model instead of installing 
and using a stable Postgres version. This sort of thing is a double 
failure, because not only was an opportunity missed to progess the 
system, other time will be consumed fixing up things afterwards.

3. Making undisciplined changes to the code: it isn't acceptable to make 
code changes without runing the test suite before, and most importantly 
after changes have been made. Not being aware that the test suite has 
been broken simply because it wasn't run, but committing changes 
regardless is a terrible thing to impose on an agile software develop 
project.

In general, I have no desire to work on an agile software development 
project that doesn't plan at the start of an iteration, doesn't care 
much for good namings, can't be bothered to run a regression test suite 
before committing changes.

>I was just looking over my notes on the domainmodel interface and
>wondering about possible API reworking. I find the current API more
>*seems* overcomplex because it talks the language of the pattern
>process so literally. Well illustration is always best; the following
>is what my notes say now about how to query for instances of an object
>in the domain model:
>
>    from ckan.soleInstance import application
>    register = application.registry.getDomainClassRegister()
>    domainClasses = register.keys() 
>    domainClass = domainClasses['PackageName']
>    objectRegister = domainClass.createRegister()
>    objectRegister.findDomainObjects(filter)
>
>^^^^- note my four-space tabs, Rufus :P 
>
>I would like to be able to address domainmodel more idiomatically thus:
>
>    ...
>    classes = application.classes()
>    package = classes['Package']
>    package.list(filter) or package.search(filter)
>  
>

Which ideom is this? Do you have a name for it? Can you explain in which 
context it works, which forces it resolves, what are the limits of its 
applicability, why it pertains to the domainmodel package, and what the 
other choices are available?

Does it make sense to have the type of an instance be also responsible 
for collecting the set of instances of that type? I think it can make 
sense, but doesn't in our case:

We have a need to support two distinct responsibilities, and have 
written two distinct system objects for this: the DomainObject class, 
and the DomainObjectRegister class. Having one fall back onto the other 
means that a DomainObject instance can't instantiate a collection of 
aggregate domain objects without somehow producing an objective 
confusion (which Spinoza defines as mixing two distinct concepts, such 
as 'triangle' and 'square'; in our case 'type' and 'collection').

Of course, a very simple model, which only has "top level" collections 
with no notion of aggregates wouldn't suffer from such a confusion, 
because there would be no aggregates (subsets of the set of all 
instances of a type) to support. The requirements of the KnowledgeForge 
service (with things such as members of a project) led to the 
distinction I describe.

Of course, we could make the type (the DomainClass object) support 
delegation of collection-shaped responsibilites to the registry's 
register, which is a collection of all instances of a particular type.

Summary: the domainmodel code makes a distinction between type and 
collection, so that instances can hold subsets of instances without need 
for further conceptual complexity. But we didn't implement delegation by 
types to the collections of all instances of that type. But we can do that.

>And have the stuff below abstracted away a bit more. It is a beautiful
>if baroque design underneath, that works really well, but as an
>application developer i don't think i need to be so exposed to the
>inner workings and to the raw pattern language as the current interface
>necessitates.
>
>I wish i had the focus to accompany this with more constructive
>illustrations but it probably wants to be talked over a bit more
>before code written anyway, the latter is relatively unimportant?
>  
>

I would encourage you, at least at first, to understand the software as 
the product of adding tests and tested features to adequate to user 
stories selected by the Product Owner, closely followed by refactoring 
to improve the design of existing code. At no time have we tried to make 
it "correct" in some sense.

I wouldn't necessarily say that there was an API at the moment. There is 
a collection classes, each having responsibilities and collaborations, 
and therefore holding several attributes and methods. And so there are a 
number of de facto interfaces, but no API as such has been designed or 
documented. There are many voids in dm, kforge, ckan, all of which call 
out for further development work. But as neither KForge nor CKAN is a 
liquid-containing vessel, that doesn't consitute an inadequacy, but 
quite the opposite: the possible ways forward are more or less obvious.

That having been said, the notes you made on "how to query for instances 
of an object in the domain model" were based on my answering your 
question of how to access what you referred to as "meta" data. That's 
why I was steering you to the register of domain classes, each of which 
hold a meta object that describes a type of domain object.

As you really want the model data as such, rather than the model meta 
data, I would suggest taking a slightly different approach: use the 
domain object registers that have been instantiated on the registry 
directly (e.g. registry.projects).

But the real way to go is to write down what you really want as a test 
case. Then we can satisfy your test case. Then we can refactor to make a 
better interface, probably first making a FACADE (not shouting: patterns 
are often written in capitals). Creating a "better interface" first 
isn't the way to do agile development, and therefore isn't the way to 
work with the established grain of this project.

I have do desire to discuss improvements to software systems without 
reference to what that improvement is to adequate to, expressed normally 
as a unit test, because the process doesn't complete, and is therefore 
bound to be exhausting. I would like this to apply the idea of 
adequation to discussion of the qualities of a software system: you say 
it's baroque (ie overly complex?) but you don't say what you measure and 
judge its complexity against.

Certainly, I find your API simplifications to be oversimplifications 
because: for example an "application's classes" 
("application.classes()") aren't simply the registered domain object 
classes, but a great deal more. I would be happier with something like 
"application.domainClasses()").

Further, I don't think that there is a "pattern process". There are 
patterns of process, and of design. But the process of development 
itself isn't a pattern, and patterns don't consitute a process. So I 
wish to make a bref remark about the reason for having patterns in 
software systems and development processes:

If (as Ward Cunningham proposes) a program is a set of rules for solving 
a problem in the future, and programming is a discussion about such 
rules, then the first point of discussion may be that the near future 
will be more similar to the near past than the distant future will be to 
the distant past. Therefore it would make sense to shortcut understands 
in the future with understandings from the past, and carry forward 
things that work in the past (in a way that works) into the future, such 
that we can give most of our attention to what is *different* about the 
future ("embrace change").

To begin, if you can *see* the patterns, then I'm happy. Just to 
clarify, the "raw pattern language" is in the black and red Martin 
Fowler book, that you said you haven't read so far.

Perhaps you could find time to expose yourself to the real "raw pattern 
language" of enterprise applications before we next meet? Then you will 
be able to understand the application of enterprise applications that 
has been made on this project over the last 18+ months.

>I am probably working fulltime for the next couple of weeks (!) but
>would love to come back to Cambridge in 3 or 4 weeks time and have a
>more proper sprinting session then, and patch the docs up.
>  
>

Well done for getting the fulltime work! Good luck with it.

I look forward to continuing the f2f discussion again soon. I'm far from 
convinced that email has the bandwidth for a discussion of software 
design that hasn't been dramatically compressed by the application of 
design patterns.

With all best wishes, and lots of love!

John.

>love,
>
>
>jo
>  
>





More information about the kforge-dev mailing list