[kforge-dev] Taking stock of our current development strategy

John Bywater john.bywater at appropriatesoftwarefoundation.org
Tue Oct 17 14:44:54 UTC 2006


Rufus Pollock wrote:

> Dear All,
>
> Recently I've been thinking hard about the relationship of 
> domainmodel/kforge/ckan to the existing python webapp frameworks. We 
> started work on KForge (and its core which has now become domainmodel) 
> in April 2005 several months before either django or turbogears had 
> even appeared on the scene let alone got close to 1.0. Other notable 
> developments since we began work are the inclusion of (some) support 
> for inheritance in sqlobject (v0.7) and the maturation of the wsgi 
> effort (wsgiref is now part of python2.5).
>
> Below are some rough thoughts on where we are and where we can go. Let 
> me know what you think.


If we want to take stock of our current development strategy, I think I 
would prefer to see thought and discussion about the design of the 
KForge software system continue, pretty much, along the same lines on 
which it was begun, and which have enabled us to achieve what we have so 
far.

As I understand things, our current development strategy, if it 
resembles our past development strategy, is not to select from various 
degrees of usage of a framework, it is not to have a "core", and it 
isn't to produce a framework.

If we want to take stock of our current development strategy, we should 
remember that we have sustained development and produced working, 
well-factored, software applications because we have followed an agile 
approach, because we have applied patterns of enterprise application 
architecture, because there is a clear requirement clearly identified 
and recorded within the KForge and CKAN user stories, and because there 
is a little resource to cover some of the costs of the work.

If we want to take stock of our current development position, we should 
note the several aspects in the code which aren't well factored, the 
several aspects which don't conform to object-oriented norms (being 
object-oriented is a lot more than being "object-based", as Python is 
throughout), and other aspects which aren't well named. There are also a 
number of aspects which aren't under test.

> ## The Current Situation and its Origins ##


In the first instance, surely the most important thing about the current 
situation is that we have a working KForge system, and a running 
KnowledgeForge service. Whilst it's true that we have factored out many 
things into the domainmodel package, unless we plan to release this as a 
framework for use by others (which would require more work than is 
required for our own purpose of having well-factored code across a 
number of systems) we should think of it as minor to the actual systems, 
which are the major concerns of the development, and which stand in 
second place only to the user stories/acceptance tests (which are the 
most important objects of development, and which in turn standing in 
minor relation to the major objects of analysis: the working events, and 
working responses to those events).

>
> We now have our own 'mini-framework' in the form of the dm 
> (domainmodel) package which provides:
>
>   0. Standard plumbing including:
>      * system dictionary (+ config loading)
>      * logging
>      * some testing extras
>      * exceptions


Let's not propagate the phrase "standard plumbing". We don't have such 
an intermediate organising element in the code, so it's probably 
misleading and counter productive to have one in our discussions.

Instead, I would much prefer to employ the vocabulary contained within 
the catalogue of patterns of enterprise application architecture:

http://www.martinfowler.com/eaaCatalog/

>   1. persistence layer (using sqlobject)


Actually, the dm package doesn't provide a persistence layer, but does 
provide a domain model meta data-driven data mapper layer (dm/db.py):
http://www.martinfowler.com/eaaCatalog/dataMapper.html

It is only the KForge and the CKAN system that have persistence layers 
(formed from dm.db + sqlobject + RDBMS).

But dm just provides a mapping layer. Specifically, it provides KForge 
with Concrete Table Inheritance and Metadata Mapping, and uses sqlobject 
to do that with postgres.

http://www.martinfowler.com/eaaCatalog/concreteTableInheritance.html
http://www.martinfowler.com/eaaCatalog/metadataMapping.html


>   2. domain model (objects + registers)


+ domain logic

Domain Model:
http://www.martinfowler.com/eaaCatalog/domainModel.html

Registry:
http://www.martinfowler.com/eaaCatalog/registry.html


>      * as well as some very basic objects (NamedDomainObject, 
> DatedDomainObject etc)


I don't think those class names actually exist: we have 
SimpleNamedObject, StandardObject, etc.

>      * and some non-standard ones (e.g. Person, access control stuff)


Person normally extends StandardObject, so it doesn't really work to say 
they are non-standard. It may be better to say they are non-simple, or 
standard extensions, or that there is a default, basic Person object 
that can easily be extended or replaced in a dm application.

