Hacker News new | past | comments | ask | show | jobs | submit login

The author carefully distiguishes precisely what type of framework they mean. The definition includes multiple parts, but the part that really stands out to me is that a framework dictates the overall flow of control.

The suggestion in TFA is to ensure that you consume your dependencies in a decoupled fashion, a move toward utilizing libraries rather than following a framework.

I've spent lots of development time in highly-constrained environments that often feel more like a framework than a true platform. When given the opportunity, I'm inclined to follow the author's suggestion to keep dependencies decoupled. Even supposedly fundamental dependencies will eventually need to be swapped out, even if just for a v2. But your domain core should be making monotonic progress towards the distillation of your key concepts and relationships.




The author uses Django as an example of a framework... but Django doesn't really fit the definition used.

Django does not dictate the flow of your code. It provides some libraries and there are common patterns, but Django is more or less just a set of Python modules you can import and use as you want (A bit of configuration is done for you if you follow common layouts, but you don't have to and can manually do the configuration).

What dictates program flow is when you use HTTP with Django (What its primary use case is) but that is dictated by the request/response nature of HTTP not by Django.

You can use as little or as much of Django as you want. Naturally, the more of it you use, the more it does for you.


All frameworks are collections of libraries and that usually means you can import and use parts of the framework. Django is exactly what the author is saying is hard to maintain. And mostly all things Django start via wsgi, asgi or manage.py.

As the lead developer on three Django based commercial saas products, there is a trade off. Spend your time reinventing the same basic things or spend your time building your product. Even the maintenance argument is really a trade off. When you are small, frameworks help by outsourcing a huge amount of labor. When you can afford more developers, you gain control and maintainability by ditching the framework.


In my experience its not Django that makes apps hard to maintain. Your experience is certainly valid, it just has not been my experience with it at all.


My experience goes further, in that the Django apps I've worked on would have been harder to maintain without Django, even with a "smaller" framework instead.


Are we using different Djangos?

Let’s take it for granted you’re using it with HTTP since it’s a web framework (this would all apply with WS).

You routes call your views. Your views load your models. These feed into your templates, which go into a response. You can tweak what’s going on at each step (DRF) but there’s definitely a way it’s all supposed to work together. It’s classic IOC.


I use Django with and without HTTP.

All a Django View is is a function (or in the case of a class-based view, a method of the class) that takes a request object and returns a response object... this is pretty fundamental to HTTP, so any HTTP app will do this. Its not Django dictating it, its the nature of HTTP.

You don't have to use any of those parts of Django if you don't want to.

I often opt to use Jinja2 instead of the Django Template Engine. I happen to like the Django ORM, so I usually do use it, but you certainly don't have to, I have certainly used Django without models before. Your views don't do anything with models unless you tell them to.


I second the mention that almost everything is replaceable in Django. And as a matter of fact DRF replaces the whole Request / Response handling with its own.


I recently spent a few months on a project where we used Django without a single HTTP / external endpoint. It basically consumes messages from a rabbitmq queue, then creates new celery tasks which are then run.

Using Django for this is of course completely overkill, but using a known framework, especially considering that Django is what's used in other applications here, did have some benefits. All our devs having to fix something in this app, will immediately be familiar with it as it looks exactly like the other Django apps we have. No new way to do migrations, talk to the db, open a shell, log- and reliability setup is identical with other apps, etc. etc.


Django requires you to have imported settings.py and be connected to the database first, before you can even import a model. It makes it impossible to write modules with type hints and modules which are partially usable outside of Django context.

If that is not dictating how you write your code, I don’t know what is.


If you are connectiong to a database, you have to tell your program how to connect somewhere. The Django ORM does it through settings.py. I do both of the things you say are impossible, so maybe I am misunderstanding?


Author here.

I use Django and Rails as examples. Both are, indeed, "just a bunch of libraries". But many of those libraries, and especially their bundled collection, enforce certain behaviour, shape and architecture.

When you inherit from base-classes offered by a library, you are tightly coupling against that: i'd then stop calling it a library and call it a framework instead. The alternative would be a library that you inject, or compose.

There's a big difference between (Rails)

`class Project < ActiveRecord::Base; end`

and

class Project

  def initialize(project_repo) # Ruby has no interfaces, but this would be something that has at least an `.add(project)`

    @project_repo = project_repo

  end
end

The first inherits, couples tightly to a bunch of libraries (ActiveRecord::Base really is just a bunch of modules that you could pick and choose) the former injects behaviour which might come from libraries, or might come from your own code.


The Serializer class is the worst frameworky piece I know of. These are basically classes which force you to use overridden methods to link HTTP with DB operations. Requires tons of hacks to work around all the time.

And just cuz it’s optional doesn’t mean it’s not frameworky. A solid platform just wouldn’t offer any frameworky elements.


Aren't you talking about DRF's Serializers ? Django itself does not have serializers. But otherwise, I completely agree with that statement.


Could you elaborate on this pain point? How do you think serialization should work?


Django is definitely a framework.

Its not just Django that locks you in, it's all the third party apps people end up adding. All these integrate tightly with Django.

They often block upgrades as they have different python and Django version requirements.


But that is also (or can be) an anti-pattern. Don't just blindly add dependencies - there are so many risks involved with that. Of course that is not unique to just frameworks like Django and Rails, but any piece of growing software.


I do agree with that, problem is all the other django-related packages that come with it, especially Django Rest Framework (framework is in the name here). I like some parts of it, e.g. Authentication, permissions, but IMO we often have to bend our code so it fits DRF views, and above all their serializers (which I despise). Obviously we could drop this part of DRF, but it would mean to drop DRF entirely, and I'm not sure everyone is ready to do just that.


What do you despise about their serializers? What would make them better or what would be a better approach for you?

(Genuinely curious as someone who's working on a similar idea in a different language)


- They're slow (like really slower than almost any other package, if you use their ModelSerializer) - They're quite verbose - Above all, they're trying to do way too much. A serializer should just be about (de)serialization, i.e. converting from a generic format (e.g. JSON) to / back a python object, with some validation. When you use a DRF serializer inside a view, it can do complex queries to retrieve / modify the model instance, save the instance in database, modify the serializer instance with db values (for example because of default values) and return the modified object in the HTTP response. All this logic should not be defined inside the serializer. Obviously you don't have to do it, but it means you cannot use the DRF mixins, nor the viewsets.

On the opposite, I'm in love with pydantic. Like any other package, it has issues, but it tries to solve a single problem, it's concise, validators are explicit and readable.

Obviously I don't mean any disrespect towards DRF maintainers, they're doing an impressive job, a lot of people use and love their work (and I still use it everyday)


+1 Django is a beautiful example of a framework you can use but doesn’t get in your way.


Ok, let's use Django with Flask and web2py then, since Django apparently doesn't dictate the flow of your code?


There was a talk a couple years back at Djangocon where a company was using both flask and Django together. It was a transition for them from flask to django, but it wasn't hard to do. Probably doesn't make a lot of sense for most projects, but it is possible because Django doesn't get in the way.


Commonly summarize simply as:

Libraries over frameworks.

If you chose not to use an existing framework and end up building your own instead, you just live long enough to become the villain of your own story, as it were. But it's really, really tempting to write frameworks.


An RDBMS meets the definition.


> TFA

That was uncalled for.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: