It's not clear what problem(s) you are actually trying to solve here in
these paragraphs, so your ideas come across as a little abstract.
Firstly, you seem to be conflating core and application, which is a
misunderstanding. django.contrib is just one directory where
applications live. It's only "special" in that it's owned by Django
itself -- i.e. it's where the maintainers might put any apps we ship
with Django. But that's the complete limit of it's specialness. Apps are
just importable Python packages. Stemming the proliferation of
applications sounds like an anti-problem: we want to encourage people to
write apps, not stop them.
Secondly, keep in mind that infinite flexibility is not necessarily a
pragmatic goal. Partly because it means you spend forever tweaking the
interfaces between sections and it actually restricts what you can do
(because any single change has enormous external implications). Django
already allows a lot of replacement of core components. ORM, templates
and URL dispatching can all be done by other means if you like. You can
use whatever web front-end you like and we have plans to fix things like
the slight WSGI incompatibilities we currently have. Besides those
things, there's not much else in core when you break it down. In most
cases, it's not even a lot of code to do these replacements.
Contrib apps can be used or not as you like. You mention a couple of
examples where contrib apps allow some internal customisation. Could you
be more concrete about what is missing.
Remember that Django aims to provide something that is "sufficiently
good" for creating production-capable websites. As a bonus (and by
design), if you want to replace things, you can. However we're not
TurboGears where they are intentionally only building interfaces between
existing components. If somebody wants that type of changeability, then
TurboGears is probably what they want.
So maybe there is a particular thing you are trying to solve here. If
so, have another shot at explaining what it is, with real-world
examples. Which pieces aren't flexible enough? Abstract conversations
aren't particularly productive (and you'll see that they've come up here
before) because there's no path towards any sort of goal that comes out
of them. Django strives to find a reasonable between "batteries
includes" and allowing customisation. Where do you want to tweak that
balance?
Regards,
Malcolm
--
Everything is _not_ based on faith... take my word for it.
http://www.pointy-stick.com/blog/
It's not clear what problem(s) you are actually trying to solve here in
these paragraphs, so your ideas come across as a little abstract.
Firstly, you seem to be conflating core and application, which is a
misunderstanding. django.contrib is just one directory where
applications live. It's only "special" in that it's owned by Django
itself -- i.e. it's where the maintainers might put any apps we ship
with Django. But that's the complete limit of it's specialness. Apps are
just importable Python packages. Stemming the proliferation of
applications sounds like an anti-problem: we want to encourage people to
write apps, not stop them.
Secondly, keep in mind that infinite flexibility is not necessarily a
pragmatic goal. Partly because it means you spend forever tweaking the
interfaces between sections and it actually restricts what you can do
(because any single change has enormous external implications). Django
already allows a lot of replacement of core components. ORM, templates
and URL dispatching can all be done by other means if you like. You can
use whatever web front-end you like and we have plans to fix things like
the slight WSGI incompatibilities we currently have. Besides those
things, there's not much else in core when you break it down. In most
cases, it's not even a lot of code to do these replacements.
So maybe there is a particular thing you are trying to solve here. If
so, have another shot at explaining what it is, with real-world
examples. Which pieces aren't flexible enough? Abstract conversations
aren't particularly productive (and you'll see that they've come up here
before) because there's no path towards any sort of goal that comes out
of them. Django strives to find a reasonable between "batteries
includes" and allowing customisation. Where do you want to tweak that
balance?
--
Best regards, Yuri V. Baburov, ICQ# 99934676, Skype: yuri.baburov,
MSN: bu...@live.com
On 9/7/07, Joshua 'jag' Ginsberg <dja...@flowtheory.net> wrote:
> Problems:
> 1) While there is a good degree of drop-in replacability of parts in the
> Django stack as I outlined (db backend, authentication backend, etc.) there
> is not a clean way for programmers to grok what specific contract various
> components have to comply.
>
> An example: How do I implement a template loader? While I can trace the
> behavior of the existing template loaders and try to guess what each of the
> methods do and the data that their arguments and return values should
> contain, there is not a defined contractual interface for a template loader.
> I have no way of knowing that the "filepath" returned from
> load_template_source will then be expected to be used by Template's origin
> kwarg for reloading the source. The Django team put so much effort into
> making these parts componentized without having a component system to
> delineate and document contracted interfaces.
This sounds like a documentation problem, not a code problem. Template
loaders are indeed under-documented, and it seems to me that
documentation alone would solve this problem.
> 2) There is not replaceability for every component unless such
> replaceability is specifically engineered in by the Django team.
>
> An example: I want to replace the session backend with something not
> database bound. I can't until Django commits an extensibility for that
> interface. Or I want to have User objects that implement additional methods,
> but if I subclass it then all of the other apps won't use instances of my
> subclass and won't have access to my extensions.
But the same is true of interfaces too. Unless the Django developers
expected for something to be extended, they wouldn't provide an
interface for it, and thus you'd have to wait for one in order to hook
into it. So, while you have a fair point that this is a slight
problem, interfaces wouldn't make anything better, so it's a wash.
> 3) Without some sort of agreed upon standards to support interaction between
> apps, we will not be able to harness the wealth of django apps being written
> right now into complete, integrated sites.
>
> An example: I like Suzy Creamcheese's Blog application but she used
> django.contrib.comments in it, and I want Joe Schmoe's slashdot style
> commenting system. I also want people who have blogs to be able to post
> their own photos, but Suzy Creamcheese's Blog application uses a BlogAuthor
> model for biographical data and needs it set as the PROFILE model and John
> Shaft's photo gallery application uses a Profile model for biographical data
> and also needs it set as the PROFILE model. I can't integrate these without
> hacking on them. But if Suzy wrote her Blog application to implement IBlog
> and IBlogManager which contained extension points for IComment and
> ICommentManager, I could integrate the two systems without having to alter
> code. And if both the BlogAuthor model and the Profile model implemented the
> same interface then I could still use them together as User can provide the
> extension point for that interface.
Now, this point I might not be understanding correctly. Are you asking
for Django's core to define an interface for each and every potential
use someone might find for it? While I can understand the marginal
benefit such interfaces might provide, I can't imagine it would be
worthwhile to require Django itself to be responsible for all of
these.
After all, what happens when somebody finds something new to do with
Django, or they'd like to add an attribute or method to an existing
interface? Well, then we go back to your second point, where we have
to wait for the Django team to agree on the changes and implement it,
before anybody can do anything.
> But I don't think we necessarily want to as a community try to produce
> canonical, standard applications and continue expanding contrib for the
> utility applications that we all reimplement.
But that seems to be almost exactly what you're asking for, by having
Django core define all those interfaces. Sure, the interfaces aren't
the implementations, so there's nothing to "override", but you're
still asking the framework to keep a registry of potential
applications.
> Perhaps at this young age of Django, it's inappropriate to discuss a
> component framework and just rely on the solid engineering to have fuzzily
> defined components. But there is not (necessarily) the same sort of
> discoverability, rigid contractual obligation, or interchangeability of
> these components. Like I said, we have all of the intention of a
> componentized framework without any of the actual code to make it work like
> one should.
And this is the point I usually get to when explaining why I don't
like interfaces, and it's at the heart of why I'm not a fan of Java.
Essentially, you're asking for the code to make sure that programmers
don't make mistakes. You're asking for developers to not have to read
(or write!) proper documentation. Personally, I absolutely love Duck
Typing, and as long as there's sufficient documentation on what is
considered a "duck", then anybody can make their own and we're all
happy. I see no need to expect code to be responsible for making sure
that programmers are doing their jobs.
Again, I probably shouldn't have gotten into this, so please disregard
my comments if I'm not making any sense.
-Gul
Except that interfaces in Trac's component system (and AFAIK also in
Zope or PyProtocols) aren't about typing *at all*; they're about
protocols for using, extending, or replacing functionality
(components). It might help to actually read up on stuff before
commenting. For your convenience here's a link:
<http://trac.edgewall.org/wiki/TracDev/ComponentArchitecture>
(I'm not really going to weigh in on whether this whole thing would
be a good match for Django, just defending a design against
uninformed comments; I'm also not saying that the design is in anyway
perfect; there's definitely room for improvement).
Cheers,
Chris
--
Christopher Lenz
cmlenz at gmx.de
http://www.cmlenz.net/
This was design error of applications creators.
Let's think what Django could do to prevent such errors.
I can see abstract idea. But don't see right implementation idea.
1) You can do this all without all javaish interfaces.
2) Interfaces are not python way of doing stuff. google: duck typing.
Please take my arguments into account and reconsider your idea with them.
And I should also explain how this benefit could indeed be achieved
without modifying Django core. As strange as this may sound,
community-established standards could work. If we had a central place
to discuss, standardize, document and publish common paradigms,
developers could easily find the information they need when building
their ducks.
This could be as simple as setting up a website, something like
djangostandards.org or something, with tools to discuss and document
these things. Then, as long as the site makes it easy to find existing
standards, developers will easily see what they'll be expected to
provide if they want to be interoperable. Again, it all comes down to
documentation. Using interface explicitly in code is just a band-aid
to allow developers to read and write less documentation.
-Gul
Personally I'd rather solve this with documentation.
> 2) There is not replaceability for every component unless such
> replaceability is specifically engineered in by the Django team.
Sure there is. Want an alternative session component? Import it and
use it according to its documentation.
> 3) Without some sort of agreed upon standards to support interaction between
> apps, we will not be able to harness the wealth of django apps being written
> right now into complete, integrated sites.
I dunno, I've managed it pretty well.
Offhand I'd be -1 on anything that makes Django's codebase more
complex; there are very few things that can be solved by "component
interfaces" that can't also be solved by good documentation, and the
documentation carries a lot of other benefits with it besides that.
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
> [...] if they both implemented IPerson, IPostalAddress, and
> IPhoneNumber, [...]
... and that's the point where my eyes glaze over and smoke starts
coming out of my ears.
I don't know you, but I'll hazard a guess at your background: Java, right?
The thing you have to understand is that Django tries *very* hard to
be "Pythonic", which usually means doing away with things like
interfaces, components, and overwhelming architecture astronauting. Do
a Google search for "duck typing"; that's how we do interfaces (as it
were) around here.
Now, you're right about a *lot* of your criticisms -- e.g. writing a
template loader shouldn't require a spin through the source code --
but the Django way is to view that as a documentation problem, not a
design issue. Database backends are another example -- they are
pluggable, but almost completely undocumented.
Our culture is to fix these bugs in English, not Python; suggestions
that involve things like "IDatabaseComponent" are going to elicit a
gag reflex from most Django programmers. In fact, just writing that
word made me puke a little in my mouth. Don't worry, I swallowed it.
> [...] I don't think we necessarily want to as a community try to produce
> canonical, standard applications and continue expanding contrib [...]
Yeah, I don't know of a nice way to say this... you're wrong; that's
*exactly* what we (or and least I) would like to do. If there's a
piece of code that does Feature X in way that feels consistant with
Django, we very much want it to be part of django.contrib, and we want
to encourage people to use it whenever possible. Django-tagging is a
great ecample here.
The only reason we've not expanded django.contrib more is that we've
not firmly established a good process for getting apps into contrib
and keeping them up-to-date.
I think you're a bit mistaken about our core philosophy, so I'll try
to sum it up: every single piece of code that's part of Django exists
because it solves a very specific, real-world problem. We vehemently
oppose adding code because "someone might need it" -- the only
features that make it in are those that solve *actual* problems.
If you can articulate what problem you're trying to solve (and how
Django's not letting you), we might be a bit more receptive, but large
architecture proposals are most certainly *not* pragmatic, and are
only undertaken when they seem to be big wins (c.f. magic-removal,
unicode, etc.)
Jacob
But keep in mind, when you start talking about outright replacing
existing implementations, you're going to run into deeper issues.
Remember, there's an underlying database that has to keep track of
relationships among the various tables, so if you change from one User
model to another, you'll likely have to scrap everything that ever
dealt with the User model.
It's one thing to provide a generic interface for something that
probably hasn't already been implemented, but to replace things
already in core, you give developers a big problem: if I want to use
your application, I have to abandon everything I've already done,
because you needed to have another method on the User model.
And I don't expect the schema evolution code would help much with this
problem either, unless it goes in a new direction to explicitly handle
this. Instead, I think we could look into ways of extending existing
models (even to the point of adding new fields!) in a way that schema
evolution would readily understand. Then, we might have a decent way
to deal with things like this.
-Gul
> > I can see abstract idea. But don't see right implementation idea.
> > 1) You can do this all without all javaish interfaces.
>
> Admitted, this is bringing some higher OO language stuff to Python. Trac and
> (gasp!) Zope both went down this route.
One of Zope developers said that he hates Python because of dynamic
features and duck typing, AFAIR. And as Jacob said - Django tries very
hard to be Pythonic. Both ways are just different ways, no one of them
is The Absolute Truth. Django developers like Pythonic way. I also
think so.
--
Vsevolod Solovyov
After writing this I realized that the example described by jag here
was pretty misleading, in particular with respect to the interface
names chosen (sorry jag ;), which definitely don't reflect correctly
on how interfaces are used in "the Trac model". So I apologize if my
reaction here was too harsh.
But as the "we're pythonic, we use duck typing and documentation"
meme has come up a couple times after that on this thread, let me
repeat: that frankly has *nothing* to do with the component
architecture as used in Trac that jag referred to originally.
"Class factory for greater flexibility" pattern makes sense in Java
world only.
Ok, last story. Once I copied Java homogeneous class hierarchy of 5
classes (100 lines each) to python and refactored it. Result was 4
functions of 3 lines each. In Java I won't be able to live without
these 5 classes. Factories and class hierarchy disappeared. Because
they were not necessary in Python!
> So at my work we developed an app to provide object-level permissions.
> Ideally, we could ask a User object if it has permission on a certain object
> via a method in that User object, but absent hacking the User object, that's
> not going to happen. I can subclass User and add the methods I want -- it
> will walk and quack like a User. But then I also have to rewrite get_user()
> so that it returns a ObjectPermissionAwareUser instead of a User. I have to
> rewrite authenticate() as well. And I have to check the middleware to make
> sure it uses get_user() instead of returning a user itself.
>
> In the end we subclass User and write a method to give us an
> ObjectPermissionAwareUser when we have a User object.
You can use monkey patching [1] instead of subclassing. If you're
using nice dynamic language you can use nice dynamic features.
[1] http://en.wikipedia.org/wiki/Monkey_patching
--
Vsevolod Solovyov
For the record, when the developers ask you what *actual problem*
you're trying to solve, this paragraph is what they were asking for.
It generally helps to understand what you're trying to say, if we can
see exactly what you're facing, and how hard it is to get there.
-Gul