>   3. command layer (i'm still not sure what the prognosis for this is 
> -- do we really need it?)


We don't have a command layer. We have a (broken) service layer 
(consisting of an incomplete, misunderstood, and now neglected set of 
commands).

http://www.martinfowler.com/eaaCatalog/serviceLayer.html

>   4. common webapp code (including an admin interface)
>      * we do use django (in a very old version) to:
>        * provide a web server
>        * do url mapping,
>        * do templating
>        * help out with our manipulators


Also: html decoding, mod_python event handling... common web app 
presentation layer stuff, as you say. We decided to use Django to cover 
these concerns.

>   5. A plugin system with a limited form of event handling and 
> notification


It probably makes more sense to talk about it as a way to extend the 
domain model, where plugins are notified of, and may handle, domain 
model object lifetime events. It isn't an abstract publish-subscribe 
framework, it doesn't make use of one, and it doesn't propagate events 
that aren't domain model object lifetime events. But that's because it 
wasn't written to.

I suppose it isn't that the form of event handling and notification is 
limited, but rather that the concerns of extending the domain model at 
run time don't call for a more sophisticated event system. And because 
we don't have other event notification/handling aspects, we didn't hook 
up a more general event-notification system.

>
> The key question is how much of what we have done is specific to our 
> projects and how much we could get from using an external framework.


I disagree: I'm not even sure if it's a good question: even if there is 
a good and easily obtainable answer to that question, it still wouldn't 
even begin to consitute an agile, patterned, development 
approach/strategy. I suspect there isn't one key question, but rather a 
number of aparallel concerns that have more or less adequate answers 
within the agile (diachronic) and pattern language (synchronic) strategies.

http://www.answers.com/topic/diachronic
http://www.answers.com/topic/synchronic

>
> ## The Options ##
>
> 1. Stay as we are in the main


I would agree with: "continue to develop as we have been developing".

>
>   * If we do I suggest replacing some parts of django (e.g. templating)


It would be really simple to use a different template processor. It 
would be much less simple to port all the templates. I think Django 
templates are fine. Why do you suggest replacing Django templating? We 
decided to use Django for the KForge and CKAN presentation layers.

>   * might be able to increase reuse in certain areas by using e.g. 
> wsgi more heavily


Yes. I think we should continue by increasing reuse, made possible 
through test-driven development and merciless refactoring. That's the 
way we'll easily be able to do wsgi things, and other things that may 
turn up and be desirable.

>   * could we pare back our domain model to be closer to sqlobject (or 
> if not articulate clearly what we are gaining from having our own 
> domain model base objects)


No, we can't pare our domain model back to be closer to sqlobject, 
because we aren't trying to implement a domain object to relational 
database mapper, but rather an effective domain model (a "domain logic" 
pattern, not an "object-relational structural" pattern).

Sqlobject isn't a domain model, even with support for inheritance (which 
would simply allow for class table inheritance - an "object-relational 
structural" pattern). We use sqlobject to map values between domain 
model objects and database table records, to form queries, to hold and 
iterate over query results, to maintain a single instance of any object 
in memory, and so on. These are data mapping concerns. Domain model 
concerns are constructed to be separate from mapping concerns. I say 
constructed to be separate because it is quite possible (and quite easy) 
to mix the two, and produce a working confusion. I often feel quite 
anxious about this, because we don't seem to be on the same page at all 
with making and maintaining a consensus of conceptual distinction. I 
feel my utterances are simple: I repeat Fowler because Fowler appears to 
repeat things that others have found to work. I trust Fowler not to say 
things he isn't sure about without declaring that, and in turn I try not 
to repeat things I'm not sure about without such declaration. But I then 
hope (and to some extent I expect) you will repeat my utterances, which 
aren't properly mine, or Fowlers', but of the fourth person singular. So 
what happens?

But with sqlobject, there's too much internal method renaming, calls to 
__init__, and so on to be a clean domain object base class. As a domain 
object isn't concerned about the mapping to RDBMS, a domain object 
should not inherit from sqlobject, but could instead make use of 
sqlobject by delgation. This is indeed what happens in dm/db.py.

