In a recent post on Framework design James Bennett describes as a fundamental dichotomy in framework design "full-stack" vs. "glue". In this case, Django (which James works on) as a full-stack framework, and TurboGears and Pylons as glue frameworks. This is not a good way to describe the differences.

Both TurboGears and Pylons have glue. They have taken existing components and put them together. Both also include substantial work in the form of fully decoupled components -- components which were written for those frameworks but are not tied to the frameworks. And TurboGears is a full-stack framework, providing a cohesive and complete story about how you create applications within its domain. This doesn't make TurboGears more or less glue than Pylons; there is nothing exclusive about full-stack and glue.

There's also awkward glue and easy glue. This often has a lot to do with whether you are using the pieces as intended. To extend the metaphor inappropriately, there are pre-measured pieces with pre-drilled holes, there are erector sets with a large number of holes, and there are piles raw wood. Sometimes components are intended to go together just one way, and if you use them together that way then everything works great. Sometimes there's components meant to be used all sorts of ways, capable of being attached to any sort of system, but you have to figure out what you want. Then there's just raw code, recipes, all the hand-coded stuff. The metaphor is horribly strained here, because most things are a bit of all of these. At some point someone wrote some code by hand. Usually there's strongly opinioned and constrained interfaces which are still public, things that are entirely private and internal, and stuff which is explicitly built to be flexible, and all these parts coexist within the same package.

All of which to say, there's many ways to look at program design. There's glue, there's standards, there's conventions, there's community knowledge. And there's a lot of pieces, all of which have to fit together, and this is just as true in the small as in the large.

An example of what formal and explicit interfaces give you: right now both TurboGears and Pylons are in the process of changing their preferred templating languages (TurboGears from Kid to Genshi, Pylons from Myghty to Mako). The process for both is the same -- they both support the Buffet API for templating languages, and have supported alternate templating languages for a while now. When someone decides to write a new templating language, they implement that API -- they don't ask about design choices, they don't have to worry that they'll be accessing an API that is subject to change. The new language can achieve some design maturity this way. If a framework wants to change languages, they don't have to force anyone -- each developer can choose to move slower or faster than the framework. This also gives developers a way to do rewrites without causing breakage. In the case of Myghty and Mako, Michael Bayer wrote both -- but because of loose coupling he didn't need to use his relation to Myghty to force his changes or cleanup into that existing project. Forking makes rewrites easy -- but it only works when you build choice into your framework.

So instead of "full-stack" and "glue" frameworks, I would describe the difference as "coupled" and "decoupled" frameworks. Decoupling is generally harder, and leaves more potential open loops, and can sometimes be misused to avoid making important decisions. But it's much easier to maintain and test, and this applies not just to individual projects but for the larger set of projects that makes up anything approaching "full-stack".

Maybe it's not entirely fair -- coupled and decoupled are not very neutral terms (at least since Agile terminology has caught on). Django people will claim to have a decoupled framework, but then they've never put their money where their mouth is -- they've never actually decoupled anything from the framework in the form of an extraction that they use. So I turn it around because calling these other frameworks "glue" frameworks isn't really fair -- they wrote much of what they are gluing to. Gluing together things you wrote yourself is called simply "software development"; that you introduce greater discipline on yourself to create something that is independently useful doesn't mean you've necessarily created something less cohesive and complete.

(There's other ways to describe differences in frameworks, of course. But I think Django's developers could make a better argument based on development methodologies and community development than they can on engineering principles.)