Problem: Django has features. These features, horrors, reuse each other's capabilities.
Solution: Use something that has no features.
I'm not sure myself how sarcastic I'm being, to be honest. There's some truth in there too (or I wouldn't have posted this). But of course your microframework doesn't have any dependency issues. Rip all those things out of Django and it wouldn't have any dependencies either. Put them all into Flask and it will inevitably have to choose between either having the same problem, or leaving vast swathes of functionality on the table because of the refusal to let the components work together so they stay separate.
Rails and Java EE demonstrate that dependencies on specific implementations are not required to build a framework that offers features.
In Rails, you can rip out ActiveRecord and replace it by an entirely different ORM like DataMapper. There is no real default authentication support, but you can easily plug it in. The list goes on and on: they've done a decent job (I would say 'great', but there are still some improvements needed to make it 'great') at decoupling the various components of Rails and making it easy for users to mix and match.
You need a dependency to offer a certain feature, but not necessarily the default dependency. They have internal API's that decouple the lot. That is exactly what this presentation argues Django doesn't have, but should have.
Now I don't know anything about Django, so I can't judge whether the argument has a factual basis. If you tell me it is wrong, because you can easily replace the persistence or authentication layer of Django, then I have no choice but to believe you. However, the argument is logically consistent and the viability of the alternative it proposes is backed up by plenty of real world examples.
Django is a single python package but is really fairly modular. You can readily use anything in lieu of it's ORM (e.g SQLAlchemy), anything for template rendering (e.g jinja), you're absolutely not forced to use the provided auth component (it's not even enabled by default) nor the admin (but the admin of course only works with django models).
Don't take my word for it, all of this is actually written in multiple places in the docs, tutorials and/or Django site, I can't remember. Here's an excerpt that exemplifies Django's philosophy (from [0]):
> Each view is responsible for doing one of two things: Returning an HttpResponse object containing the content for the requested page, or raising an exception such as Http404. The rest is up to you.
> Your view can read records from a database, or not. It can use a template system such as Django's -- or a third-party Python template system -- or not. It can generate a PDF file, output XML, create a ZIP file on the fly, anything you want, using whatever Python libraries you want.
> All Django wants is that HttpResponse. Or an exception.
> Because it's convenient, let's use Django's own database API, which we covered in Tutorial 1.
Indeed, Django components are incredibly convenient to use, and readily included, and officially supported. But they're completely optional.
"but the admin of course only work with django models"
I think you missed the point. In Rails, ActiveSupport does a whole lot of automatic magic with ActiveRecord. But it is not limited to ActiveRecord, as most of that functionality is factored out into ActiveModel - implement those interfaces and your link helpers and whatnot will happily support nonAR models. I use this quite often to represent things that doesn't reside in a database.
Well, most of the time. There are a few things out there that are not migrated to ActiveModel yet that really should be (the model side of datehelpers in forms comes to mind).
The point I was making was with regard to the article, which goes down on Django because it would supposedly not be barebones enough. I was expliciting that although one does an apparently monolithic (easy_install|pip install) django, one can readily use only the project+url+view part and have something as barebones as Flask in which you could use other components. Additionally you could readily use only Django templates or the Django ORM, and use e.g Flask for the view part (or no view part at all if you're not doing web stuff)
As for the comparison with Rails, faking models is the same in Django, as both leverage duck-typing features of their underlying language. In Django, a model is just a class, and many things are just queried via introspection. Many parts just query model_instance.pk. Additionally populating Model.meta and you even get yourself some deeper model introspection features. To me the true important part of ActiveRecord, ActiveModel and ActiveSupport is rather that you have a set of modules that you can readily include/extend into your fake models to inject complete model behavior, and that is something Django lacks.
You name the example of link helpers, and interestingly this is an example of the difference of philosophy between Rails and Django (see [0]). Django parts are coupled more loosely than Rails parts, a possible rationale being that creating coupling between two distant parts such as URLs and models could enforce constraints on each, thus reducing their potential to independently shine and coercing possible alternatives of each to the provided model. Another example: with Django you explicitly create a request object (whether directly constructed or encapsulated into a helper method) to be returned by the view function while Rails does magic for you in the controller.
Interestingly you bring the problem of forms and this is again an area where Rails and Django differ. Rails wants both form and data to be handled by a single model, whereas Django separates form models and data models. The rationale here is that they are two different problems and that they ought to be solved by two different components (yet they share a great deal of similarity, and code).
FWIW I worked extensively with both (although my current job is in a Ruby shop, I worked with Django at my previous job and since I'm more of a Python guy I keep myself up to date on that front too), and am in no way saying that one is better than the other. Choose what works for you.
> dependencies on specific implementations are not required to build a framework that offers features
I think this is incorrect. You can't offer features without implementations; The feature will never be completely agnostic of its implementation. When you get a really strong shift in the possible implementations (for example: websockets or even long polling, vs rpc) then the feature (for example: dynamic UI), if re-implemented, starts exposing very different semantics and secondary features.
To sum it up: if you implement a thousand ORMs based on SQL db's then they're all going to look the same, implement one thing based on a NoSQL database and you suddenly see how the "feature" of "storing data" suddenly becomes something different from what could be anticipated by the people who designed the original "feature" back in the SQL era.
Let's not lie to ourselves and pretend that features are some wondrous thing poised in thin air above their implementations.
Agree - This paradigm plays out in every development effort I've ever been apart of...
1) Project starts out relatively agnostic and casts a very wide net
2) Features start to mature and while you are servicing one use case, you are somewhat unknowingly making your product unsuited to certain different future use cases that may or may not arise.
Thats just how design decisions work. Django has made design decisions to cater to a certain set of needs and they have obviously been quite successful. I don't even use Django but I can tell it doesn't "suck" just by how many people have told me it has fit their use cases quite well.
I actually wouldn't be surprised if X years down the road Flask becomes much less agnostic as its community consolidates and matures.
In a way, frameworks are inherently stupid, but who's to decide where between assembly language and x layer abstraction people should work in?
I think people who criticize Django have yet to make up their minds about what a framework is all about, and what, if anything, it's for. They just hold on to their utopian idea of what their framework should be.
Django was created for practical purposes by people who used it in publishing. I think that's a great foundation for a framework - for some people - and piling on it is just a stupid bandwagon.
---
EDIT: I found a better way to put this: the author doesn't have a problem with Django; he has a problem with the concept of frameworks.
I'd say it's more of a problem with frameworks as they exist today. I'd like to see a movement to REST API service frameworks with some level of cooperation to get compatibility for standard client libraries.
Everything then gets built around services: from static site generation to single-page apps, third-party developer APIs to admin interfaces. Then you'd have flexibility to replace any piece of the architecture, whether to get better to performance from a service or to use the latest JS single-page app framework.
1) All teams will henceforth expose their data and functionality through service interfaces.
2) Teams must communicate with each other through these interfaces.
3) There will be no other form of interprocess communication allowed: no direct linking, no direct reads of another team's data store, no shared-memory model, no back-doors whatsoever. The only communication allowed is via service interface calls over the network.
4) It doesn't matter what technology they use. HTTP, Corba, Pubsub, custom protocols -- doesn't matter. Bezos doesn't care.
5) All service interfaces, without exception, must be designed from the ground up to be externalizable. That is to say, the team must plan and design to be able to expose the interface to developers in the outside world. No exceptions.
The problem is not frameworks; the problem is object oriented programming. Simply put, OOP lends itself to kitchen-sink frameworks because it is the only way to really share code in OOP. We write these large hierarchy of objects and then, because we have to carefully maintain state, we mark most of it as private, or sealed. Then we give precise instructions on how to consume and use the code, and even more precise instructions on how to extend it.
You can, but that doesn't mean you should. It's brittle. If your app or library breaks because a minor update to a dependency changed those internals completely, you can't say you weren't warned.
Who's piling on Django? It has flaws and weaknesses just like anything. It is a huge codebase that tries to be everything for everyone, and it succeeds about being almost everything for almost everyone, which is great.
But it can be very difficult to do relatively simple things with Django sometimes, mostly in the admin pages. Admittedly, this is a pain point people bring on themselves by trying to do too much there, but it's a big red swollen example of how too much interleaving and complexity make it painful or impossible to reason about what's happening.
This got a lot better in 1.4: TemplateResponse and the list filter API meant some gnarly code removal on my biggest customized admin project.
That said, I also chose to implement many of my admin changes at a higher level: templates which use jQuery, etc. and interact with the REST API for e.g. complex object creation are much easier than the crazy form / widget hacks I used to try.
I have no problem with criticism of Django, but to write a presentation called "Why Django Sucks" is bombastic, misguided link bait - replete with rage comics and whatnot.
It's just not constructive for the discussion, interesting as it may be.
Actually yeah. Great point. I think Django rules for publishing, or building sites where your general technical competition might be Wordpress.
It's frankly an awkward fit for loads of web applications. It seems to me (note: Django guy, not RoR guy) that the Rails stuff has adapted much better to applications that fall well outside of the blog/publishing sphere... but maybe that's a false impression.
I'm currently writing a control panel for libvirt and it's a pleasure to use Django, so many features mean I can concentrate on the problem at hand and not on reinventing the wheel.
> I think people who criticize Django have yet to make up their minds about what a framework is all about, and what, if anything, it's for. They just hold on to their utopian idea of what their framework should be.
No, they have a different idea of what a framework should do or not do. Doesn't mean they have some utopian idea just because it's not Django.
It's difficult to refute this line of thinking, except in practice.
In practice, I think large frameworks are eventually pretty terrible. It's too easy to compromise your business needs in small ways because the framework offers you something close-enough. Whether those compromises come in the form of over-coupling (which they always do with these frameworks), or in other ways like compromised URL design, query performance, or authorization plumbing.
Great at first, but in my experience a project run long enough in one of these ecosystems tends to outgrow it.
Being faced from the beginning with more of a blank sheet of paper and open ecosystem of solutions to choose from (or build) tends to make you more aware of the trade-offs, and how well the solution you're implementing fits your business needs. Costs more up front, but you're less likely to grow a hate-tumor during years 3-6.
I've been writing web apps for a long time and for many different companies of different sizes. I've never, ever, seen a homegrown setup that was in better shape than the average rails app after a few years. Maybe your experience is different.
Amen. I've seen quite a few projects that start out by rerolling the ORM, routing and templating, then grind to a halt under the weight of all the bugs before getting any significant features out the door.
I wouldn't, and I'm sure you wouldn't... but there are people who do.
Case in point: OpenERP. Serious business software doing serious business things, so of course they can't use any of those other toy ORMs, they have to spend 5000 lines of code writing their own: http://bazaar.launchpad.net/~openerp/openobject-server/trunk...
I know of other projects in a similar state, but they're smaller teams or solo coders, so I don't know that they're quite as fair game for finger pointing...
Most codebases I've seen that are badly maintained or managed over the years are horrible messes - whether Django, Rails or anything else. The last codebase I worked on - written in Django - was appallingly bad. That's no fault in any way of Django, but no framework is going to save you from poor coders, last-minute rushed requirements, chronic technical debt, or lack of investment in refactoring.
I'm not sure you addressed the issue at hand. Others are arguing that using a framework will make your codebase worse in the long wrong. I'm asserting that all of the homegrown codebases I've worked with are worse than the ones using a framework, after a few years.
I'm not arguing against using a framework, if it fits your project requirements, and we can argue the day long about micro-vs-full-stack. There are good arguments for both, they suit different people and projects.
My own observation is that bad codebases are the result of bad development practices regardless of framework. In my last job the code quality was so poor (and the management processes so broken) that whether they'd used Django, Flask or roll-your-own would not have made a whit of difference.
The original discussion was about a potential difference in the long term quality of a code base if they choose a framework over a homegrown solution. You aren't saying anything about that potential difference. Correct?
My experience says there is a difference. Allow me to offer one possible reason. A good framework gives a project a good structure to start with. Most homegrown solutions have to recreate much of the structure of the framework, and they often do a worse job than the highly developed frameworks that have the experience of many open source developers behind them.
All other things being equal, a "homegrown" project by coders who know what they're doing is going to be better than a framework project by coders who don't. Yes, I understand your reason, and given coders of equal ability it may be true; but I've seen Django projects written so badly the framework made very little difference to maintenance overhead (and as Django becomes more popular and mainstream we're going to see more examples of this).
Even a team of good coders often produces a worse homegrown solution due to the time pressures of their project. This in my opinion makes the chances of creating a better homegrown solution low. And you lose all the reuse abilities you get from a framework.
Could you summarize your suggested best practices (Specifically what you suggest is a good way to avoid at least some of the problems you list in your last sentence.)
Really, it's more of a management problem than a coding problem. Short-term thinking, bad hiring/outsourcing practices, and poor client expectations management, among others. A framework or language isn't magic pixie dust that will make these problems go away.
At this point I'd prefer to work on a well-managed, professionally coded project written in PHP than one written using <insert-python-framework-du-jour-here> run by idiot managers.
One of the factors I considered when I switched jobs earlier this year was that the new place has a policy of devoting 2 months a year to refactoring :)
Which has an interesting balance: you're then using things developed in isolation, which can give you better parts but it definitely means you have to provide interconnect conventions and that new developers have to get used to your particular combination of parts.
If you think you can do this better than the Django community, this can work out well but I'd say more often than not when I've heard about it people weren't actually able to spend enough time on this as they'd hoped and keep falling further and further behind Django and other frameworks.
Sure, if you did it completely on your own. More likely you use Flask or Pyramid which provide the plugins/entry points/templates to make wiring these components together quite easy.
I have been creating software for 20+ years and I have personally never seen a case where 'in the end' it wouldn't have been better to use a framework. And mostly actually a framework which is as opinionated and feature rich as possible. These frameworks don't grow randomly; they are based on actual needs. When they are young they answer mostly to acute needs of the developer, when they grow they automatically grow into stuff 'most companies' need. And that's 'your company' as well; you can think you are different, but that's not really true. If you try to be different, you mostly do a lot of work which you shouldn't have. Yes, there is Google. Yes there is Facebook. But you are not those. And you won't become those. Also most companies are not IT companies; non-IT companies benefit even more from frameworks and rigidity; in most cases it's better to remake or form your business process to the framework/software than the other way around. Other people did that heavy lifting already; why should you try to do that again?
I'm not sure where you work, but this is my experience from using 'wysiwyg' clipper & dbase software in the 80s to Delphi frameworks in the 90s to web frameworks. People think they are very different from the start and then (usually after a management change) they notice the same stuff happens everywhere.
Are you talking about frameworks or software products? There is a very good argument around building custom software versus buying a product that matches your argument. In that case, I strongly agree. You should find products that either match your business process or change your process to match the products.
With regards to frameworks. I find it hard to believe that none of them would work out in the long run. I wonder if you are under-estimating the cost involved from the developers to replace or create these frameworks from scratch. This also seems like a selection problem more than an inability of frameworks to meet any development need. I mean they do exist for a reason.
That said, most software products are pretty horrible. Many frameworks are equally bad. Does this mean you should custom build everything? Of course not, you company is not going to be able to afford the time it takes you to write your own ORM, your own web framework, your own logging library, etc... It is your job to make compromises that will allow your company to achieve its goals.
Exactly, and I have exactly the same eye twitch every time someone recommends tearing out Django's ORM "because it's shit" and replacing it with SQLAlchemy.
Each of those arrows from slide 25 on should have a little label: "Things that you have to write yourself in Flask."
You sound institutionalized. Django is indeed awesome for having a ton of features immediately. Of course, once you need to start changing those features you realize you have to dislocate your shoulder to do so.
Django is badass for what it is intended to do: be a kitchen sink. Flask is badass for what it is intended to do: be a platform for composable applications. If you ever need to reason about the internals of your web framework, you want the latter. If you don't, the former is great.
I'm not sure what that even means, but I suspect the thing that disproves it is "The last website I built was in Yesod.". And while it may be in some sense targeted to fill the Django space, at the present time (and certainly at the time I worked in it) it was more like Flask and a couple of things lightly tacked on.
No, my main point is that Django is what Django is, and while that may not be perfect, it isn't useless, it doesn't "suck", it just doesn't meet all needs any more than anything else does. Flask doesn't meet all needs either. Don't complain that water is tasteless when what you wanted was mustard. Being tasteless doesn't make the water suck, it just makes it water. Complaining about its watery nature is just silly.
If Django actually sucked I'd probably not have said anything, but it's more successful at actually bringing together all those things than most of its competition. (Though since there are roughly 1000 web frameworks out there I'm sure there's better things somewhere.)
This was a presentation for a room filled with Django developers that likely use it for just about everything.
The purpose of the talk isn't to bash Django, it was to introduce Django developers to some interesting concepts that are worth exploring and a tool that may suit their needs.
To be fair to the author of the presentation: if there is a problem, it isn't features and reuse. It's tight coupling, boilerplate and overhead. (Although it is funnier to say that the problem is features and reuse, like it is more provocative to say that Django sucks).
I won't slam Django, Django is good. Its most salient traits are its mindshare, liberality with features, big plugin ecosystem. And these traits were not all present from the beginning, when it was the Django developers who were reinventing wheels and going without features. Django's top traits are historically contingent. So in an alternate history, we might be talking about CherryPy having basically the same problems, because of the inherent pain of taking on so many features so quickly, then maintaining backward compatibility, etc.
Good framework or library code takes significantly longer to develop than similar functionality inside an app. When you add goals like trying to reduce boilerplate and coupling, it gets much harder and slower. It is totally valid to question why not just charge ahead with something easier to develop and get done more quickly. There is a real issue to think about here, it's not so clear cut.
It isn't as simple as saying "Flask is only nice because it has no features, anything with features is necessarily ugly." Both features and clean design take time and if you want both, even more time. But design is hard while features earn mindshare and dollars... if they work reliably, then who is complaining?
Now, at this point, Flask actually has a significant mindshare and plugin ecosystem of its own, so it is really inaccurate to say it has no features. And actually Flask does have a number of dependencies as well, with much of its implementation tucked away in Werkzeug (which is hardly a simple library).
Solution: Use something that has no features.
I'm not sure myself how sarcastic I'm being, to be honest. There's some truth in there too (or I wouldn't have posted this). But of course your microframework doesn't have any dependency issues. Rip all those things out of Django and it wouldn't have any dependencies either. Put them all into Flask and it will inevitably have to choose between either having the same problem, or leaving vast swathes of functionality on the table because of the refusal to let the components work together so they stay separate.