However, the advantages of creating a domain model are many, have 
nothing whatsoever to do with data mapping, persistence, or relational 
tables, but about getting the conceptions to develop on an abstract 
plane: a model of the problem domain.

http://domaindrivendesign.org/books/foreword.html

Please read these patterns (perhaps buy the book I lent you, as the full 
descriptions aren't published on the wiki):
http://www.martinfowler.com/eaaCatalog/domainModel.html
http://www.martinfowler.com/eaaCatalog/concreteTableInheritance.html
http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
http://www.martinfowler.com/eaaCatalog/classTableInheritance.html
http://www.martinfowler.com/eaaCatalog/associationTableMapping.html
http://www.martinfowler.com/eaaCatalog/inheritanceMappers.html
http://www.martinfowler.com/eaaCatalog/metadataMapping.html
http://www.martinfowler.com/eaaCatalog/repository.html
http://www.martinfowler.com/eaaCatalog/foreignKeyMapping.html

Like some of the other issues here, we've talked about this several 
times in similar ways.

In general, I don't want to discuss enterprise software application 
architecture without reference to these patterns. In particular, I don't 
enjoy discussing KForge software without reference to previous 
discussions about the application of these patterns to the support of 
the User Stories of the Open Knowledge Foundation.


>
> 2. Move fully to turbogears or django or ...
>
> There are large benefits to using as much of a framework such as tg or 
> django as possible in terms of sharing in the combined work of many 
> other hands (and in contributing to that).


As I've said previously on this list, I'm not convinced that KForge is 
simply a "web application". That KForge integrates other web 
applications indicates that the concerns of KForge go beyond the 
concerns of a normal web application, and so trying "fully" to use a web 
application framework will be frustrating, because (as we found with 
Django) opportunities to extend the objects of the framework are likely 
to be inadequate where the system doesn't follow the patterns of 
enterprise application architecture observed, recorded, and published by 
Martin Fowler. And Django doesn't even flirt with these patterns (except 
for MVC, but then there's dicussion about how Django isn't really MVC 
anyway...). We've gone over all this already.

>
> The question is to what extent can we do so? To really get much more 
> integration we need to be able to plug more directly into the domain 
> model. The big question then is whether we can do inheritance.


I don't understand "to plug more directly into the domain model", and I 
don't see any connection between on the one hand variations of table 
inheritance and data mapping, and on the other hand elements of 
presentation layer in Django depending on their domain model interface 
(if that's what you're talking about). The two concerns appear to me to 
be separate.

>
> Furthermore while e.g. turbogears provides some kind of access control 
> model it is not clear how suitable it is to our situation (e.g. to 
> kforge).


Sure.

> It might well turn out that adapting tg to our purposes would actually 
> entail more work that it has taken to get our system working in the 
> first place.


I agree with this last point: I expect it isn't a productive move. The 
recent history of software development is that code reuse has failed, 
that the limiting factor in software development is the formation of 
concepts (it's astonishing how limiting this can be), and so reuse moved 
up to the conceptual level, where the form of conceptual reuse, and the 
basis for communication amongst developers, is the named pattern. I've 
said this several times to you now, no?

http://appropriatesoftware.net/wiki?NamedPattern

Applying some of the patterns, like building a good object-relational 
mapper takes lots of time, and the recommendation (in PoEAA) is to use a 
third party component (like sqlobject). But most of the others are very 
straightforward, and are perhaps best implemented freshly each time.

Best regards,

John.

PS This email has taken me several hours to write. It repeats many 
things that we've spent similar amount of time going over. So what 
happens? Do you think I'm mistaken, or do you not understand what I'm 
saying, or suspect it somehow of a hidden agenda? Or do you forget? I'm 
really not sure where the discussion is breaking down, and why it's 
going round in this circle. But it's kinda hard work. I don't want to 
die trying to explain these things. If we can't form a consensus, and 
align our thinking, perhaps we should try operating different roles 
where I act as developer (decide technical concerns, and develop code 
adequate for your user stories) and you act as product owner (decide 
business concerns, develop user stories and acceptance tests, and 
determine whether code adequates to your user stories). I would prefer 
to form an adequate concensus about software development practice, but 
if we can't achieve that I feel it would better to focus each of us 
exclusively on one role.




More information about the kforge-dev mailing list