1. Every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework.
2. If you have a talented team, that half of a framework can be much better than using a one-size-fits-all framework that is popular because it used to be lean and mean with a small surface area, but has grown over time to do everything for everyone, becoming a complex monster.
3. If you have a small team that hires slowly, it's relatively straightforward to bring new devs up to speed on "the way we do things." if you are hiring rapidly and/or have a large team, the more bespoke things you have, the harder it is to maintain them.
4. Over time, everything degrades. In the long run, many framework-free applications either get walled off as "legacy" apps with new work done in separate services, or replaced outright. If it makes you money before that happens, you win. It is not necessary to try to design architecture that will last for centuries.
5. My last and--to me the most significant--observation is this: You want to pay the majority of your attention to the code that has the greatest impact on your desired outcomes.
Using libraries and frameworks is like a business outsourcing things that aren't its core competency and also aren't competitive differentiators. Most software shops do not win by having their own framework or by not having a framework, they win by using something bog-standard and saving their attention for the part of their code that "moves the needle."
But that's only "most," and your business may be one of the few.
> 1. Every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework.
After 25 years of experience writing software I can honestly say I have encountered many people that agree with this, and perhaps all of them (every single one) have not actually experienced writing an application without a framework. This sentiment sounds correct in theory, but it isn't based on any experience from any one of the people making such a claim.
The reason why that is comes down to selection bias and cognitive conservatism. Once you become dependent upon a framework everything looks like a framework, even when it isn't. Therefore everything works as expected (like a framework) or it doesn't, which isn't buggy. So really this isn't a question of the software, but of the developer's capability to perceive (or not) that software.
> perhaps all of them (every single one) have not actually experienced writing an application without a framework
I actually have written software without a framework, so by this standard I feel qualified to comment.
Not all software has an implied framework within it. Most Unix command-line utilities do not, for example, with only a few exceptions, and discounting the C standard library as something worthy of the label “framework”. Nevertheless even they exist within an overall architecture that starts to look like one, if you squint, and realise the enormous power of piping stdout around.
However, many line-of-business applications do develop sufficient complexity, as the owner/operator adds new features to support their expanding operations, that the subsequent edifice either accretes random code into a horrifying fatberg of unmaintainability, or some wiser developer refactors substantial parts of the interface, business logic, persistence, and runtime configuration, effectively creating a framework within that application on which the logic and interface and so forth subsequently hang, and with a pinch of skill and luck, in a fashion that is more readily reasoned about and amended.
Whether that informally-specified framework might be considered worthy of extraction into a unit of software for itself is another matter, and largely a case of programmer hubris.
> or some wiser developer refactors substantial parts of the interface, business logic, persistence, and runtime configuration, effectively creating a framework within that application
That's not what people commonly understand as a "framework". Nor is it a helpful definition because then where does "abstracting things" and "framework" start and end?
No, the main difference between frameworks and what you describe is the IOC. In the framework world, the framework calls you and then something happens behind the scenes until the framework decides to call some code that you provided via the frameworks API.
With libraries it's the other way around: you call the library and then you do something with the result and then use it to call the library again and so on until you have the desired outcome.
The difference is, for example, that you can call the library and when it returns something to you, you can inspect it and choose to ignore it. You can do so in an arbitrary way. In the framework case, if the framework does not provide any way for you to interact with it in the way you want, then you are screwed.
Sorry, I don't accept this very mechanical definition; not only is it a needlessly narrow one, it's downright meaningless in some paradigms, such as when implementing coroutines via continuations, but that doesn't mean you can't have frameworks in Scheme. Conversely, we could describe tuplespaces (a la Linda), or many event- or interrupt- driven systems (like an Ethernet port), as an inversion of control, but whether they're frameworks or not would be an open question, and indeed in the end almost everything happening inside a modern computer consists of one element calling back to another, up and down a stack.
Heck, it's not even true of some of those specifically called out in the article above. For example, I've written programs that use Rails as a library - or rather, suite of libraries - of functions and classes to be called, but anyone suggesting that Rails is somehow "not a framework", on the flimsy grounds that it did not dictate the flow of control, is gonna get some funny looks at morning standup.
But the greater problem is that narrow, mechanical definitions omit purpose, and talking about software without purpose being front-and-center becomes rapidly theological. If you're wondering what I mean by that, look up the wikipedia article for "Software framework", scroll through its desultory talk page, and recognize the inevitability of the boilerplate it got stuck with: "This section is written like a personal reflection, personal essay, or argumentative essay that states a Wikipedia editor's personal feelings".
I‘d say Rails is a combination of framework and libraries.
Some parts (ActiveSupport, the part that simplifies e.g. date calculations) are clearly libraries. They can be used outside of Rails as well, because they totally ignore the shape of your other code.
Other parts (ActionPack, the component that calls your code depending on the incoming web request) are working like a framework. Your code must adhere to their requirements, otherwise it won‘t work.
I think it might be better if instead of trying to redefine libraries and frameworks we instead used the terms impure application(frameworks) and pure application(libraries). That would make it evident as to which libraries are actually tainted with impure work and need to be redefined as impure.
When you extend this pure/impure idea all the way throughout the computing eco-system, it quickly becomes apparent that something went wrong a long time ago, and every-time, instead of untangling the mess that is pure and impure into their own buckets, we find a way to run a framework in a framework.
What is an Operating System? What is a container? What is k8s? What is a Programming Language? What is a browser? What is a website? What is next?
One of the most useful definitions I found was from Luciano Ramalho, the author of Fluent Python (and so many other cool things). According to his insight, a framework is something that calls your code. A library is something your code calls. Frameworks are more rigid things that force structure on your functionality. If the structure it imposes is good, then your code will be good.
Their scope is also tailored to the languages they support. As you pointed out, different languages will have different needs.
I'm not saying that I gave the perfect definition of a framework. But if anything the original definition is even worse or less meaningfull.
Also, it is certainly possible to have a mix of a library and a framework where parts use IOC and others don't. Maybe that's try for Rails (never used it) and that's where your confusion comes from?
I don't agree with this simplistic distinction between framework and library. There are plenty of libraries that call back into user code. A better definition might be that a framework imposes an entire 'application model' on you, and trying to step outside that predefined model is at your own risk, while a library is a much smaller and flexible building block (also a building block for frameworks).
But there's a large gray zone between these two, and eventually the distinction is also often quite pointless in the real world.
I think the last sentence is really true. And yes, there are libraries that call back into user code, which makes them framework-like in this regards.
> A better definition might be that a framework imposes an entire 'application model' on you, and trying to step outside that predefined model is at your own risk
This is the kind of definition were 50% will call something a framework and the other half will call it a library then. Not sure if that is really helpful.
Yeah, if this is not just an once-off async callback (where you could just use a promise) but somthing more complicated, then this is indeed more framework-like and for me would be a reason to try to avoid it.
> then where does "abstracting things" and "framework" start and end?
It doesn’t. If you abstract things enough there is your framework.
The only things I’ve seen that were truly without a framework were raw php files that did everything contained within that single file. And even these had headers that combined some common functionality.
> Not all software has an implied framework within it.
The definitions of "framework" are always a sticky issue. If you take "framework" at face value, it's minimally a set of idioms. "an essential supporting structure which other things are built on top of" - which necessarily includes a mental model of execution. This relates closely to why naming, in software development, is considered so difficult.
All software has an inherent framework. First is the mental model and then the implementation. Implementation middleware to simplify utilizing these idioms or enforce them, are incidental. If you're lucky, you can derive some of the underlying design from documentation.
Ironically, those who claim that they never use a framework are largely making implicit claims about what they consider a framework to be or have.
> The definitions of "framework" are always a sticky issue.
Hence why the article defines what it means by framework, and by the definition in the article, software rarely has any implied frameworks within as one of the definition points is that there is code in the framework the user is not free to change.
There certainly can be frameworks emerging within large projects, but by the definition in the article they're not problematic because they don't lock you in: You can change those pieces. You in particular ultimately remain in charge of the flow of control in the code. Those "frameworks" don't take away control and put you in a straightjacket.
The article could perhaps have been framed better as "how to write a framework or framework-like thing which doesn't become a problem". Some thoughts might be:
* Structure it as decoupled components where you can opt in and opt of different elements, including of control flow. E.g. Padrino - a Ruby web framework fits well here. You can pick and choose which ORM to use; you can opt in to a router, controller, admin interface, mailers, logging, caching, and view libraries, or not use them at all. You can start with plain Sinatra and add in bits of Padrino as and when you choose, or supply your own.
* In particular, if possible, externalise the control of flow into replaceable components. Doing this alone can often be enough to get you out of the straight-jacket of "frameworks as defined by the article"
* Allow users to override/replace all components rather by defining clear interfaces and not assuming you can call hard-code calls between the different components. Padrino again fits well there. So did e.g. Qmail treated as a "framework for building a mail server" ("nobody" used pure Qmail, but Qmail defined the interfaces between each individual program which made up the full system, so you could replace every single bit step by step). In particular there should be no "magic" glue which there isn't a well defined way of tearing out.
Well, I don't disagree, and we could almost label that "framework zero", and also hence the reference to Unix utilities and their assumptions regarding stdin/out, but I am also taking a contextual cue from the article linked at the top which is clearly taking aim at large pre-chewed boluses of code such as Rails, Django, Drupal and so forth.
I am just about old enough to have even toggled in a program on the front panel of a PDP-8 that my local university had kept around to occupy valuable floor space in their computing center. I wouldn't say I used a framework, but I was just a kid at the time, so it's possible that I did use a stepladder.
Really? Did my toggling on an 8e that ran as a controller for a COM (Computer Output Microfilm) "printer".
Not saying that I could write code directly in octal... but I was pretty darn close. Of course, it helps when your assembly language consists of just eight instructions.
An important part of being a framework is that it is made for reusability, similar to a library. Just because your code has some thought out structure/architecture doesn't mean that it has an inherent framework.
> An important part of being a framework is that it is made for reusability
I might have agreed with this at one time. A dedicated "framework" has documentation and additional software to shortcut assumptions, but a coherent design isn't different enough from the rules that guide any given framework to be a distinction. The biggest differences are how mature the frameworks are in breadth of documentation, guidance in how to achieve constrained goals (there is no "everything" framework), and supporting software to shortcut boilerplate.
> Whether that informally-specified framework might be considered worthy of extraction into a unit of software for itself is another matter, and largely a case of programmer hubris.
The interesting thing to me is that this is how Django, one of the canonical big backend frameworks, came into being. It was based on what a newspaper's website's staff were actually using in practice.
But this is fine. The framework that the organisation develops for itself is designed to solve the problems that the organisation has.
As TFA says, one of the main problems with frameworks is that the maintainers of the framework don't share your organisation's goals, and therefore will have different problems to solve.
While one can think of every problem as a snowflake situation never encountered by anyone before, outside of its core business domain an organization (particularly a non-technical one) rarely faces truly unique challenges. Most of the time one can also decompose the solution into a number of well-known problems that had been solved before.
For example, in an overall solution for some snowflake business challenge you may see components such as an order taking system, a customer support center, a CRM, an ERP—and on another level patterns like a statically rendered site, an SPA, a “classic” content-driven site, and so on. In my opinion, being blind to these opportunities and intent on putting the entire solution together without any delegation of control flow smells of lazy architectural thinking and/or job security. The exact decomposition would depend on business specifics, foreseeable future evolution of the business, team capabilities and other factors, but as a result you’d be able to radically lighten the implementation and indeed maintenance burden with a strategic use of frameworks or even lightly customized CMS.
This simply isn't true for, well, every project I've been on. There is always some unique wrinkle in the requirements that means this project needs a different approach.
SAP is the classic example of this: SAP implements vanilla business processes (with lots of flexibility built in). Yet every single business implementing SAP needs extensive customisation and modification to make it fit their business processes. Some have spent millions or tens of millions trying to make SAP fit their business and failed.
In your terms; every business is a snowflake. You cannot create (for example) an order taking system that will fit all businesses. Or even "all businesses for whom order taking is not part of their core business domain". Only "those businesses who are willing and able to make their order-taking process fit your system".
You identify common aspects and snowflake aspects, and in the end the separation as to which parts are snowflake (contain business specifics). That’s your job as software architect. Again, the locations of snowflake parts tend to be similar across businesses, and this is where good frameworks and CMS tend to offer extension points.
It’s a spectrum: a CMS may be more fiddly as to customization but more reliable if your needs and extension points fit, framework offers more freedom, and a bespoke combination of libraries generally forces you to implement and integration test more of control flow and imposes higher costs of maintaining proper documentation as to how everything fits together (to avoid the next engineer accidentally killing performance due to a misunderstanding of how it’s supposed to work).
On the other hand, CMS and frameworks can actually inform your decisions, as their engineers had faced tasks similar to yours time and time again.
I work in startups mostly, where requirements are not defined and the business learns as it goes; it's simply not possible to identify all the areas that are "snowflake" ahead of time.
It is sometimes possible to persuade the business that if they create the process in a way that matches the framework it will make life easier for everyone. But often that isn't possible, and often there are good reasons for that.
I see. When writing my comment I also had in mind all the businesses that are not primarily technical (shops and such).
I think it’s often possible to identify the truly inflexible/snowflake aspects the business and still make use of frameworks/CMS. For a tech-focused company there are possibly more cases in which building your own is a viable decision, but with other companies that don’t have strong technical brains so to speak “this will cost you more to develop and more difficult to hire for later” is something they would understand…
<quote>Some have spent millions or tens of millions trying to make SAP fit their business and failed.</quote>
Any business that tries to make SAP fit their needs will fail to some degree (usually to a large degree, and expensively).
SAP will tell you in a heavy German accent that you bought the perfect business practices from them, and if you want to be successful, you VILL make your business fit SAP, not the other way around. In reality, they're right - All the really successful SAP installations I've ever seen had the company tossing all of their existing processes and replacing them wholesale with the ones built into SAP. Trying to make SAP fit foreign practices is a losing deal.
Yeah, I've heard the same. And this echoes what I think happens with frameworks. You cannot make the framework fit your process. You might be able to make your process fit the framework. But the further your ideal process diverges from the framework's process, the more painful it is and the more the benefits of getting started faster are lost.
> Not all software has an implied framework within it. Most Unix command-line utilities do not, for example, with only a few exceptions, and discounting the C standard library as something worthy of the label “framework”.
The C standard library is exactly that though, a framework for writing UNIX command line tools :)
A library is not a framework. You can write framework-free apps while using libraries (in fact, most do - not wanting to be burdened with a framework doesn't mean you have to write all functionality yourself).
A framework is either about inversion of control (it calls your code, e.g. you write web request controller logic, and it sets up the infrastructure for calling your controllers), and/or a set of ways to structure your code, like classes to extend, folder structure, a set of patterns you must follow to work with it, like a specific MVC-like organization of code, and so on.
Well to be pedantic, the CRT invokes a callback called 'main' with preprocessed (command line) parameters, in the 'main callback' you're expected to do something with the parameters that have been passed to you (for instance read data from stdin, process it and write back to stdout), and then return from the 'main callback' with a success or failure code.
Ok, I'm throwing together the CRT and standard lib here, but in the end both are parts of the "UNIX command line tools framework" which is supposed to provide a programming environment to easily extend the UNIX shell with your own commands.
By this definition everything is a framework. You're never the one calling code, it's always the BIOS, the bootloader, the kernel program loader, etc. I don't want to go all ad-reductio, but this is one of the points I have against the anti-framework people: the code you write is actually a pretty small percentage of the total code that makes up your system/application. Good engineering is working to make sure that code is differentiating code, not irrelevant code like garbage collection, HTTP header parsing, etc.
> You're never the one calling code, it's always the BIOS, the bootloader, the kernel program loader, etc. I don't want to go all ad-reductio
I don't think you're even being reductive; it's just irrelevant. The saying is to do with the software you're writing right now - do you include a framework (e.g. Django, Ruby on Rails, Spring) or do you include libraries that you could swap out (e.g. Flask - which terms itself a "micro framework", but is a library for this definition, ReactJS, SQLAlchemy) and your code is in control. You're right that the code will run on one or more operating systems, but abstracting out that far elides the useful conversation application developers can have about eggs and baskets.
> the code you write is actually a pretty small percentage of the total code that makes up your system/application
This is almost always true, but seems again irrelevant. How I write my application is worthy of discussion in and of itself, if for no other reason than, with a few exceptions, I'll spend a lot more time and money on making my application than I will thinking about how the Linux kernel works.
> I don't think you're even being reductive; it's just irrelevant.
The arguments here are:
"With libraries you call the code; with frameworks they call your code"
"This isn't a good distinction because there are lots of things we wouldn't consider frameworks that call your code"
That seems relevant to me.
> I'll spend a lot more time and money on making my application than I will thinking about how the Linux kernel works.
That means the kernel is doing its job, and if you swap out "Linux kernel" with "Django", that would also mean Django is doing its job. Without the kernel, you'd have to do a lot more work talking to hardware and scheduling other processes to run. Without Django, you'd have to do a lot more work wrangling HTTP and SQL.
It feels like peoples' issue with frameworks are that they force a way of thinking on you. But everything in software does that, the semantics of processes, pages, threads and so on are entirely made up, just like model view controller is.
> The saying is to do with the software you're writing right now - do you include a framework (e.g. Django, Ruby on Rails, Spring) or do you include libraries that you could swap out (e.g. Flask - which terms itself a "micro framework", but is a library for this definition, ReactJS, SQLAlchemy) and your code is in control.
I'd say by this definition (your code calls a library, a framework calls your code), Flask is every bit as much a framework as Django; I write functions that are called by the router just like I do for Django views. Sure, I can swap out the ORM and the templating library; I might even be able to swap out the routing library, but here be dragons. But a standard Flask application and a standard Django application are very similar. And if I wrote an application using Flask, it would be more or less a rewrite to swap in something else for Flask, because I'd be depending on Flask's request and response objects, at minimum.
This is partly why I don't think this definition is very useful, too. Clearly Django and Flask are different, but this isn't why.
>I don't want to go all ad-reductio, but this is one of the points I have against the anti-framework people: the code you write is actually a pretty small percentage of the total code that makes up your system/application
Which is neither here, nor there.
We're talking about a specific kind of inversion of control and forced structure within the codebase.
Else we could just go down an irrelevant rabbit hole, and it would like being a lawyer in a criminal case and arguing that your client is innocent, because "ultimately everything, including the murder, is just deterministic after-effects caused by the Big Bang".
Well, my point is that because this applies to more or less everything, it's not a great determinant of library vs. framework.
Like, the way you use Django is by wiring up URLs to functions [0]. This is pretty similar to setting up a vector table for interrupt handlers. Is that a framework? What makes Django a framework and vector tables not a framework?
I'm not trying to be pedantic here, I just really couldn't tell you the difference, and as a result, I'm not sure the distinction is useful. It sounds more like a post-hoc rationalization of why you like or don't like something.
Except none of these steps are dictated by the C standard library (some may be dictated by some libc's)
EDIT: To expand on this: You can call the code from stuff other than a shell; I'm assuming you mean "C runtime" by CRT, and some libc's may have issues without them, though usually only access to argc/argv and atexit(), and you can certainly write C without linking with the initialisation code; and while you'll of course usually enter via main() you don't have to. You decide the control flow.
The kernel loads your program, and schedules its execution. This is basically the same as using an async framework and sending the entry point to your application.
If you're willing to extend a little, there are also signal handlers, or setting up callbacks in pthreads.
Again this isn't to be reductive, but to say this is a super common method of encapsulating irrelevant stuff. It doesn't seem to be a significant differentiation between "I'm a library" and "I'm a framework".
CRT also does stuff like floating point emulation, loading dynamic libraries on demand instead of at load time (e.g on AIX and Windows), handling threads post C11, or runtime checks in hardened code.
The point is all of that is optional. You can - and I have - write C to be executed on bare hardware with no initialisation code, and depending on your choice of libc you can still use it (though some functionality may not be available).
Of course it is still C. You've just opted not to use some of the functionality.
Nothing stops you from e.g. providing your own startup code which then calls the appropriate initialisation code either.
The point being that there's no enforced inversion of control in the sense used by the article, and so calling it a framework in the sense described by the article is meaningless.
Even if we postulated the inversion of control was there, the fact you can replace all parts of it still means it does not fit the article definition.
If you were to write a program that relies on those aspects of the abstract C machine and don't provide those aspects, then you might have an argument, in that in that case the observable behaviour would be different, but if you choose not to make use of that functionality, its presence is entirely irrelevant.
This is also massively shifting goal posts. You first wrote "At which point it is no longer C". By your argument here, e.g. the Linux kernel is not written predominantly in C. But nobody uses the term that way. If you were to speak specifically about ISO C, maybe, but the person I replied to initially did not limit it to ISO C.
As such this is also entirely irrelevant to the original argument.
Everyone knows Linux is actually written in GCC C, and Google has burned lots of dollars making it work with clang, if it was proper C, that wouldn't never been an issue.
Yeah, that is why plenty people then show up on Stack Overflow with questions that prove how much they know C, versus "whatever my compiler did when I tried it out".
Any time a piece of software abstracts a repeatable pattern, that’s a ‘framework’.
All a framework means is that there is a coherent, repeatable model for implementing the building blocks out of which the application is built.
Even a simple command line program with hardly any functionality soon runs into the issue of having more than one command-line argument or environment-variable based configs. And a sensible, maintainable approach to this involves someone spotting ‘hey! We can abstract the bits that all our command-line parameters have in common so processing them all is consistent’. And then you have a framework. Because now ‘adding a new command line parameter’ has to be done in the standard way - you register a validator here and you add a help string there.
Building something without a framework is a rejection of patterns, or of the value of establishing repeatable structure.
Software that facilitates encapsulating chunks of functionality as standard building blocks is more maintainable over time. It’s much easier to work on a system where you can take a user story and interpret it as ‘okay, so we can implement that as a new Task type and then add a Tool to the Tool Library that lets users who have the right Role create a Schedule to run the task’. any time a system is sufficiently structured that you can think that way, it’s essentially become a framework.
Frameworks can be lightweight or heavyweight, sure, and they can be open to being overstepped or closed - and choosing when to prefer to structure your framework to make it easier or harder for someone to step outside the lines is just an engineering choice like any other.
No, programming languages exist in a different domain. The domain of frameworks is explicitly in toolchains and environments.
It's similar to the difference between function and algorithm. The former is literally code, and the latter is conceptual.
Many programming languages are distributed with a cohesive framework. For example, Rust is distributed not only with rustc to compile binaries, but also with cargo to manage library dependencies. That doesn't prevent you from using rustc without cargo, though, or even making another rust compiler for GCC, and using GCC's framework.
In some ways, languages - or features of them - certainly can be 'frameworks'.
What is a class definition in an OO language but a way for you to implement some state and some functions in a particular pattern that, when plugged in the framework of the compiled application runtime, will take care of the lifecycle and marshalling of calls to your code?
That meets all the definitions of framework provided by the author.
What you call a framework I call a function. I don't consider functions or the DRY principle to indicate a framework. A framework dictates how to proceed. A function is merely an available approach. To me this really sounds like imposing the word framework where the word abstraction is more appropriate.
The article precisely defines a framework, in its terms, as "an abstraction in which software, providing generic functionality, can be selectively changed by additional user-written code, thus providing application-specific software," where the "overall program's flow of control is not dictated by the caller, but by the framework"
Which is exactly what I am talking about.
If adding a new commandline parameter to your application involves adding a piece of validation logic that gets called on startup, putting an extra line of code into the help text initializer, and writing a handler to be called when the parameter is supplied... then the flow of control is already dictated by the application, and you are adding new functionality over the top of an abstraction. You are using a framework, not a 'function'.
> After 25 years of experience writing software I can honestly say I have encountered many people that agree with this, and perhaps all of them (every single one) have not actually experienced writing an application without a framework. This sentiment sounds correct in theory, but it isn't based on any experience from any one of the people making such a claim
I also have 25 years of experience and started my career writing C and FORTRAN on mainframes without any real library let alone a framework and then wrote my own libraries in C for my next job where I had to write cross platform code that ran on x86 based PCs and mainframes.
My next job, involved maintaining a proprietary compiler/IDE/VM for ruggedized Windows CE devices. So I think I have experience working without frameworks. Not to mention by the time I graduated from college in 1996 , I was a hobbyist assembly language programmer on 4 processors for 10 years (65C02, 68030, PPC 601, x86)
I can say that it’s the fifth level of hell coming behind an “architect’s” half assed framework who thought their problem was so special that they didn’t want to use a mainstream framework to handle non business specific concerns.
There have been a few times that I have ripped out my own code in favor of a popular library when I discovered it.
This isn't about NIH syndrome. This is about other people's code which is composable and can be mixed and matched with other code from other sources, compared to other people's code which dictates to you how your code is written, how it runs, and what contexts you can use it with. Libraries vs. frameworks.
> There have been a few times that I have ripped out my own code in favor of a popular library when I discovered it.
I'm much more likely to rip out the one function I need out of a framework or library and put it in my code, with a comment "// stolen from <source>". I've spent lots of time untangling the crux of someone's implementation away from the problematic abstractions they built up around it to make it universally adaptable.
Usually the security issues come from the wrapper code that tries to hammer the square peg of an algorithm into the round hole of the abstraction they provide. Dropping the wrapper code is the safest thing you can do.
I used to be a web app security tester. I loved it when I got an app that didn't use a framework for development because I knew I'd get some security issues for sure.
In the context of web applications, frameworks mean that your devs don't have to be experts in SQL Injection, XSS, SSRF, Session management etc etc etc.
My experience over several hundred tests was that without a framework there weren't many apps that could get that right first time. If they were lucky the pentesters found the issues, if they were unlucky, it was attackers.
A library could work here too, to turn off the footguns and provide safe tooling. No need for the library to also intercept all of the DOM callbacks for you as well.
Where do you draw the line between using and not using framework.
Programming language is a framework over machine language. Java garbage collector is a wrapper around manual memory management. Java Servlets is a pretty thin wrapper over HTTP request/response, is this a framework already? How about Java JAX-RS, it is built on top of Java Servlets and built to handle mostly REST type requests.
Same with database connectivity. Where framework starts? On JDBC/ODBC driver layer? ORM mapper like iBatis? JPA/Hibernate "true" ORM with automatic dirty checking?
It appears you are falsely using the word framework to describe abstraction. Language is not a framework. APIs are not frameworks. A framework is a tool providing conventions that dictate exactly how to proceed, typically demonstrated as a packaged architecture. The appeal, it seems, is not having to independently form many minor decisions.
It appears bias, and possibly even neurological limitations, largely account for framework dependence. Typically this is self evident when you step back and examine the opinions qualifying that dependency as most such arguments are fallacies from ignorance. Decision avoidance is the primary indicator of ASD.
For example many of the arguments in favor of frameworks will sound something like: ”I tried without a framework once and produced a framework anyways, so therefore you must use a framework”.
Another example: ”The code must broken and slow if not using a framework.” Without evidence (numbers) this is a bias (or a lie). Before making that claim there is likely no performance measure or comparative defect count. In my experience doing this for 25 years rarely measure anything and instead invent assumptions to qualify whatever opinion they want. Example (look at the parent and peer comments for comparison): https://news.ycombinator.com/item?id=33004060
>The appeal, it seems, is not having to independently form many minor decisions.
No. It's also to make the work easier and do the heavy lifting, too. Conventions alone are useless if the work becomes more difficult.
It's a vague term but it is pretty darn obvious what the desired intent is behind frameworks and why the endless discussions on their costs and benefits exist. Frankly, most developers couldn't care less about the semantics, they only care if the outcome is beneficial.
> I tried without a framework once and produced a framework anyways, so therefore you must use a framework
In my experience, the correct way of saying this is: I tried without a framework once, and I found myself rebuilding everything that the framework previously gave me. Therefore, I must use a framework (for things that are remotely similar to the thing I built a framework for).
For me the most important defining characteristic of a framework is inversion of control. With a framework high level control flow is dictated by the framework itself. It follows from this that using two different frameworks can be challenging.
An abstraction layer over a database is not necessarily a framework, it can be just a library. I'm not familiar enough with specific ORMs to comment on those.
A programming language is interesting to look at from this point of view. While sure, you need to use the programming language's features to implement control flow, it typically doesn't actually dictate a high-level control flow itself. There are probably languages where this is not completely true.
By this definition, though, which does seem to be the one used by the article, both Flask and Sinatra are frameworks. Which I don't necessarily disagree with, but there are tons of people here in the comments arguing the opposite.
For that matter, it seems to me that CGI would be a framework in this sense - the high level control flow is that you are called by the web server, run, take input from environment variables, output an HTTP response, and exit. Not fundamentally different from "Django views take a request object as an argument, and return a response object, and are called by the framework". Just a matter of degree.
Seat of pants definition is that a library is something with a single function. Add postgres support, logging (sort of a grey area sometimes), etc.
A framework is something that provides an ecosystem for you to develop in. Rather that using your own style/glue/etc a framework provides all of this for you. Another key aspect of a framework is how much it hides. It's not uncommon that a framework (like rails) hides almost everything from you down to exactly how it's launched. I suppose you could say the hallmark of a framework is it's closer to writing a giant configuration in a bespoke DSL than actual programming.
Sometimes I stated writing a web app with Sinatra, which is about the less frameworkish thing you can do in Ruby unless you are also writing your own router.
I regularly end up having to
1. Either write my own code to query the db and build Ruby objects from the response and viceversa OR use ActiveRecord.
2. Same thing about managing the database schema. Either my own code or someone else's. So why not Rails' well tested one?
3. Organize the code base in some way that makes sense.
4. Write my own code to manage tests OR use rspec / capibara (OK, they are not part of a framework but they are a large dependency)
In the end I always regret I didn't use Rails from the beginning because I end up spending a lot of time doing useless takes. Keep in mind that I do that for my own projects in my free time. 99% of the times my customers decide what to use (Rails, Django, Phoenix.)
* It lets me pick and choose an ORM. I usually prefer Sequel over ActiveRecord. Pretty much nobody suggests you should use Sinatra without an ORM unless you genuinely don't need a database.
* Nobody suggests you should build your own schema management. Pick an ORM which provides it out of the box (e.g. Sequel), or use a component which provides it (e.g. Padrino has a generator component which out-of-the-box supports generating migration helpers for the major Ruby ORM's and some you're unlikely to have heard of)
* Nobody suggests you should write your own code to manage tests. Just use rspec / capybara, or whatever else you prefer. And again, consider using Padrino's generator if you want something to generate scaffolding for it for you.
The point of using Sinatra is the freedom to opt-in to your preferred components as and if/when needed. If you always want the ones Rails provide, just use Rails, nobody will think less of you for doing so. Not even those of us who personally don't like using Rails.
For my part I rarely want the ones Rails provide, and so I rarely use Rails. Often I use bare Sinatra. Sometimes I mix in some components from Padrino because they can be easily torn out again.
I'd suggest that if you want something lighter than Rails but have those issues with Sinatra, look at Padrino (Sinatra + a pre-packaged set of components you can opt in or out of separately, or layer in piece by piece on top of Sinatra if/when you need them). But you can also just use Rails.
Counterpoint, and let's assume mostly parity of flask :: sinatra and rails :: django.
I've usually used Flask and even when I needed a few db operations you could easily contain that to a small part of the code and stepping up to django would have felt like a huge step up in complexity. But I guess it really depends on what you're actually writing - your use case sounds a bit like "something like wordpress" from a "customer uses this" point, and mine were mostly "small REST API endpoint for something".
Small REST APIs are usually not very small because they hit the database to perform useful operations, must be tested etc. Furthermore a framework enforced common structure shortens the onboarding time for any developer regardless of the seniority.
If that were true, what would be the difference between a library and a framework? Is a library not also factoring out common parts? Or is a framework just a bunch of libraries?
No, this definition doesn't describe what people understand as frameworks.
I would say the difference is that you can put a shim interface between your code and a library, allowing you to switch it out safely if desired.
A framework is a library that is so pervasive that you cannot reasonably do so - your shim would just be a copy of the framework's API, and it would be exceptionally difficult to take a different framework and make it fit the shim.
E.g. if you need to work with time zones, you can easily write out the function signatures you need, then look up any number of date-time libraries and make any one of them fit your shim.
But if you need to 'manage data flow between backend and UI', and try to write out the function signatures you need, you're either going to be copying a particular framework's API or you're going to have a hell of a time implementing the same signatures for two different frameworks if one is one-way and the other is two-way.
The article includes a crucial point about inversion of the flow of control. Somewhat exaggerated: You call into a library; a framework calls into your code.
The old archetype of a framework might be one which expects to control an overall event loop for your application.
In practice many things we would still recognise as frameworks allows you to undo that, but I still think it's a useful rule of thumb in that even many frameworks which technically allows you to remain in control of the overall flow tend to assume the framework will mostly dictate structure and flow.
> This sentiment sounds correct in theory, but it isn't based on any experience from any one of the people making such a claim.
Do you really think that there isn't a single person who claims that frameworks are good who has never written an application without one?
Well, now you know me. I've tried writing a website without React, and I ended up writing a buggy half-implementation of React. (In my defense, I didn't really know of React at the time.) You only really have to do that sort of thing once before you learn that frameworks have some advantages.
Your comment appears to reaffirm the consequent. Your comment suggests you tried to not use a framework once, but failed only to write a bad framework, which suggests you are incapable of writing code without frameworks. Is there something more to draw from this?
Maybe you should master your tools before using them.
You can use frameworks where they fit, and not where they don't. Knowing when to do which takes time and experience, but it is definitely do-able, and better.
Frameworks allow you to update, and maintain your app for free, since others will do it for you. If you do it yourself, you have to do all the work and that's keeping you from adding value elsewhere.
To not use frameworks these days would be objectively stupid unless you're working on extremely low-level things.
That's the big caveat. Loads of frameworks leave clear issues dead in the water. Your team/predecessors weren't the most clean. Now have fun fixing that one issue working out a framework you can't easily modify or switch out.
Of course that problem isn't unique to frameworks nor inherent to framework rather than social and legal problems.
The voice of reason. Frameworks just work for a reasonable cost, offer an easy upgrade pathway to follow, and facilitate the integration of new devs. In most case (depending of your business domain, of course), they should be more than adequate.
The cold hard truth is that most developers are not the genius hackers they fancy themselves to be.
I think you misunderstand the value proposition. In order to spend less effort on maintenance, thus freeing yourself to add value elsewhere, you need increased automation. That automation may or may not include a framework but is absolutely not limited to frameworks.
I instead prefer test automation to frameworks for automation. They are both tech debt, but only one of those provides a layer of risk mitigation (regression detection or changes to business requirements). The other provides a substitute for training, experience, and soft skills which suppresses risk realization. Just because the danger is hidden to lower layers does not indicate the danger is gone or avoided. If this were true frameworks would eliminate the need for testing and quality assurance.
> Frameworks allow you to update, and maintain your app for free, since others will do it for you.
Usually not for free. Sooner or later there's an API breaking change and you end up spending time reading changelogs trying to figure out how to get your code working again...
"After 25 years of experience writing software I can honestly say I have encountered many people that agree with this, and perhaps all of them (every single one) have not actually experienced writing an application without a framework. This sentiment sounds correct in theory, but it isn't based on any experience from any one of the people making such a claim."
Twice, I made the mistake of programming my own data frameworks so that I wouldn't have to rely on pre-existing databases. Total mistake both times. I have learned my lesson. (Most people wouldn't even think of doing that now; but I've been a pro since the 80's. The situation with web frameworks now is analogous in many ways to the situation with databases long ago.)
> So really this isn't a question of the software, but of the developer's capability to perceive (or not) that software.
It is quite telling of HN's audience if they honestly think that "every sufficiently complex framework-free application contains a [buggy] half-framework." The precise definition of a framework may be a bit hard to pin down, but most any experienced practitioner knows it when they see it. Things I look for:
* coupling of a blessed architecture, libraries, and patterns. Some choice of libraries may be allowed, but they must conform to a framework-prescribed interface.
* difficulty of isolating behavior for fast unit testing when using framework as prescribed (not always, but this is right more often than I want still)
* inversion of control as a core building block instead of straightforward composition. (This point gets fuzzier in callback-centric langs.)
* main() (or its moral equivalent) ends up being a framework bootstrap call, or is hidden entirely.
* related to last points: emphasis on hiding as many execution details as possible to present a simplified view of what the framework author believes is important.
* reliance on extension points to customize behavior (via subclassing/hooks) rather than simply exposing primitive operations that users can call alongside custom code.
* documentation beyond API docs and tutorials, usually necessitated by the number of novel concepts introduced by the framework
* heavier-than-normal emphasis on marketing, often leading with social proof from a megacorp, sometimes with big promises on how this framework is not like the others
The main takeaway should be this: a framework is not something that wants to blend into the background of your application. It is extremely visible and it is something that you program to, and often must take what it wants into account when designing. Without a framework, you can literally do whatever you want, including making a huge mess, or something small, functional and minimal.
I believe that should disqualify most of the rather absurd claims that all libraries/patterns/libc are "frameworks."
> have not actually experienced writing an application without a framework
There are a lot of different types of organizations, and their needs for development vary. Using well known tools reduces onboarding time, and in a large organization with turnover, that's not an insignificant cost. You really think the documentation you wrote for your app is better than those of a popular open source framework?
Frameworks also bring community defined best practices and standards. There is support from tooling like test frameworks that make functional / unit testing easy, linting and code formatting tools, IDE support, autocomplete snippets, debugging tools, browser extensions. These things might not be important in a small team, but with 100 devs, they bring real benefits.
> I just put all my state data in one object, save it on each user interaction
The saying is any "sufficiently complex app", and your approach to state management speaks volumes about the scale and type of front end apps that you work on. If you've never had bugs in your state using this strategy, it's wonderful. But if there were 100 of you constantly adding to and changing this global object, do really think that would be manageable?
How much state are you dumping in this object? If you only reference it on page refresh, your app must not be very reactive. One UI component could have quite a bit of state associated with it. One complex dashboard SPA could have hundreds of different pieces of state that are being tracked. Modern frameworks are tackling that problem, and the fact that you don't have it doesn't mean nobody else does.
I think of frameworks as running with crutches or cycling with training wheels. People interview potential couriers, look them in the eye, and ask: "DO you run with crutches?"
Not "CAN you run with crutches?" (as anyone who can run without crutches can run with them) but DO you run with crutches, as though running without crutches might signify a lack of ability. Fine time to unask the question.
> This sentiment sounds correct in theory, but it isn't based on any experience from any one of the people making such a claim.
I've written a number of frameworks, plugins, and extensions, and refactored existing ones. I've used a number of them. I tend to customize stuff, which isn't always conducive to using "heavy" frameworks. I've enjoyed "bald" ones. Done some big stuff.
Some came out great ... some ... not so great.
The "not so great" stuff tended to be early in my career. Refactoring existing ones, helped me to learn how to do it right.
I think the first one that I refactored, was PHP Nuke. It emitted terrible HTML, and my refactoring made sure the output would validate (and WAG the dog, so to speak). I ended up binning it, when they did their first upgrade. Learned a harsh lesson, there.
I wrote a framework in Perl. That was ... challenging.
These days, I tend to use a lot of modules and connectors, and use whatever framework is built into the OS (I write native Swift). I've heard great things about Laravel, but I have never used it.
I've been creating software for 40 years and I can tell you the statement "every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework." is 100% accurate. Back in the day we'd go and create our own frameworks that we could use on multiple projects. They were never as robust as the frameworks that exist today since we didn't have nearly the number of people using the framework and discovering issues. Not to mention the incredible amount of time we spent creating and maintaining these frameworks. Coming from that experience early on in my career to where we are today with people complaining about "too many frameworks" sounds like first world whining to me! :) I'll take too many frameworks over having to create everything from scratch any day.
In my current job, I have written a small framework. It's very limited in scope and hasn't changed much since the initial implementation, so it works fairly well. But, there is a big issue with getting other team members to understand how to use it. That alone is enough that we're replacing it soon.
Another team member has developed frameworks for both infrastructure management and creating services exposed over http. Here there is a large value in using the same internal tooling over 20+ projects. But once again, being an internal-only tool means that the documentation is severely lacking, and often we need new features in the frameworks. All of that is essentially blocking on the single team member. In this case we're keeping the frameworks, but it definitely has its caveats.
I am a big believer that the primary business benefit of frameworks is that they ease hiring (candidate selection). There are pros and cons to that.
Where I currently work they primarily rely on nontechnical qualities for candidate selection because they are more interested in choosing the right people than a tool user. Either way they will be investing time in training in some form and would rather that training focus on the business objectives than the technical objectives. Counter-intuitively I was entering the code earlier here than at previous employers even though I am writing in a language I have never touched before. This is likely because I entered this employment drowning in deliberate one-on-one training.
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.
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.
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?
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.
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.
- 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)
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.
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.
I've been burned by so many frameworks I am hesitant to use one unless the advantage is abundantly clear. Even something as mundane as an ORM can cause massive problems down the line if you're not careful, or you forgot to anticipate the case you need something more complicated than braindead CRUD.
Frameworks force you into a paradigm. Yes, to spin up quicker, get new engineers onboarded quicker, etc a framework will do the job. But it's not a free lunch. In exchange for this you are hopelessly intertwined in the author's idea of what makes something good. You're bound to their bugs, you're bound to the nuance, and most importantly you're developing knowledge of a framework, and not what the framework does. Some major frameworks, for example React, might pass the smell test as "just use it". This is the exception and not the rule mostly guided by the fact that Javascript is the absolute hottest garbage to ever grace our unfortunate field.
For some people this exchange is worth it. I'd generally recommend a company use pieces of a framework where they can. But to use a whole framework? Let's put it this way, early in my career I was involved in more old rails projects than I care to admit that were FILLED with kludges because no one could justify actually doing it right and in-housing most of it. I've been involved in projects that were hopeless dependent on the ORM-du-jour that were completely hamstrung because the ORM didn't take full advantage of the query planner, or lacked the necessary constructs for complicated queries, etc. ORMs are the worst, in my opinion, because the only other option is to then _force_ the ORM to do what you would've done originally (defeating it's purpose). General purpose web frameworks are close runners up (and related).
Your 5 points are nice sounding, and you probably get a lot of CTOs and engineering directors to agree with you. However, as a man in the trenches I can't say anything but you're fortunate to never have been on something complicated enough that a framework hamstrings you. Rescuing a project from a decision made by some framework-first shortsighted genius is the reason we get paid as much as we do.
I mostly agree with this, and also with the parent poster. I've seen framework become a big problem, and I've seen shitty ad-hoc frameworks for "framework-less" applications.
I've had fairly good success with what I like to call "framework libraries". That is, all or most of the functionality of a framework, but composed more as a library (or rather, a set of libraries) than a framework, giving you the best of both, mostly. ORMs are often given as an example, but I rarely found them as issue as most I've used have an "escape" to allow you to just use SQL if need be. The bigger problems with frameworks are when you want to compose some application in a way the framework doesn't really like (this can be a problem in Rails, for example).
I aggressively push things to libraries whenever I work on something; sometimes they can be made public, sometimes not, but even when private it helps a lot in mentality of people, especially with certain kind of devs.
I kind of feel that people talk past each other on this issue. If you use a bad framework, no framework is vastly better.
If you use a really good framework, no framework is vastly worse.
From one day to the next there will probably be one or two frameworks which dominate your work. If it's really good you'll have an overall positive impression of them and vice versa.
I completely agree, unless you are doing something unique, low level where ie latency is the king (which most of us don't), frameworks and libraries shine for 99% of the cases.
Some brilliant folks are just bored by usual rather generic work, and their idea of 'fun' is to keep reinventing the wheel that specifically fits current problem. Actual benefits to business be damned, intellectual fun is more important. Once those folks leave (and they always leave eventually), its mayhem for the remainder of the team/company.
For me, this kind of 'autistic' brilliance is overall just professional incompetency that shows over long time period and I avoid hiring such folks. One can babysit them and steer them but its rarely worth it within usual teams.
> Some brilliant folks are just bored by usual rather generic work, and their idea of 'fun' is to keep reinventing the wheel that specifically fits current problem. Actual benefits to business be damned, intellectual fun is more important. Once those folks leave (and they always leave eventually), its mayhem for the remainder of the team/company.
I could write a dissertation on this statement alone. But let's use two examples. Python and Node. Both are very "never do anything yourself" languages. Lots of libraries, even more frameworks. What's the result?
1. CVEs all over that place that effect nearly anything people touch.
2. Library creep. Pulling in one library or framework pulls in the entire planet.
3. Libraries and frameworks exist for absolute trivia. Node is famous for this, including stupid packages that literally just color text (and not in a meaningful way like a logger).
So in exchange for avoiding your alleged "autistic brilliance" you increase your attack surface 10 fold. I use libraries all the time, I am absolutely sure to limit their scope as much as possible. I won't use libraries for trivia, and I evaluate frameworks extremely carefully. It's kind of funny how often your opinion is parroted in startup forums but for some reason I keep making more money every year despite every signal pointing to me somehow being in the class of engineer that are, according to you, better off without a job.
Companies are run by idiots. The hubris you show is the same hubris a VP of engineering shows having last programmed 10 years ago. It shows a complete lack of nuance and understanding of the engineer.
When I was briefly on a Go project when go was still relatively young we decided to use a framework. I can't remember what it was...GORM + something possibly.
Three months later we find a few game breaking bugs. Do the right thing and send a report and hope the author's fix things. Things didn't get fixed in time. Now over budget and over the time limit I have VPs of engineering breathing down my neck (as the lead at the time) for why things aren't getting done.
This is not an isolated case. You might not run into this problem using a mature framework (the problem then is being bound by the author's idea of a good architecture), but if you're needing something better and venture into other languages for your needs you will run into this at some point. "Highly skilled contributors" often work for free. Perhaps I'd agree with you if you meant some professional, paid, framework. But I have never had an experience where these "high skill open sourced contributors" fix bugs inside my sprint cadence. The implication that I have an ego and skill problem for not using a framework, but these so-called contributors are "high skilled" is insulting to not only me but the entire profession.
I'd imagine the nuance is in what kind of language you use. Lowest common denominator languages like Ruby, Javascript, etc (things that can be learned quickly in a code camp) tend to be dominated by framework-first-and-always people since frameworks can be parsed easily by seat warmers. Engineering management loves frameworks because it takes the thinking out of writing code. The maligned view of engineers as people who will "screw things up when they're left to their own devices" is so pervasive they've even got other engineers parroting it.
If you believe it's a "lack of skill" or "ego" problem to honestly not use a framework in some cases you should probably stop hiring idiots. An actual "high skill" engineer will evaluate the cost and probability of needing to break out of a framework.
I've had a couple of cases case where a bug was not fixed in time or fixed at all which results in writing workarounds or forking which is far from an ideal solution and further reduces the advantages of using a framework.
> 4. Over time, everything degrades. In the long run, many framework-free applications either get walled off as "legacy" apps with new work done in separate services, or replaced outright. If it makes you money before that happens, you win. It is not necessary to try to design architecture that will last for centuries
not sure what framework-free has to do with. I'd remove the word "framework-free" and it would still be just as true
The adhoc framework will also be half known to 5% the current team and barely known outside of happy path use cases to the rest. If you find a bug with the adhoc framework you need to convince a busy person in another team to spend time to unblock you. Or chuck in another hack and move the ticket to done and walk away slowly with stretched out arms.
> If you find a bug with the adhoc framework you need to convince a busy person in another team to spend time to unblock you.
Which is not so difficult, because that busy person is in the same organisation as you, and therefor working towards the same goal.
Fixing that bug is much more difficult if that person is in an outside organisation, serving many other customers on the same code base (with possible conflicting needs), and/or is not actually in any way accountable for it (open source).
> Which is not so difficult, because that busy person is in the same organisation as you
Hopefully. But not necessarily. This argument is spinning in circles.
In house projects can be abandoned just as oppen-source ones can.
For me that was Powermock for example.
> Which is not so difficult, because that busy person is in the same organisation as you, and therefor working towards the same goal.
{evil laugh.mp3}…
Ideally yes but in reality: all teams have bottlenecks, and nearly all teams have assholes. Is fixing your problem on their OKR or whatever.
Free / open source code can be fixed by anyone: the volunteer owner (who you could even bribe to fix it), any contractor with experience, or someone in the org. This is the beauty with free software. It enables people to fix their printer drivers even if they didn’t write it originally.
Free / open source code can be _forked_ by anyone, but in doing so one often takes on a maintenance burden bigger than one's current codebase.
To have a fix accepted on an OSS project means fixing it not just for your use case but also for every other user of the project, on every target platform, while aligning with the goals of that project. If you can get anyone to look at the PR in the first place. Assuming you've used the framework to save time, you probably don't have time to go through all that and your deadline will not wait a month or six for your code to make it into a release. Depending on your employer you may well need internal permission and legal sign-off to contribute to an OSS project in company time which is yet another hoop to jump through; though that goes for forking too.
Frameworks have a very narrow compatibility and accessibility range, and to get the other (often more than) 20% requires extra hackery which has to be bolted onto the framework in ways that were not foreseen by the framework writers.
I've come to believe the difference between framework-lovers and framework-skeptics is that one (larger) group is generally following a well-trodden path and doing only things the framework authors anticipated. Viewing a framework as a common architecture extracted from the experience of writing lots of software, this makes total sense. Most software looks like X, so a framework like X will look like most software.
Those who have problems with frameworks are solving problems that are to some extent novel. Maybe only 10% novel, but that's still enough to feel like the framework is a straitjacket - because everything else is a solved problem and that 10% is the hard bit and the framework just makes it even harder.
Perhaps some of those people could re-examine their problem and achieve it in a different way using the framework, but others couldn't. But to say "if you're not using a framework you're doing it wrong" perhaps exposes a lack of experience with unusual problems, and "all software ends up containing a custom framework" is confusing frameworks with architecture.
One example I can think of was the Play framework.
If you wanted to work with Scala 3 and Play 2.7, you couldn't.
You needed to stick with Scala 2.13 to be able to use Play 2.7.
This was more than a year ago.
Now we have Play 2.8. Is it compatible with Scala 3 now?
Edit:
I am not entirely sure whether it was possible to make Scala 3 and Play 2.7 work.
So my statement above might be partially wrong.
However, I had other dependencies too, which required me to use Scala 2.13.
Consider to downvote this, if you think I made a false statement.
I should have looked up the documentation beforehand and not rely on my (past) personal experience/impression at all.
Things that you (can) put away behind abstractions, layers or wrappers.
I'm the author and tried to convey clearly the difference between libraries and frameworks. Both allow code-reuse, both allow "standing on shoulders". But one allows you to do so with freedom of movement, independence and domain constraints (libraries) whereas the other locks you in, enforces architectures and designs and requires workarounds when your domain-requirements differ from what the framework dictates.
I agree with a sibling commenter after reading the article. The main point, as I see it between the lines, is not to refuse to use functionality (app side), but instead how this functionality should be packaged preferably (module side). Nothing prevents the one “in control” to give it up and expose a meaningful degree of it to a user, along with default mode convenience for those who want boxed version.
Frameworks actually add to a deplorable side of the software industry. They encapsulate truly great efforts and wisdom into a package which cannot be unwrapped and used partially. They are like smartest CPUs soldered into shitty boards (or simply incompatible with your requirements) without a chance to unsolder the functionality and use it elsewhere. You can’t make your own and you can’t take one off the shelf.
Consider this imaginary example: someone figured out all of the nuances of dom events across all browsers ever and made a clear api to it. Library way is to provide (Context, DomEvent) => MyEvent. Framework way is to create a complex rendering idiom in which MyEvent appears naturally and is an implementation detail. In the latter case you buy two for the price of two, and only so.
Or, they want to test a new idea/paradigm in some area. Without composable libraries, they are doomed to repeat all the mistakes you pointed out because to compete with already existing solutions they have to go all the way through issues unrelated to the idea itself. All that only to battle test it. For most library makers, the desired outcome is a sum of all parts, not just one.
> Frameworks actually add to a deplorable side of the software industry. They encapsulate truly great efforts and wisdom into a package which cannot be unwrapped and used partially.
Do you have a concrete non-hypothetical example? Because I don't think I've seen this.
Say what? That unholy mess of annotations, unusable outside of the Spring "walled garden" where you have to search the internet on how to do the most basic thing (with annotations)? Spring(Boot) is the perfect example --to me-- of a framework that dictates, and does not allow to be get out of your way when all you want is "just libraries".
I have to disagree with that. I have developed software without frameworks before, and have come to love a good framework. Spring Boot is a performance multiplier. It may look scary at first because it has so many (optional) modules that supports everything from basic injection to cloud infrastructure.
You don't need to use everything just because it is available. Even basic web services are not enabled by default, and is something you need to explicitly add as a dependency. If you don't want to use Hibernate, just import a different dependency instead.
It lets me focus on business logic, while handling the interface outside the "garden" for me. In my experience, the use of annotations is confined outside the business logic. If that's not the case, the code is organized badly and will cause issues regardless of framework.
Example (could be improved of course)
@RestController
@RequestMapping("/dogs")
public class DogController {
private final DogRegister dogRegister;
public DogController(DogRegister dogRegister) {
this.dogRegister = dogRegister;
}
@PostMapping
public void registerDog(@RequestBody Dog dog) {
dogRegister.registerDog(dog);
}
}
If I decided to change it to a message based approach, I could do that without changing any business logic, by replacing the controller with a queue listener. Also note how IOC will automatically inject the business logic component.
@Service
public class DogListener {
private final DogRegister dogRegister;
public DogListener(DogRegister dogRegister) {
this.dogRegister = dogRegister;
}
@JmsListener("dogs")
public void registerDog(Dog dog) {
dogRegister.registerDog(dog);
}
}
In my view this is a framework that gets out of your way. I did not have to change the business logic (dog service). Spring takes care of the interface outside the program. If I wanted to switch to a different standard than JMS, I would most likely in many cases just need to change to a different annotation.
If the code is organized badly, the business logic would have been included in the controller and be harder to change. But isn't that the case of bad structure in general?
Spring nowadays supports the JDK-native annotations where the exist, and they have a lot of Spring-agnostic libraries under their umbrella.
But I'm inclined to agree on the case of Spring Boot... It's meant to be a "convention over configuration" kind of thing, so I guess by nature it ties you in pretty hard.
>1. Every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework
Every sufficiently complex built-on-top-of-a-framework application contains an ad hoc, informally-specified, bug-ridden, slow implementation of workarounds to the framework's limitations, the overhead of parts it doesn't need, a nightmarish dependency situation, and as a cherry on top, it ends up based on a previous version, of the framework (as the latter's creators rewrite with different APIs every couple of years for no good reason).
Often you end up with an external framework, and an internal framework, and workarounds for both of them.... that are trying to evolve into their own framework
Re point 1: yes. But it’s your bug ridden half framework and you don’t depend on external developers to make sane decisions.
I’ve been using static site generators for my product site and app documentation and every time I set up a new dev machine e (or just update the generator) I’m in dependency hell because some plugins had breaking changes etc. that’s why I switched to my own bug ridden php implementation of the site/docs. At least I don’t get to spend the day googling for change logs, etc when I type ‘make’.
PHP is a bit of a special case here. I returned to PHP after 10+ years of hiatus and was surprised how easy it is to get shit done for the web, I had forgotten all about it.
> Using libraries and frameworks is like a business outsourcing things that aren't its core competency and also aren't competitive differentiators.
Adopting frameworks is a variation on the the Build vs Buy question, even when there's no money involved. Does the framework provide some features that are necessary for the technology but not core to what your business does? It's probably OK to use. A company that adopts a framework for its core business is essentially giving up any competitive edge, because any company that uses that same framework with the at least the same skill as your team will end up being a viable competitor.
Software is a layer cake and in my opinion from 20 years software development experience I firmly believe that the top 1-2 layers of your business application should not rely on some framework if you want to create a great product, stand out amongst competitors and have a technological advantage in terms of innovation and maintenance. Whatever happens at the top 1-2 layers is what your business cares about the most and what defines your business and you want to have 100% control to fine tune it. I've worked in many companies and on many projects and this made a difference every time.
This is good and I pretty much agree. One thing though is that I think #1 and #4 actually also apply to framework'd applications. In my experience, even apps built on Rails end up with a business logic-level "framework" that is ad hoc and not obvious to newcomers, which results in bugs.
Not to mention, the frameworks tend to be hard to use "correctly". Rails devs will have heard the term "the Rails way". In fact this article has an awesome example. There's a snippet of code of a controller checking to see if a User exists with the given email. Any Rails veteran would know that you can just call `User.create` in the controller and rely on validations for that kind of check. But that's another problem with frameworks - you have to know the whole thing in order to use it well.
That has long been one of my complaints about Rails. It creates a nice directory structure for the framework's objects. But there's no obvious place by default to put business/application "your logic". So then all that stuff gets wedged into huge controller and model files. (in the old days there was a division between 'business objects' vs 'data objects' etc)
#1 is definitely true. I had my own halfassed 'framework', and have dug into enough older web apps to know that everyone else had one too. (Or at least the smart ones did.)
> But that's another problem with frameworks - you have to know the whole thing in order to use it well.
The difference is I have plenty of resources at my disposal to learn how to use a popular framework. I only have hopefully the one “architect” who thought their problem was a special snowflake to ask about their framework - if they are still at the company.
> But that's another problem with frameworks - you have to know the whole thing in order to use it well.
This applies to whatever in-house monstrosities get built too, except that without docs or a million eyeballs to judge whether a workflow makes some sense to an outsider.
Right. I'm definitely not trying to say that apps on a framework are actually larger and nastier than frameworkless apps. They both get large and nasty.
> Every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework.
I want to credit both the reference (it’s about lisps) and my frame of reference (there are at least a couple of should-be lisps in projects I maintain, and at least one more I think would benefit from a going concern that seldom gets recognized as lispy but absolutely is).
Something I keep observing that seems to be passed over, coming from a Rails background, is that by using a known framework, the company is also accepting the "population" that comes with it, as well as the known problems.
I observed many Rails developers and many apps (purely anecdotal, I wish I could run a real study), but the problems are the usual, the ones on top of my mind right now:
- database changes affect directly UI code, so a change in the DB requires changing code in a million places
- Rails devs don't know SQL as much as they should (often just don't know it), for a framework that so SQL-centered, it's weird
- hidden logic (callbacks)
These are very common problems with this framework and are well known to hinder company growth and ability to iterate.
Would a home-grown framework be better? I cannot tell, but surely if the list of downsides when choosing a framework was written in the splash page, I would be way more scared.
"If you use this framework, your db will 100% be coupled with your frontend" is a terrifying statement.
Given that, framework should be evaluated for their downsides too, but there isn't even a list of known issues.
100% worthy observation from my career experience.
Choice of a framework both attracts a certain type/subculture, and repels another.
Example: You have an old app that uses Backbone+CoffeeScript for the front end. If you stick with that, it will absolutely impact your hiring. But what about switching?
If you pick React, that will have one impact. If you pick Ember, that will have a different impact. And so forth…
Also, speaking very specifically about Rails, every architecture is composed of design choices that make some things easy, and other things hard.
The default "Rails Way" has a particular dynamic around REST and CRUD that makes it very easy to "Extrude the implementation into the interface," and, "Extrude the implementation into the API." It's what accelerates building a thing the first time, but later on it can work against you.
JM2C about this, but it's what I have observed and have lived through refactoring on multiple occasions...
> 1. Every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework
Yet a nicely designed, simple, custom half-framework is cheaper to maintain than a bloated popular framework.
Unless your half-framework has equivalently good documentation as a popular framework (which hardly ever happens), this thesis break apart as soon as someone who didn't implement your in-house creation needs to maintain your project and fix your bugs.
For a "sufficiently complex application" it is more likely than not that the framework of which half was implemented in an "ad hoc, informally-specified, bug-ridden, slow" way actually is not available anywhere. Instead, very likely, some random framework that sounded like its functionality is somewhere in the direction of what is needed was downloaded and now partially helps and partially hinders development. Probably it hinders more than helps. But this assumes "sufficiently complex application". For a simple application it is more likely that a helpful framework is available.
Do you think that formal specifications might alleviate logical bugs to an extent?
Yes, it appears that companies won't budget that at all.
Many seem to ship fast, fix later.
It is also on the customer, really.
Some people expecting software developers to deliver high quality software (with near 100 % code coverage and exceptional performance), but paying them less and less, is not fair.
No wonder, some devs are incentivized to skip unit tests or error handling.
Because some employer or some customer won't pay for it.
This is the status quo that makes me pessimistic.
It appears that software development is gluing things together and make it somehow work.
I shudder to think about what a formal specification of some of the full stack web projects I've developed would look like. They might take longer than the actual coding of it - especially because specifications change mid project as we build things and realize we actually want them different.
Note this is a feature, not a bug, of "agile" development - you learn and adjust on the fly
I seem to have upset people. I’d certainly be interested in knowing why, as my comment directly addresses the parent, and does not coarsen the discourse.
I think this argument is about free vs. not-free frameworks. Frameworks that are supported by a company and actively developed are far superior to the state of NPM open source right now (thinking of Qt vs Electron and my 7 year battle with both).
It is no fun when an open-source framework pushes a new major version, then deprecates the version you were on, or dependencies fail to find matching version, and you beg github developers to fix the bug and your issue sits open for months and is then closed with no warning.
I think some of your experiences can be explained by your citing NPM as representative of FOSS. Not that there's anything wrong with the astonishing breadth of functionality available in the NPM ecosystem, but stability isn't its strongest comparative suit. OTOH, Django, which was cited by the author, just doesn't have that kind of volatility in its base features.
> Not that there's anything wrong with the astonishing breadth of functionality available in the NPM ecosystem
There are at least two things wrong. One is those things is missing standard functionality (eg, leftpad), and the other is a failure to maintain appropriate hubris (eg, is_even).
And it is no fun when the manager of the company developing your proprietary framework decides to tank it because of a change in strategy or the competitor buys the company and stops development. Since you have no source code you are forced to do what the commercial interest of foreigners dictate.
That is far, far less likely than a package being abandoned. What happened to your project? What "commercial interest of foreigners" went under that doomed you so?
I would add though, that if the framework consumes much of the attention of the developers, then it is still a loss.
And I would add to the title, that using a overly _hyped_ framework will harm the maintenance. Using some framework, simply because it is new or hyped, that will get teams and companies in trouble.
Not my experience at all. The fewer frameworks I use, the more solid and reliable the software tends to be. And you avoid the yearly “our current framework is crab so let’s try something else” rewrite that everybody else seems to be involved in.
> Every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework.
This is simply false.
On the other hand, every sufficiently complex framework-dependant application is way too complex for what it does, and would be a lot simpler if it was not using said framework.
> My last and--to me the most significant--observation is this: You want to pay the majority of your attention to the code that has the greatest impact on your desired outcomes.
One of your greatest desires should be to have strong propietry technology that you control. Otherwise you are not different from anyone, and anyone can duplicate your work in two months by just using the same framework.
Avoiding the use of a framework does not preclude someone else from duplicating your work in two months by using a framework. It just means that you wasted a whole lot of time hand-rolling things that didn't need hand-rolling.
Most businesses are not successful by virtue of the technologies they choose. Facebook is probably the foremost example here; they started with PHP and moved over time to leverage additional technologies (some homegrown like hack and react, others just additional languages like C++).
There are plenty of facebook clones in plenty of languages. The technology isn't the reason Facebook hasn't been supplanted by a competitor with the exact same product.
No, it's not "simply false". It's something that many of us have repeatedly observed happening and probably done ourselves at some point. There are of course exceptions, but it's not really fair to bluntly dismiss it.
One of your greatest desires should be to have strong propietry technology that you control
Yes – and you should be investing your time in making that "strong proprietary technology" more effective, and spending as little time as possible doing all the bits that your competitors didn't have to do because they picked an off-the-shelf solution that did most of it to a "good enough" level.
This notion that frameworks save you time is just ridicluous. Unless the framework is doing something really complicated and difficult (like, say, a 3D game engine such as the Unreal Engine), chances are it's costing you time and effort.
What often ends up happening is you have to do a lot of useless work to get around the limitation of the framework you decided to use at the start.
Since most people on HN are in the web space, framework often refers to things like "Django" or "Redux". These beats always cost way more than they provide.
For a web server, a library like the standard "net/http" in Go is way more useful than a "framework".
I remember people saying this in a PHP days and almost without fail their code would be littered with security bugs. They don't a template language, and there would be a XSS vulnerability. They don't need an ORM, and there would be a SQL injection vulnerability. They don't need a form library, and there would be a CSRF vulnerability.
Now-a-days there are less security vulnerabilities and more buggy messes powered by Express.JS. API's with shitty query string parsers than crash the server.
The average developer should just be using a framework.
You're basically saying the average developer is grossly incompetent. Which I don't necessarily object to, but it's important to be aware that this is what you are saying, even though you are not using the exact phrase "grossly incompetent".
If the average developer is so incompetent maybe they should undergo further training before being allowed to touch production systems? I suppose this is what code reviews are for, but I don't see how it helps when incompetent developers review each other's code.
The tricky part is that many more developers think they're capable of handling all these issues than actually are.
Web app security is a genuinely tricky area with lots of edge cases. Good frameworks provide abstractions that mean you don't have to deal with a lot of those problems for most mainstream cases.
Are we all talking past each other? IME there is a time for using an off-the-shelf framework and a time to hand roll from scratch. (For varying definitions of scratch.)
Generally when a company's tech needs aren't very unique, and they seek to compete on time to market, then a shelf framework makes sense. Companies whose needs stretch the boundaries of shelf frameworks too much may be better served by building on a lower level platform like from a standard library--entirely or in part.
Yet building from scratch is costly. Depending on the stack / language chosen it may cost an "innovation token" or three. Small companies can't afford a lot of these tokens. And lots of eager engineers want to believe their problems are unique, dragons never before defeated. IME most problems aren't like that. They're boring, such as a codebase that's lost its fit as the market or company has grown, pivoted, or contracted.
> This notion that frameworks save you time is just ridicluous. Unless the framework is doing something really complicated and difficult (like, say, a 3D game engine such as the Unreal Engine), chances are it's costing you time and effort.
... Have you ever written a simple web app? Pull values from a db and present them somehow? Having something that just gives me places to plug in the business logic makes this pretty trivial.
If you think "net/http" is more useful and contains more functionality and less need to reimplement
* HTML forms
* and admin
* a plug-and-play security framework that's already worked out all the kinks of crypto libraries
* an ORM and DB libraries for a half dozen production-ready DBs, with their kinks in transaction and connection management already sorted out
That is a pretty extreme take - that frameworks “always” cost more than they provide? On what do you base this categorical assertion? I’ve been in this industry a long time, and based on my experience that’s not true at all. “Sometimes” they cost more, if your problem is esoteric or a poor fit to a general framework.
Most problems aren’t.
Even if this were true (and sibling posts make compelling counterarguments), you've completely overlooked that the value of a unit of engineering time varies wildly. Spending weeks of engineering time re-implementing all the security features Django provides out-of-the-box is suicidal when you're trying to get off the ground. It doesn't matter that it could save months down the road if your project literally doesn't exist anymore.
Not really true. Sure they add some, but the alternative (libraries) also add weight. So the question should be: do FWs add more weight than using libs directly.
There are some FWs in Rust where the weight is very minimal. That said the FWs are also very minimal.
> 3. If you have a small team that hires slowly, it's relatively straightforward to bring new devs up to speed on "the way we do things." if you are hiring rapidly and/or have a large team, the more bespoke things you have, the harder it is to maintain them.
I disagree that framework or no-framework is the distinguishing characteristic. I do think that the quality of the code base, documentation, and onboarding plays a role in how fast devs get onboarded. Anecdotally, the only framework-based projects I've signed on to ended up incurring more onboarding time because I had to learn the framework, how the framework does things, and then how the team does things in the framework. All of this "how" is a step before "why", of which, every step eventually needs to be repeated over the course of my tenure in order to be successful.
> 4. Over time, everything degrades. In the long run, many framework-free applications either get walled off as "legacy" apps with new work done in separate services, or replaced outright. If it makes you money before that happens, you win. It is not necessary to try to design architecture that will last for centuries.
I've personally never seen this in any language except Java. Spring might as well be Java at many companies. The bespoke applications stay around, in my experience, because:
- They exactly match the business requirement and that requirement doesn't change much
- People don't know how to work on them or the product has little funding, probably because of the above reason
- The company has hired a team to maintain the product that have not moved
I've also seen where companies try to replace something bespoke with something written in a framework where the budget expands multiple years in a row and the project never completes because it's impossible to make the framework do what the bespoke product did completely.
> 5. My last and--to me the most significant--observation is this: You want to pay the majority of your attention to the code that has the greatest impact on your desired outcomes.
To me, this reads as, "we should spend the majority of the time focusing on our core competencies". I've heard this time and time again in this industry and no matter what way I've heard it explained I've never liked it. Businesses that only stay in their core competency, or narrowly define their competency, often stagnate with time. There's a lot less opportunity for organic business growth with that mindset. They'll also have little expertise to solve problems as they scale, other than through purchasing, because they only have knowledge that serves their core competency. The businesses I've seen become most successful alongside strong technical success were businesses that encouraged employees to innovate and experiment in new ways on a rhythm, allowing that innovation to inspire and percolate when it finds a strong usecase.
> Anecdotally, the only framework-based projects I've signed on to ended up incurring more onboarding time because I had to learn the framework, how the framework does things, and then how the team does things in the framework. All of this "how" is a step before "why", of which, every step eventually needs to be repeated over the course of my tenure in order to be successful.
This is one of the most interesting replies, thank you.
The pitch for a lot of tools—be they frameworks, libraries, languages, &c.—is that if they’re popular, you get to hire people who arrive already knowing the basics of how things are done.
The reality is that popularity waxes and wanes, so when people are evaluating a tool’s fitness for purpose, they sometimes have to read tea leaves to decide if it’ll pay off or not.
A company making several such wrong bets in a row often has a trail of poorly supported ancient technologies lurking around. They still work—Joel Spolsky famously said that code doesn’t rust—but it’s aggravating to onboard, there are few productivity advantages, and sometimes the same thing is done three different ways because the company made two “wrong” bets before making the bet they currently think is “right.”
Would things be better had they just done their own thing and stuck to it? Possibly, I tried above NOT to make a claim that a popular framework is either the right thing to do or the wrong thing to do.
But it is good to read your comment pointing out that sometimes, a popular framework isn’t popular enough to harvest the benefits for people onboarding.
> 1. Every sufficiently complex framework-free application contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of a framework.
Of which you are the creator and expert, and have complete control and insight, and can change it in any way you want any time. It is in 100% alignment with your goals at all time.
If you use a framework your organisation becomes incredibly complex, because you are now actually competing against the needs of other companies, your competitors, which are also influencing the framework.
Your software is custom made for your organisation, it's not mass producing identical systems on an assembly line, so it doesn't make sense to share a common platform like you do with cars. And even if you did, this platform would be a joint venture, and absolutely not made by a subcontractor, and no way in hell some random unpredictable volunteering hobby organisation.
No, I'm not. The guy who quit 2 years ago was. I've worked with custom frameworks, and while they where both clever and powerful with some quite cool features which would have been tricky to do in a more generic framework, they where also virtually undocumented, fragile, difficult to extend and slow to get people up to speed on.
I'm confident most software engineers I've worked with understood this. Usually the problem wasn't understanding that but rather meeting the deadlines and finding the resources to write that documentation. The only time I've seen documentation done really well, the company had a dedicated technical writer whose main job was making sure they had good documentation. Engineers would write the first draft and hand it off to the tech writer. My impression is that many companies don't want to spend resources on that level of documentation, which is the level you'd probably want to roll your own framework.
I meant it "part of the job" the same way unit tests are.
I see this more often when the project is open source. For some reason we feel like when its not, we don't need to pay attention to the documentation. Nothing could be further from the truth.
> Of which you are the creator and expert, and have complete control and insight, and can change it in any way you want any time. It is in 100% alignment with your goals at all time.
And then you change a job and you take 80% knowledge with you and your now-past project is in deep trouble.
If knowledge is on a single person alone, then your ex-company has bigger issues than framework or no framework.
Not to mention that the interesting parts of your app should be the domain logic and workarounds and solutions used in it for business issues and historical layers of bussiness logic choices. And that a single person can take with them whether there's a framework or not.
These are generally just resource issues. Companies generally won't pay for engineering hours to build really good framework documentation. It's not in the critical path. Companies that know that documentation, as well as tests, compatibility guarantees, security policies, etc. are actually critical components would probably not ever make the decision to take on that engineering burden themselves unless it were a business differentiator, which it almost never is.
> Not to mention that the interesting parts of your app should be the domain logic and workarounds and solutions used in it for business issues and historical layers of bussiness logic choices.
In my experience this has been a point in favor of OTS frameworks--the code you don't care about is handled by the framework, and you bring the business logic. But also, reading through this, I guess I don't understand your comment. Isn't the business logic in the code? How can a person take it with them?
> In my experience this has been a point in favor of OTS frameworks
Its not guaranteed. I've seen many developers spend lots of time trying to get the framework they're working in to cooperate or dig through bad documentation. Framework authors are fallible too and general-purpose software is really hard to get right.
Well, my point here is that even if there are little patches against a framework, we're talking something like 5% of the repo's code is framework-y stuff. If you've got your own framework, then... what even is the limit? 50%? 90%?
I wonder if some of the disagreements in this thread are just like, people in favor of frameworks used Rails/Django, people against them used Spring/Struts.
> Framework authors are fallible too and general-purpose software is really hard to get right.
Yeah, I think that's solved by the "market". There was a big explosion of Python frameworks in the aughts: TurboGears, CherryPy, Pyramid/Pylons, Zope, web.py, etc. etc. Lots of stuff. The ecosystem now is Django/FastAPI (Flask/Tornado legacy apps are either stuck or moving to FastAPI IME). Django got it right.
But more broadly, what are the odds a bespoke framework will do it right? Will you think up a new way to organize controllers, or to abstract auth, or to manage database sessions, etc. etc. etc. That sounds like a nightmare to me; just let me focus on the business logic please, haha.
The market will settle on "good enough for the average usecase".
> But more broadly, what are the odds a bespoke framework will do it right? Will you think up a new way to organize controllers, or to abstract auth, or to manage database sessions, etc. etc. etc.
Some of this is a nightmare indeed (e.g. dealing with any web security stuff). Other things are very straightforward, especially when you don't have to deal with 1000 other people's use cases but only your own.
> just let me focus on the business logic please
We all want this. The question we should be asking is do we spend more time fighting a 3rd party framework or implementing our own. The answer may well be we'd spend more time implementing our own - but its still important to be aware if things start to go south.
> Other things are very straightforward, especially when you don't have to deal with 1000 other people's use cases but only your own.
> ... fighting a 3rd party framework ...
Can you give some examples of this? I'm personally finding it hard to come up with examples where this is a significant problem. The closest I can get is I worked on a Django REST Framework project where we went all-in on serializers, but then ripped it out because performance wasn't where we wanted it to be. But it's pretty easy to not use serializers in DRF, so it wasn't actually significant.
- Fighting webpack (its plugin system makes it a "build framework"). Lots of configuration complexity to support thousands of possible tool configurations, when you need only one combination.
- Angular v1. Scope, transclusion, watchers, directives, DI and things randomly breaking.
- Almost all of the modern devops configuration tools. Would be easily replaced by some very basic typescript functions / libraries and Deno. In fact, cdk8s (which is typescript) comes with a mandatory jsii layer included, adding about 150MB of node_modules. This layer translates between the TS API and other languages you might use (Python etc). You get it even if you don't use the other languages and it has measurable impact on e.g. CI run times
- Bazel (another "build framework"). You just wanted some basic build caching, but get to do all the work for perfect hermeticity instead, which includes things like different directories, dealing with symlinks and dealing with tools that handle those symlinks poorly.
Its really, really easy to pick the wrong tool(s).
Yeah, I definitely see what you're saying here--I think a lot of people have had really frustrating experiences with these tools (even though I might quibble about them being frameworks).
But is it a reasonable alternative to build an alternative to webpack yourself? Or Angular? I would bet some people have tried/done this, and also have some frustrating experiences.
My point is I think you have to be _very_ careful when deciding to take on a big engineering project, like making your own JS build tool. Will the improvements in devex really outweigh the engineering hour investment? IME the answer is almost always no, what usually happens is you get a half-baked, non-documented/tested system, and reading through this thread, I'm not sure any of the anti-framework people have shown convincing examples where they did better than an OTS framework.
Or if they did, they released it! Django is famously one such instance, or your Bazel example. It seems like they bet right, or did a lot of off-hours work (pretty sure that's the case w/ Django haha) to get it going.
> But is it a reasonable alternative to build an alternative to webpack yourself?
Before code-splitting, yes, it was quite easy (not much harder than building a makefile). Webpack is difficult and complex because it has to cater to literally thousands of tools (https://www.npmjs.com/search?q=webpack%20plugin). An individual project can choose to use a simple js-only bundler and a copy command for static assets.
There was nothing to release there, however - we just wrote the equivalent of a makefile. It was not a big engineering project at all.
Would I do the same thing today? No, because of code splitting and because there are simpler, faster bundlers out there already (esbuild).
> Will the improvements in devex really outweigh the engineering hour investment? IME the answer is almost always no, what usually happens is you get a half-baked, non-documented/tested system, and reading through this thread, I'm not sure any of the anti-framework people have shown convincing examples where they did better than an OTS framework.
This is, where I think we differ. I think much more often than not, we already have half-baked, poorly documented systems which we insist on trying to use, even if the team is quite capable of building something better. This is also one of the reasons we have JS fatigue - its not because the language or even the browser somehow prevents something better from being built, its because we keep insisting on using poorly designed tools or tools designed to solve problems that large companies have but we don't really have.
Well, business usually don't have that comfort of spending money on this when there is much cheaper alternative. Aaand they can hire experts in a framework instead of an engineer that would have to be learned the custom stuff and could eventually say that he doesn't like the stack and would build his own...
I'm not sure why you would describe the entire real world as "problem". Because this is how the real world works, with organizations where the last knowledgeable guy was fired two years ago and now discovers they need to touch that incredibly useful and huge application he wrote ten years ago. I'm aware there's an entire book industry telling how the ideal world should look like but there are also unicorns in every fantasy book yet nobody would judge you for not herding a couple.
It will always happen to a degree anyway. The more people are experts because of specifics to this company, the worse. Using a framework also improves hiring.
> If knowledge is on a single person alone, then your ex-company has bigger issues than framework or no framework.
You are both right and also describing every single company I've seen. I haven't worked in a straight up software company, though. Maybe they have things better.
Unless you're in a library driven ecosystem like Clojure in which case the majority of interesting code is just calling into a library
Yes you still have to know how it's glued together but at least there is still standardisation whilst still being flexible enough to swap individual libraries
Not a perfect solution but a good compromise in my experience
I started using a framework for a task at work, was immediately tripped up by an obvious stupid bug in the config files, reported it and it was closed because "too many people already depend on this behaviour". So now I've in-sourced other companies legacy and taken on a huge liability in depending on the evolution of undefined number of other organisations and their code bases.
And even worse when these frameworks are open source and don't even have any accountable people at all, and god knows how many people working professionally are suddenly held hostage by some dude who just felt like going backpacking in south america for 6 months without giving any notice to anyone.
Build everything in-house or be beholden to some dude going backpacking is a false dichotomy.
It'd be like saying I always make my own food from scratch — have you seen the state of the burger van down on the corner? You can't trust food made by others.
All frameworks aren't created equal — as with any tooling, you choose something based on the features of the framework but also the longevity, reputation and ecosystem built around it.
Thank you for this common sense reply. Can you imagine someone wanting to roll their own Flask? Their own React? It's like most people here seem to be siths and only deal in absolutes.
Yeah, but this has other trade-offs than the other two options of just using a 3rd party framework and inventing your own. Not saying that this is not viable though.
Then your architect needs a fresh course in how to decide what open source project to use.
When its a critical spot you first check how it is maintained. Its that easy.
Yeah but isn't this example just a trivial config bug? We're not talking about core functionality here. You're extrapolating from a minor nuisance to "a huge liability in depending on the evolution of undefined number of other organisations and their code bases" which is quite a leap. Just do config the way everyone else does; again it's not a differentiator.
Thinking about this case more, this is exactly what you want from frameworks: compatibility guarantees. Frameworks break compatibility, but deliberately and slowly. Will your in-house framework do that? Will it announce and well document its intent to deprecate functionality in favor of new features? Will it find all the users of it across your enterprise and work with them on migration strategies? Will it build in deprecation notices for literally years? Will it build in tests for the bridging changes? Django does all of this, for you, for free.
Speaking purely about web software / web APIs, most software is 90% CRUD. It absolutely makes sense to use a framework to save new hires from grokking 90% of it's capabilities. You can have a new developer do stuff right out of the gate.
This is one of my hobby horses! I'm disclaiming my bias upfront so I can try and have empathy for your position, but I strongly disagree with this line of thinking. I've been thinking a lot about this personally, and I think I would summarize my argument as "a lot of engineers think they're building beautiful, bespoke palaces, but in truth they're building regular houses, which is actually more important in the macro, but should be boring in the micro".
I broadly agree with GP here, but to round out some of their points:
- Frameworks take care of the parts of your application that aren't special. In the same way garbage collection isn't the value your company provides to customers, HTTP header parsing (or whatever) isn't either.
- Frameworks prevent your team from diving down architecture rabbit holes, or having to read a bunch of books on DDD, or what have you. This sounds like a small point, but if you tracked the number of expensive engineering hours spent disagreeing about where code should go, look like, and work, you would realize it's a pretty big one.
- Frameworks are tested way better than you ever could by thousands of users, actually documented, contain compatibility guarantees, and have security policies. To match this quality, your company would probably spend millions of dollars on eng hours. That's why company-specific frameworks don't match this quality.
- Frameworks make onboarding way easier. Most Python engineers know Django; most Ruby engineers know Rails. By definition, you can't hire engineers that already know your framework (even if you use something like Hexagonal, because no two implementations of this are alike). And again, because your in-house framework will be poorly tested/documented/etc., new hires will struggle. They'll also wonder if this is a career cul-de-sac: "I have 4 years of irrelevant experience in [bespoke framework X]" is not an enticing resume bullet.
> Your software is custom made for your organisation, it's not mass producing identical systems on an assembly line
This returns us to the palace vs. suburbs framing. The software you write is a super small percentage of the code that runs your app, all the way from firmware to CSS libraries. Good engineering is carefully deciding what code you will write yourself, because code isn't just implementation, it's design, buy-in, maintenance, documentation, and liability. Some enterprises are replacing a big chunk of that stack (Oxide or Cloudflare come to mind), but I bet 95% of companies are just building REST/GraphQL servers. That's not special enough to require a custom, in-house framework. You should just build the house the regular way.
You not only are in control, you HAVE to be in control. Nobody else will patch holes, optimise or deliver new interesting features. You're on hook for all of that.
Every time I see anti framework posts I am forced to frusteratedly chime in. This mentality makes me fume... not all of us work on massive teams where building stuff without a framework is even an option.
And even then, whats really a "framework"? You could argue it's even the language itself. Android apps used to be written in Java, and now they are pushing Kotlin way harder (and it may even be the default soon). Everyone who wrote those JavaScript apps back in the 1990s without TypeScript, are they still just as maintainable as their TypeScript counterparts? Such a shortsided and ignorant view IMO.
I think what bugs me the most is any sort of purist mentality (about anything) in software engineering. WE ARE ENGINEEERS. ENGINEERS USE THE RIGHT TOOL FOR THE RIGHT JOB! It should NEVER be "always use X", "never use Y". Both X and Y exist for a reason, so they are both useful for some reason.
And again, because I'm an engineer, I've also built my fair share of apps in just "purist" languages, the classic HTML / CSS / JavaScript, so I'm not against the purist approach either. Again, right tool for the right job.
I've tried to answer that in the article. Anything that I should have clarified even more?
Do note that I make an explicit distinction between libraries and frameworks. I'm not expecting a one-man-show to write the SSL libs or even the HTTP routing: there are perfect libs for that.
When this HTTP library lives on the side of your app, abstracted away behind e.g. ports&adapters there really isn't any issue. It could be Sinatra, Flask or such.
My article wasn't meant to argue against code-reuse, au contraire. It was meant to explain that there's "dangerous" code-reuse, and good code-reuse. That with the wrong re-use of existing code, you'll paint yourself in a corner that might easily prove impossible to get out of. Frameworks, I argue, are such code-reuse. Libraries, used and layed out in architectural patterns is, I argue, the alternative that allows for longer living projects.
I'll take advantage of the fact that you commented here to point out something unrelated that I found concerning in the article's reasoning:
"""
Companies that have..
A team that defines the standards, processes, practices, frameworks or architectures that other teams must follow.
...are amongst the lowest performers. Reversed: companies that lack this, amongst the high performers.
In other words: enforced standardising the tech, doesn't pay off.
This makes sense: if everyone in a company is forced to use, say, Django, for any project, regardless, there will be a lot of projects where Django is a very poor choice.
"""
I think that's not too far from presuming you should put armour where you find the most bullet holes in the planes that come back.
You have to keep in mind that an implicit trait of all of these companies is that they are still in business, despite having a "low" ranking for the evolution of their tech team. That speaks volumes about what it takes for their business to succeed, and apparently it isn't investing in a high quality technology team. Despite that, they've survived, and it's entirely possible that having "a team defining standards, processes, practices, frameworks or architectures that other teams must follow" is the trick that's staved off their otherwise higher propensity for existential disasters.
Of course, that's presuming there's any kind of causal relationship between having such a team and outcomes. In reality, the survey found that 16% of "low" companies had such a team, but 10% of mid and 7% of high companies also did. That's as compared to 15% of "low" companies that had a team that responds to tickets related to infrastructure issues, whereas only 6% of mid-level and 5% of high level issues... or the even bigger discriminant of a team that provides software delivery solutions for many feature teams through self-service APIs, which made up 3% of low teams, but 15% of mid-level teams and 23% of high-level teams. In that context, maybe having a team that defines standards & practices really is driven by factors that at best correlate somewhat with how evolved your tech team is.
...and I think one could argue much the same thing about frameworks, for much the same reason.
Realistically, having a team defining standards & practices doesn't actually play out as "if everyone in a company is forced to use, say, Django, for any project, regardless, there will be a lot of projects where Django is a very poor choice." The entire job of centralized teams like that is not to make everyone use one technology for everything, but rather to allow teams to operate independently while avoiding all the inefficiencies that come from teams using different tools that don't actually add much value but certainly subtract value. Take the case of choosing Django. If you don't need anything like Django, of course you shouldn't be using it. That's not what standards are intended for. What they are intended for is cases where using Django may be a perfectly fine tool for what your team is doing, BUT if you used Flask instead it really wouldn't matter that much. There might be a whole ton of other teams using Flask, a lot of tribal knowledge about how to operate it, and a ton of tooling that's already been integrated with it. While it might be better to use Django for your specific project (more often than not, that's not actually the case), in aggregate for the organization, it's way better if you just use the same technology as everyone else... and where things go organizationally overall in the long run is far worse, because with everyone using different technologies and no consideration for how they all interoperate together, you have no common fabric you can plug in to effect systemic change.
> What they are intended for is cases where using Django may be a perfectly fine tool for what your team is doing, BUT if you used Flask instead it really wouldn't matter that much
This is a good summary of my entire article, really. What I said is that on one axis, frameworks are a very bad trade-offs. There always are trade-offs. The axis being "maintainability".
That does not mean one should always avoid frameworks. Nor does it mean that without a framework, software magically turns maintainable. But it does mean that the benefits a framework bring, come at a cost. Make the tradeoff, weigh the cons and pros, and then decide if a framework, company-wide standardisation, team-knowledge etc. weigh up to the downsides of that framework. One of which being that it puts limitations on how well maintainable you can shape the software.
> But it does mean that the benefits a framework bring, come at a cost.
Except they don't really, right? Sure, there can be some negatives, but those negatives, are by and large coming anyway. If you had a rule that you don't use any outside tooling, that outcome is invariably far, far worse.
also typescript apps that haven't had active development in the last 10 years will be a pain to work with again. Toolchains need maintenance and upkeep.
The post is promoting building applications in a loosely coupled but highly cohesive manner. It mentions using libraries when appropriate and not duplicating code.
I agree with this but it requires a lead who's good at architecting such a codebase. That person also needs to stay with the company for a long time because they're essentially replacing the "framework" with bespoke human logic.
I think many, maybe most, companies that try to build loosely coupled and highly cohesive code bases end up failing and it ends up being a mess.
Frameworks aren't perfect. But know what's less perfect? Humans. The really big frameworks try and take the human component out and replace it with codified conventions.
> I think many, maybe most, companies that try to build loosely coupled and highly cohesive code bases end up failing and it ends up being a mess.
Companies who try to build any type of codebase end up with a mess. Always. No exception.
There is no reason to pretend software development's natural tendency to increase entropy is exclusive to a specific type of software architecture. In fact, some developers even go to the extent of criticising software architects for existing, because they have "rules" and enforce "order" and "organization".
If anything, being mindful of a specific architecture goes already a long way to fight entropy.
Every single codebase doing anything nontrivial is mess. Show me a code base that you can marvel at it's beauty, elegance, and how neat and tidy everything is organized and one of two things will be true about it.
1. It has never touched the real world, real hardware, or real users.
2. All the mess is hidden in some dependencies that handle the integration points with the outside world.
You cannot escape the fact that the world is full of sharp edge cases, no perfect abstraction exists, all models of the real world are approximate, there is no architecture that survives changes to business requirements, and all assumptions made about the environment where your code runs will eventually be false, which makes a mess out of code that was once nice and tidy.
I’ve worked on a lot of open source projects and large proprietary code bases that I’d call not-a-mess. I’m not sure what that means to you, to me it means well-engineered in terms of quality criteria, rather than aesthetics, as it seems to be the case for many.
You sound very defeatist to me. I’m under the impression you’ve only worked in teams that don’t have an engineering mindset but rather throw-shit-at-the-wall-and-see-what-sticks coding sweatshops. You may want to look for a new company to regain your pride in your work..
I first thought to post some links to code bases that, in my eyes, aptly counter argue your claim.
Then I realised that you have already solidly placed yourself in a corner and are bound to defend that corner no matter what I am going to post. Since there's no objective measure of what constitutes as a mess (in contrast to what is simply not perfect) it's also easy to convince yourself that the statement always remains true.
Probably in a small close-nit team working on something for no more than a year or two that will be impossible to maintain once the authors move on to greener pastures.
I actually got to a point where I don't mind my own code. Even code I wrote years ago feels natural to me when I revisit it.
And about the switching teams part. I much rather take over code that is written for our specific use cases than trying to wrap my head around some huge generic framework.
But this is the point... You don't have to "wrap my head around some huge generic framework" for every project. If you choose the right framework, it's already used in teams, projects and businesses across the world, so hiring and upskilling are far far easier than they would for a custom framework.
Until something is broken, and you need to step through 40 levels of stack (certainly no exaggeration) to try to figure out where something is happening, and where that exception is swallowed. Most often it's not the framework that is broken, but you still need to understand enough of the framework to figure out what is wrong where.
Which again is the whole point. I could care less if the auto-generated SQL isn't 100% efficient, as long as it's not getting in my way and I don't have to think about it when I do
User.add({})
I think you need to better examine what you consider critical and maybe try to further break down the word critical for a better understanding of where to focus your time and energy while coding.
I would like to propose that if your organization has trouble making root cause analysis into usefully actionable information, that their codebase is also a mess. Because at the end of the day I think the same skills at looking at the interface of human and process are required for successful decomposition of logic to soften the interface between human and technology.
I love these technical topics because I can open up popcorn bag and read how people with statistical significance of 1 person experience throw their opinions and claim they have it all figured out.
In my 14-15 years of experience in software industry I learned that having framework helps mostly with that - having bunch of "know it alls" rounded up to use the same approach instead of having "I know better discussions".
Where frameworks shine is specifically lowering amount of discussions on technical details that has no relevance to the business but has all kind of opinions from devs.
Someone in the thread claims - if he is hired he has to learn framework - well I am hiring people with knowledge on framework we use, he might not have been looking for a job lately. I have not seen we hire c# or c or java dev - there is always framework in requirements. Just see how frontend devs ads look "react dev to hire"/"angular dev to hire" no one hires "someone who knows html and css", yes it is requirement to know these but you also have to know at least one framework.
Architectural patterns and design patterns can just as well help against "bikeshedding".
More than a framework. I avoided this topic in my article because it already is far too long :). But a framework such as Angular or Rails does three things here, all of which aren't really properties of the framework:
1. Dictate where to put files, and how to name stuff.
2. Dictate what architectural pattern you must use. Rails? MVC or GTFO.
3. Dictate what surrounding tech to use. RDBS, REST, template languages etc: you don't have a say, use them, or GTFO.
First, I don't think this is good, not because I know better, but because use-cases demand different setups. Sometimes Event-sourcing is crucial to a domain. Sometimes message-bus, sometimes microservices, sometimes monolyth. It really depends. Having the freedom to choose the best constraints and trade-offs for a project is IMO a crucial skill for long-term success.
But even if such bikeshedding is bad and "we use Rails for everything, from websites to bots to embedded software" is the proper thing. Nothing in those thre points come from a framework directly:
1. where to put what, how to name things? - ubiquitous language, a thesaurus a simple loader or even the language (rust "enforces" file naming conventions as a language). It's a good thing to have, but can be achieved without marrying to a framework with all its trade-offs.
2. What architecture to use? This should be the first thing. Maybe second is to then choose a framework that uses or allows this pattern. Not the other way around. So you'll need to do this anyway: frameworks or not.
3. Again, highly dependent on the use-case. The requirements should dictate the tech to be used, not the other way around. And the tech used then dictates whether a certain framework is feasible at all.
"Frameworks are designed to take your project hostage" Wow, that is some enterprise level FUD, and with zero citations to back up that assertion.
While one could possibly see 3rd party external dependencies pose a variable cost, service risk, or security issue... a standalone/maintainable site should not have 25 domains for every lame js widget a designer thought looked cool.
If library is deprecated. You replace the library.
If framework is deprecated. You give up the project or rewrite 'everything' to use another framework because essentially your project is build on it.
That's the difference.
If you make abstract to make it suitable to port to another framework. Then you are writing yet another framework on the top of a framework. In my opinion, it's even worse.
If framework is deprecated. You give up the project or rewrite 'everything' to use another framework because essentially your project is build on it.
Or you just carry on using the deprecated version. It doesn't stop working.
If your team is sufficiently skilled you fork the framework and carry on developing it yourself.
There's lots of options other than just giving up.
Besides, how often is a framework deprecated? It hardly ever happens. This line of reasoning is the same as the old "We'd better use a database abstraction just in case we change database!", something that no one has ever done in the history of IT projects (this is hyperbole on my part, but it's pretty much true.)
Yeah but that sucks though. Imagine being a large company with a multi-million dollar annual spend that could be entirely free if only Postgres had been a bit more mature back when you started.
So many of the decisions you make when needing to move quickly at the start of your growth curve, are the ones that slowly kill you after market saturation.
That's not true though. The answer isn't to use a database abstraction, but to architect your software to make changes straightforward. If you design your code properly (push database queries through a standard set of APIs that are reused everywhere, put queries in their own functions or classes, never put queries in components, etc) then moving to a different database is a relatively simple matter of updating your DB layer. A database abstraction makes people think "I can change my database just by changing the db adapter, so why think about my DB code at all!" That is the problem.
You don't need a wrapper that understands the APIs for different databases when you're only using one database. What you need is to think about how you write your code.
Exactly. It seemed to me as if the author originally thought with a framework they don't ever have to think about the architecture, but of course it's still possible to shoot yourself in the foot and end up with a tangled unrefactorable mess. The article channels misplaced disappointment.
Give it some thought and properly encapsulate your core business logic and you won't have that much trouble migrating to another framework or a custom solution if need be (especially easy if your current framework has good documentation, which Django definitely does).
In my experience, I lack the talent for truly graphic swearing that would be required to adequately communicate just how much worse it is. Wrapping frameworks is like throwing water on a grease fire. Or maybe like someone else throwing water on the grease fire while you're standing inside the splash radius.
The only way to win is not to play, but the best way to minimize the damage if you can't avoid it entirely is this: escape out of the framework code into 'normal' code as fast as possible. The framework only calls glue code. All of your real logic and investment is in code that uses Plain Old <Language> data structures and that's it. That'll keep you sane.
It also is a great way to pop out bits of your logic into separate little programs where you can do things like write utilities that let you reason about the bigger system in bite sized chunks, or even to use benchmarking tools to do A/B testing of different implementation details of one subsystem, without the noise of the rest of the system getting in the way.
On this line of development a customer of mine has a lot of small/medium Rails applications with very little in models and controllers and almost all of it in service and command classes. They use commands for code that does only one big complicated thing and services for bags of simple methods about one resource.
They end up with code like
class Command
def initialize(a)
@a = a
end
def run
s = Service.new(@a)
s.do_something
s.do_something_else
end
end
Command.new("a").run
which is funny when I think that in Elixir I would write Command.run("a") and there isn't a good reason for using OO in this case, except that Ruby is very object oriented. Anyway, their code is quite separated from Rails except for the calls to ActiveRecord, but that could be ActiveRecord without Rails.
Probably a different problem domain, but I like simple BSON message objects over AMQP into rabbitMQ to enforce a producer/consumer linear job queue from a distributed platform... where transactional ordering can on occasion be more important than the latency hit.
Most OTP projects can benefit from a RabbitMQ/kafka message channel, as some jobs may end up visiting several languages, CPU and GPU architectures. =)
You can affect this by picking the framework properly.
The chances of Spring Framework, React or .Net being deprecated are zero to none. Even if they are sunset, there will be a) years of warning b) a cottage industry of open-source options.
Or you can hamper your project by abstracting EVERYTHING in your software to be 100% free to switch any library or framework at a moment's notice with minimal work. In essence building a meta-framework yourself :)
Silverlight was around for 12 years (9/2007 - 1/2019). Not exactly a shooting star.
It was technically better than Flash in every way, but the Internet was in its "Micro$oft bad!" -mode at the time and shunned everything they made. They also took a bit too long to provide proper clients for OS X and Linux.
If I recall it was mostly the DRM and codec-licensing that strangled most projects.
Silverlight itself was actually relatively good at the time, but HTML5 media tag standardization made it along with Real-player, QuickTime, and Flash effectively obsolete for their primary use-cases.
Or, as TFA suggests, you separate your concerns with a framework just as you'd hopefully do with other elements of software development. While TFA starts out with strong language against frameworks (as defined in TFA), the conclusion is pretty sound, IMO.
One of my goals this winter is to clear my head of as much OOP dogma as I comfortably can, fill it with as much DevEx thinking as possible, and read Christopher Alexander, A Pattern Language, from that frame of reference.
My very hot take is that we will start referring to everyone who bought first editions of the Design Patterns book as the Lost Generation, because we have completely misinterpreted Alexander's work, as it could apply to software.
I usually recommend "Designing Elixir Systems with OTP: Write Highly Scalable, Self-Healing Software with Layers" (2019 James Edward Gray, II, Bruce A. Tate)
One may also find it interesting how Elixir/Phoenix-framework uses the OTP to greatly simplify implementation. =)
I think the missed or perhaps unspoken observation in this thread is that if the language provides it, and you're using it, you're tying yourself to the language, which tends to last a lot longer than frameworks.
Switching languages obviously requires a rewrite. But you aren't also rewriting the framework integration too. Some languages have work-alike frameworks, but they aren't ever exactly the same behavior and semantics. There are always subtle but important differences.
A clean pattern does not emerge naturally with a polyglot stack, as multiple languages with many library dependencies only lead to maintenance issues, duplicated code, and kludges.
I guess my point was that while it is sometimes necessary to pipe messages though multiple languages & platforms under special circumstances (see BSON over AMQP post above alluding to decomposing multiple hardware-dependent programs/codecs into a standardized cluster API.) In general, it is cleaner to have a simple distributed framework that hides the fact it is _not_ a monolith from _most_ developers.
We can agree to disagree on this matter, as everyone's use-case differs. =)
I’ve read the original and was underwhelmed from a software epiphany standpoint. Design patterns are just names for deliberate design decisions, so you can communicate them to others who can then deliberately make those decisions themselves. Half the industry still seems to think the GoF book is about C++ not having first class functions.
The problem is that they are milquetoast. They are “design decisions” in the same way that white space is technically code style but really distracts from the real elements of style like structure and meaning (don’t create three meanings for the same word, for example).
Architecture is much bigger than making sure the doors open the correct direction.
Well, there are many collections of patterns, GoF doesn't claim to be exhaustive. Enterprise Integration Patterns is more high level, for example. But for everyone who hand waves away something like the Strategy pattern as trivial, I have to work with a dozen libraries which accept a massive dictionary of static options to configure their behaviour instead of allowing me to choose an arbitrary, dynamic policy at runtime. I don't think that's a conscious design decision on behalf of most API developers. I suspect it's because the industry largely received the original GoF book as a bunch of cut and pasteable code and later rejected it as symptomatic of Java-esque OO excess. We could instead have received it as a network of signposts telling us what's possible, when and why. Not earth-shattering stuff (neither is Christopher Alexander's original) but useful nonetheless.
I think, wrapping an api or a few methods is okay. But wrapping a whole platform/framework is just wtf.
I had seen someone decided to wrap a simple pixi.js project with a whole mvp framework and tons of command / facade / proxy patterns to make it like a oop program. So I hate it.
I heard it's wrote by a c# guy picked up for the project because no one had time to do so I could probably understand why. But, damn. It's so painful to read.
You don't need a framework. You can control execution and use libraries. Once you use a framework changing back is hard. Removing a library on the other hand is easy. Because for libraries you control execution, and for frameworks you have to fuck your code so it will obey the requirements of that framework.
With framework maintainers providing paid support, extending services or an ecosystem with commercial components it somewhat makes sense even if not outright obvious or intentional.
I think using a framework can help with the maintenance of the software.
Let me use the one that is usually used as a negative example in hacker circles: Spring.
Spring has a steep learning curve. Spring feels like too much magic. Spring makes simple things look complicated and hard to understand. Spring is large.
On the other hand: I don't care about making extremely simple things more complicated. In the enterprise world / large-scale SaaS development, we don't do extremely simple things. If we wanted to have a service that adds to two integers and returns the result, then it must have unit testing, integration testing, end-to-end testing lifecycle management, documentation, health checks, clusterability.
Why? Because we want to make our own lives easier by having ground rules for services and code, and anyone who starts maintaining, improving or operating a service knows that they can expect the stuff mentioned earlier.
So Spring gives us these out of the box. People learn it once, and then whenever they start to work on something new, they get Prometheus metrics, testability, proper logging, etc. right off the bat.
I find Spring (and other frameworks) annoying and boring as a hacker, and I find them very useful as a CTO when a large team is working on system and people come and go over years or decades.
exactly. and of course it's not impossible to identify the good things in Spring, then look for a different framework that has those but has less of the bad ones. Dropwizard was looking good a few years ago.
The entire article uses some very odd grammatical conventions. The author is from the Netherlands, which I think might account for some of the oddness, but I can't tell if the capitalization is because of that or just because of the desire to be quirky.
One reading which might be valid is that testing on hardware that lives in the happy path will lead you to think your code has less issues than it actually has on real user systems.
Every year I have 2/3 internship students. This year I put them on this framework as a baseline, compared to the previous years where the students would have to do things more manually through libraries. They all got at least 5 times as much done as the students of the previous years in the same 3-4 months span of time.
On contrary. Not using frameworks (when you have need for them) actually means you build 60% of framework your self, and then you have to maintain your app and your framework. Which is waste of time and resources.
In my experience as freelance developer the worst project I could possibly get is from people who invent their own "frameworks" (they just call it "lib") because they thought they were smart avoiding frameworks like next.js, laravel or springboot. It is a mess to maintain and to implement anything new on that codebase.
Complaining that framework wont support you forever because you were too lazy to maintain the software incrementally, is like complaining why php 1.0 or why windows 98 is not supported anymore. It simply doesn't make any sense.
My advice was always focus on your product, on your app, use as little dependencies as you can, but do not waste time on things that are solved already. Don't write your own framework to avoid using some other more mature and better maintained framework or lib. Sure you do not need library dependency which will tell you is something boolean or not, but if you need to add router to your app, use the lib.
Well said. I've had to suffer those frameworks somebody thought they could do better without them, and it was a disaster. Nobody other than the person that wrote it was happy about it.
Not really. Those bad ones look for outside help when people who maintained all that leave and they don't find in-house devs quickly. Projects that use frameworks tend to maintain opinionated structure that frameworks usually push. Which helps onboarding. Not always, but mostly. And it's always easier to fix and maintain the mess I see for example in a Laravel project, than in built-all-alone project.
I'll rephrase: my suspicion is that there's a survivorship bias here. No-framework setups with poor architecture cause people to leave more often, while no-framework setups that work out are a pleasure to work with.
> Many people will argue that not using a framework means write everything yourself. This is a false dichotomy. We can use libraries and frameworks just fine. ...
> But we should give them a clear, and well-isolated place in our project. ...
There's an excellent, if older, presentation called "Architecture, the Lost Years" that addresses exactly this problem and gives very specific, actionable guidance on how to solve it:
But how to pull off this decoupling? The answer is both obvious and surprising. Define a boundary. On one side is the framework. On the other side is your code. Through the boundary, only dumb data structure can pass. JSON works. So do structs. So does XML. The point is that these are behaviorless blobs of data.
This buys you a lot. You can run your application completely detached from the network, a database, and other expensive dependencies. So testing becomes much simpler and easier. And of course, you can replace the framework by writing new boundary code.
The other big lesson has something to do with why frameworks get added to a project in the first place. When designing a system, the goal should be to defer major decisions for a long as possible. That's when the best information is available. Sometimes you can just defer until the point becomes moot, which is a major win.
Reaching for a framework before being forced to do so sets up the kind of situation the author is talking about.
Isn't the problem here that your decouple framework requires data X,Y, and Z in the message across the boundary, so you plumb that data through right near boundary where the request is made. But later on, you want to switch out a different framework, but that framework requires U, V, W, X, f(y), and Z. So even on your apps side of the boundary layer, you still formatted your code and data flow to support the single framework you started with.
If your message contains framework-dependent data, it wasn’t decoupled.
For example, in a typical web API, all the stuff concerning HTTP endpoints, JSON, OpenID Connect or whatever should be entirely separate from your domain logic. I’ve been doing this for years and it is very feasible.
Do you still have to write code where the framework dictates its structure? Absolutely. That’s the decoupling layer. Do you have to change this layer if you upgrade or switch frameworks? Also yes. However, you don’t have to touch the application core.
I too have been doing the same. It's surprisingly simple and elegant. I prefer 'ports and adapters, aka hexagonal architecture', but there are many alternatives.
This is what prompted me to write this article: the simplicity, elegance and maintainability of those codebases that had domain logic separated from delivery and storage mechanisms.
*Is really the accurate summation of the article. And yes, this is well known. Every article about a company upgrading Rails is "it took us several years and only three people died." And we know better than to use MVC nowadays.
No offense to Rubyists, but in the Ruby ecosystem, I have seen a disturbing lack of absorbing information from other programming ecosystems. This article smells like that to me. If you've only used Ruby and Rails, you might not realize some of the dangers and inherent limitations of the design unless you've worked in other ecosystems.
It's been a whilst since we've had one of these on HN. What a bit of fun.
My 2c. There's a choice about the work you do. does your work satisfy a business requirement, or does it satisfy your ego.
I need a site for work for a 3 year project, CRUD, users, auth, sessions. Django's perfect for my team of 1.5. It wouldn't be responsible to roll my own, when I can have the bare bones of that site up and ready to go within a day.
This is like complaining that X company is locked in because of a chipset, and suggesting they branch out into lithography to ease that burden.
Is your core business getting things done, or is it flexing by rolling your own framework.
I did some Django but in the days, and I completely agree that as long as you have CRUD, Django shines. The issue starts when you cannot really fit your uses cases into simple CRUD and you start to fight against the framework to achieve this.
The author also made a point of negligible gains - even if you spend a week to setup auth, sessions etc. if still negligible for longer running projects
I've worked on to many long dead projects with scant doco and the best ones are always where people colored inside the lines. Remember google web toolkit? That flamed out hard 15? years ago.
I've recently had to make a mod to a decaying app written in GWT. It was easy because no one got creative. I think theres a long term risk with rolling you're own that you box yourself into a lot of corners without knowing it.
You can also get really creative with frameworks, specially if you need to quickly overcome some strange limitations imposed by framework. There is also a long term risk with using frameworks - somebody here mentioned method renames in Laravel, that makes upgrading difficult.
Im not talking about writing your own http server, or building the whole database access library. You can use some ready made libraries. As long as you keep proper boundaries between IO and business logic, you can fairly easy change the IO libraries.
Of course there is quite some overhead there, and for some projects it makes not sense.
It seems that there are mostly 2 types of devs:
- those that use tools, learn them and master in them,
- those that always want to create their own tools, and will usually oppose adopting and learning existing ones.
I belong to the first type. I love frameworks because they give publicly available documentation that plenty of people contribute to - so my project will have access to all of it even if I'm gone. Another reason is that frameworks have opportunity to be battle tested in terms of robustness and in terms of use cases. My stance here is that I love to use wheels instead of creating my own ones. I'm a project developer and not an academia developer.
The second type of devs are what I would avoid hiring to my projects if they wouldn't be an academia projects. I need to deliver business goals in a most efficient way. That efficiency has to be on multiple levels. One these levels is to that the code won't be depending on one or two my best developers, because there is a high chance they will go at some point. My project would then rely only on what they created and documented, hoping that documentation cover everything. But my project would also slowly deteriorate technically, because most devoted contributors would be gone. Frameworks usually take much longer to become abandoned.
I believe first type should work for businesses. The second type - should aim academia.
There is a third type: those of us that work with frameworks and build our own with libraries when needed. The right tool for the job essentially. The "right" framework is absolutely a net benefit, even in academia, but it can be very hard to pick the right one. Sometimes none of the available framework options are "right" either. The downsides of picking the wrong framework for a project are massive and worse than custom code in my experience. I rarely hear pro-framework-only people talk about the downsides, and I always wonder how experienced they are. Have they never seen a project go sideways by picking the wrong framework?
I'd propose a different dichotomy: those that have good experience using and developing complex systems, and those that don't. The former are more likely to fit with your dichotomy, while the latter are more likely to do what's best for their project.
Though nobody can predict the future and what seems like the right choice initially might not be later on.
I belong to the second type. I believe it's a great asset to have in business. Most often less code means shorter development time and cheaper maintenance.
People knowing a framework will often use it for everything. Instead looking at the problem and find the easiest solution to it offers great time to marked.
I've proudly deleted more code than I've written at work.
> Instead looking at the problem and find the easiest solution to it offers great time to marked.
The easiest solution you can imagine. These are 90% of the time cute tricks that narrow down the scope of the solution so far it makes the surrounding code unmaintainable after a year.
I learned to call those people "Ricks" they are best used in walled of projects that are not expected to change. Not useable in cooperation.
Agree on the importance of deleting code, but with "less code means shorter development time and cheaper maintenance", I don't think I've ever seen a program without a framework use "less code" than it would using one.
1. "If you don't use a framework, you will end up creating one" -- And that's exactly how successful frameworks were born. If everyone uses an existing framework, who is to create better frameworks for the future?
2. Framework vs. Library -- Framework calls your code; Library is called by your code. There is clear inversion of control. The article touched on this, but I think it's a very important distinction to call out.
3. Framework makes me think inheritance. Library makes me think composition.
4. Framework is like CPUs. A more powerful CPU is a more powerful CPU, no doubt; but you need more power to bring out the performance. If your company don't have the resource to deal with the maintenance, Framework becomes a liability rather than asset. But if you can sustain it, it should still be a net positive.
5. In addition to the mixing of domain and non-domain concerns, poor Framework bring incomplete abstraction that expands the surface area for reasoning/debugging/maintaining. A good framework should provide the perfect abstraction that frees the developer from having to descend the stacks. I consider programming languages as good "frameworks". So are the layered networking architecture.
6. Watch out for self-fulfilling prophecies. e.g. in the web frontend framework space, a framework might claim it helps solve problem X, but it might also be very cause problem X. Accessibility, Routing, State Management... a lot of these can be solved by using the platform. Before you reach out for a framework, be sure to assess platform capabilities and single purpose libraries first.
7. Reliance on framework can be caused by lack of knowledge. If you are a manager, give your team the time, money, and endorsement they need to learn things, attend conferences, and provide ample budget for training and technical book purchase. They might pay more dividends than a framework does.
I'm experiencing this with Laravel. I'm stuck on 5.2 while they're on v9 now because the author thought it would be a good idea to arbitrarily change some method signatures because he regretted his decisions earlier, while not providing any additional value and I don't have the time to hunt all these down and refactor everything, and I feel unmotivated when he's made it clear he's a bad steward. He refused semver for the longest time, not sure if they're using it now but even if so, 4 more major breaks is not encouraging
That’s Laravel in a nutshell. I tried it for a year, then got fed up with all the useless name changes or directory layout changes after every “minor” (yeah, no SemVer) and moved to Symfony with their LTS promise. Still happy with that decision.
I will be astonished if that works, especially with all the nonstandard junk I've done to my codebase, but I will give it a whirl. Thank you, didn't know about this.
I did see a paid version of something similar before but never tried it.
I don't have the time to hunt all these down and refactor everything
Yes you do. You're just choosing to spend that time on other things rather than pay off some of the technical debt (that the framework introduced rather than you). Your decision to just live with the old version will prove to be a bad one in the long term: you'll find it frustrating, your skills will stagnate, new hires will find it frustrating (and will quit), eventually 5.2 will stop receiving patches so your security will be compromised, and you'll miss out on some of the shiny new features in the latest versions. This will get harder the longer you leave it.
It's worth investing the time to move with the framework even if the framework is a pain at times.
Before you comment with "So you want us to write everything ourselves?", make sure you read the paragraph that starts with "Many people will argue that not using a framework means write everything yourself. This is a false dichotomy."
I feel like this response is common enough that it's almost a trope.
"Oh you don't like leaky abstraction X, so what we should all code in binary!?"
I think it comes from a kind of "Just World" spin off whereby all abstractions are considered pretty much equal, and it's cavalier to not code to the "highest" of these, no matter how many rickety chairs you've piled on top of each other to get that high.
Not all abstractions are created equal. As an example, choosing to use vanilla JS over react is not the same as hand-coding assembly instead of using C, Zig or Rust.
I'd go so far as to extend the statistics aphorism about models to software abstractions: all abstractions are wrong (/leaky?), but some are useful for now.
The problem with software abstractions is that they, unlike the fundamental laws of physics, model code organization and business logic that frequently changes. These changes often make no sense beyond "VP lifer thought it was a good idea" so our house of cards is built on ever shifting sands. No abstraction short of a pointer can survive that.
No I get that all abstractions leak on some level. But some leak a lot more than others. And as an industry we don't seem to have good mental models or languages around that.
More than once I've seen using the abstraction + working around the leaks being more complex than just using the the thing underneath the abstraction.
I have no pithy phrase to describe that scenario, without the "why don't we just code in binary" retort.
If your argument is that using someone else’s abstractions is bad because you can write your own (which is what this article is saying), then the standard cliched reply is accurate. Cliches are cliches for a reason.
Indeed. This excerpt from that paragraph is a good thesis for the essay as a whole:
> The point is not to never use frameworks, but to isolate them. To call them from a single place. One that we own. That we are responsible for and that we limit very much in what it can touch.
> > The point is not to never use frameworks, but to isolate them. To call them from a single place. One that we own. That we are responsible for and that we limit very much in what it can touch.
I had the misfortune of working on a project which abstracted a framework. It was awful. It ended up being an ad-hoc component that was half-façade, half-adapter that was inadvertently tightly-coupled with the framework. It added an awful lot of complexity with the only tradeoff being theoretically being able to abstract away the underlying framework.
It was not worth it. It created far more problems than those that it solved.
I think an easy example of that is what frustrates me the most in JS-land: everything has it's own CLI. Why? Quick start: `npm run nouveau-framework create@app 365 --with-voodoo`.
I don't want that. I want (maybe, at my discretion!) to add your framework as a dependency, read some API docs, and just start plugging it in where necessary.
But they all focus on greenfield projects, they all think the whole project is about/driven by them.
This does frustrate! On more than one occasion I've spun up a create-x-app project just to see what an implementation looks like to then do it manually inside an existing project.
Then again when I'm greenfielding having the option to be up and running in 2 minutes is rather nice.
He likes to generalize the kinds of problems he has with Rails and Rails-like frameworks to all frameworks. This seems impertinent, since Rails-style frameworks are a particular style/flavor of framework, those of which I'm sure experience the problems he describes, but more generally? I'm not so sure about that.
The author started their post by defining what they mean by "framework" and it's pretty clear that your snark "do you have to write the HTTP server yourself" is way off from that definition.
Also, if you don't have any experience with framework-free web applications - to the point where you can't imagine how one might exist - perhaps it would be a good idea to familiarize yourself with one? Yes, they exist. I've written several.
I don't accept the distinction between frameworks and libraries. Once past the most trivial stages, any codebase uses frameworks, often multiple of them. But they aren't all published or named as such. Often you create them yourself. I have myself written lots of things that work like a framework. Inversion of control is a powerful pattern.
There really is no clear cut difference between a library and a framework. All depends on the mental model what you call what.
For a discussion that began with a clear definition of "what is a framework", you sure are spending a lot of effort muddying the waters. I for one strongly disagree with you on the idea that coders "accidentally" create frameworks, just like one might accidentally slip on a banana peel. I have written several codebases that have NOTHING resembling a framework in them.
Developers use frameworks because frameworks that are used by many others take care of edge cases that most engineers have no chance of fixing, or even discovering, on their own.
Web framework code is typically riddled with comments like "this extra margin is added to the input to work around a bug in Internet Explorer 11 where Tibetan characters are cut off".
Good luck solving such issues without having tens of thousands of eyes and hundreds of hands to help you.
From my own experience, writing something without a framework often seems very elegant to yourself, but the moment you try to onboard other people to your framework-less code it becomes a nightmare. Turns out most folks don't want to get familiar with e.g. intrinsics of browser technologies, HTTP request processing or other complex things that you've reimplemented in your code, they just want to deliver working software using frameworks and conventions they know.
You can think of frameworks like conventions: If enough people know them, it makes life so much easier for everyone, even though the convention might not always be the best fit. To state an analogy, imagine each municipality would invent their own traffic signs from first principles - because it makes maintenance easier for them - and you were tasked to drive through such a city with large speed, learning the conventions as you go. An absolute nightmare. I think that's how most programmers feel about code that brings its own framework-less abstractions and technologies.
So while I would've been able to write my own frameworks I've become humble and reasonable enough to just default to something that's popular and well-known, because it will make life easier for my colleagues or employees.
> Many frameworks aren't as extreme as Rails with its public interface of over 1200 methods. But all offer an API, functions, classes, to be used by the user of the framework: it's the whole point of the framework to offer this!
Some frameworks make the effort to make a clear distinction between which methods you can extend, which you can call, and which are framework-internal. The only one I've seen that really did this properly is Wicket, but it absolutely does work: you can fearlessly upgrade even a major version. (Of course the cost is you sometimes find yourself cursing because the method you wanted to override is final, so instead you have to copy-paste it and accept the maintenance burden belongs to you now - but you're doing so explicitly in that case).
> The more isolation, the better maintainable. The code that handles e.g. token authentication should not be written by us, but be included in a single, well contained, bounded area. One that encapsulates this and translates it into domain language, preferably. E.g. behind a authentication.is_known_as_admin(request.token) rather than sprinkled throughout our controllers, commandline-interfaces, scripts, or async jobs.
This sounds superficially like good advice, but it's practically impossible in a language without monads, and often ends up as the "inner-platform effect" - sure, you've put a wrapper around the library, but reimplementing your wrapper to switch out that library is no easier than reimplementing your first library's API directly on second library. In my experience you're better off YOLOing it most of the time. If you ever do need to remove or replace a dependency, you can do the work then rather than front-loading it, and it's actually pretty easy - delete the dependency, fix the compilation errors, and you're done.
This is like saying game engines can be clunky and get in your way (absolutely true), therefore you should just glue a bunch of libraries together.
In practice, that almost never works out well. You want to carefully pick the right tools for the job, but those tools will be enormously helpful when dealing with any kind of complex task, even if you can recite a litany of annoyances.
Of course if you don't have a complex task at hand, go nuts, find a sleek solution that truly fits your needs.
From the author’s About page: “I mostly work with Ruby on Rails. A professional, Open Source platform which powers enormous (e.g. Twitter.com) and tiny applications.”
Done Rails my entire career. It scales more than you think if you’re willing to throw some hardware at it and avoid turning your controllers and models into logic layer soup.
What kills scaling is inexperienced developers doing what I just mentioned. Also, ActiveRecord is not your friend at scale. It’s wonderful in small amounts, but callbacks and memory overhead will kill you. You really need to learn SQL to avoid doing select * on seven tables.
Also, view partials. The lookup cost on those is pretty high.
Off the top of my head, I think Github and Gitlab are both based on Rails, as well as Shopify and Airbnb. So there are for sure some very large companies that use Rails successfully at scale. I can't speak to how difficult it was to develop or deploy, and it seems like Ruby as a whole has lost some popularity, but Rails has worked and continues to work for a lot of organizations.
It seems like a herculean effort to make it work from what I have seen at GitLab. Which includes having the majority of the site not in rails but Go microservices.
Personally I find that Ruby is more the problem than Rails. Having an untyped language makes things extremely difficult to work with as the app grows. Gem updates are very difficult to do safely.
We wouldn't need bloated convoluted web & JavaScript frameworks if we had a state-ful GUI markup standard. Then any language that can emit and read XML can use the GUI kit/browser/component, no binders needed. At least in the domain of custom business and administrative CRUD, the end users really want a web-enabled GUI application, as most work is still done on desktops. ("Desktop first" works better for typical biz than "mobile first".)
Somebody criticized the idea saying that one would end up writing their own wrappers for such a language, but that's not a problem: one would customize a sub-interface for their own shop's needs and conventions. That's not a bad thing. But if we had a decent state-ful GUI markup standard, such wrappers would be lite, more about managing domain patterns & defaults than reinventing a GUI engine and common GUI widgets from scratch.
The article tries to generalize but I think it's a bad idea since not all frameworks are equal. Back in 2005 (and to this day), I made websites with Django and it was relatively easy to maintain and upgrade them to follow the framework. I can't say the same thing about websites I made using the Zend Framework (now Laminas).
The wrong framework will harm the maintenance of your software. The right framework will keep it going for decades.
Of course it's not always obvious how a framework will evolve over time (let alone the requirements of your website/app/api), so the safe bet is to stick with the ones that already stood the the test of time.
I still think about that suite, because it had a certain kind of elegance: Everything was frame, and therefore text documents and spreadsheets were frames, and you could embed a frame in a document, which correctly implies you could put a spreadsheet in a text document.
But the cells in a spreadsheet were frames, and therefore you could make a hierarchal spreadsheet, or put a text document in a spreadsheet's cells, and so on.
It had a "frames all the way down" philosophy that appealed to me, although the implementation was hobbled by the (to us) obvious limitations of the technology of its time.
From the wikipedia link:
The spreadsheet program was superior in its day, offering true 3D capability, where spreadsheets could form an outline which can be "opened" to reveal a separate spreadsheet, as well as other frame types — a feat of sheer convenient function never again seen and further enhanced in later versions.
Framework's built-in interpreter, the FRED (Frame Editor) computer language, was based on Lisp eval function. It can reference all frames and types across the product and can sense and perform all user interface operations.
Thanks for this! I grew up writing school papers in Framework IV on a PC-clone 386. I still miss Framework from time to time, small wonder I became an Emacs user!
I'm glad I started my professional career working on a large Django app, I think learning about its abstractions and organization gave me a really good starting point in building my mental model of all the problems sufficiently complex web applications end up having to solve. Now I often find I prefer, or am in a situation where the companies architecture dictates writing projects and services with much simpler dependency graphs, I've also found the prospect of deploying web applications with python a lot less appealing, but there are many reasons the opinionated all-in frameworks like Django and Rails were and are awesome.
Maintainability is how long it takes you to solve a problem. If the reliability of the framework exceeds that of code you could write then we're limiting the overall scope that must be maintained to begin with. Now on to what issues look like with frameworks, if you use the framework as designed, the code should follow convention - convention improves maintainability. If your framework can't do what's asked, it's been misapplied and another tool is needed. Using a tool improperly is terrible for maintenance
This pretty much sums it up. Narrowing the scope of maintenance is a big deal. Once I'm confident in the quality of a framework, the next question is how likely and how often am I going to need to use escape hatches for this project now and in the medium term. If I expect too many (or too difficult) escape hatches, it's the wrong tool. If I can't find a framework that I'm reasonably confident in that way, only then would I go without. If so, whatever I come up with is by default a framework. It's just probably not going to be as good as an open source one.
I didn't read the whole article, but I agree in principle.
My rule of thumb is:
* Prefer code vs a library if what I want to do is simple and/or if the complexity of the library overshadows whatever benefit I get from using it.
* Prefer a library vs a framework if the library provides what I need.
A couple of examples when using:
* The use of the Spring Framework in the Java world to do DI, web apps and many other things. I think java is the only language where a framework has such a bad influence on developers (maybe Ruby and Rails follows it, after all Spring tried hard to copy Rails ease of use). In this example the framework makes a few things easier, by ading a metric ton of complexity.
* The npm left-pad library (debacle).
This doesn't mean that one shouldn't use libraries or frameworks, just that they need to be justified. Development is boring and most developers just see shiny stuff and have to use it in production just to get some entretainment.
Disclaimer: I'm a DevOps, not a developer, but enjoy writting software side projects at home where I am free to chose whatever I want and don't suffer from real world engineering decisions. So, take my opinion on this with that in mind.
Traditionally, I've always used Python with whatever framework (Django, Flask, FastAPI) but always had this feeling that I am learning a framework, not digging into the language which is what I would like. Django, for instance: you end up feeling that a big part of it is magical, which is something that I personally dislike.
A few months ago I found Go and fell in love with it's pragmatism and its non-written (as far as I am aware) rule of not relying on frameworks but instead on just libraries. I find it great, but again, I don't have direct experience in the real world to know the trade offs on multiple levels this can bring.
Number of people here (apparently) confusing frameworks and libraries is kinda surprising.
With framework, your app becomes the framework and that framework becomes your app. There’s no abstraction and clear separation like with libs. Oh, maybe you can have abstraction with frameworks, but then why use the framework in the first place.
> Companies that have, "A team that defines the standards, processes, practices, frameworks or architectures that other teams must follow," are amongst the lowest performers. Reversed: companies that lack this, amongst the high performers.
(formatting edited)
1) I'd like to see real data behind this claim. (feels very anecdata and I have reversely correlated anecdata)
2) Companies that have large codebases or large developer populations and don't have any of these things are often headed for disaster.
That's from the state of DevOps surveys. Those aren't causal and define performance oddly.
I'd speculate that companies that benefit from that sort of standardization probably don't care about blindly maximizing deploys/day (maybe nightly plus emergencies is enough) or minimizing time from coding started to deployment finished (maybe a better starting point is when the request is first made, or maybe they're optimizing for development throughout instead).
Using a framework will affect the maintenance of your software. So you need to consider that aspect before using it. If it will harm or hinder you, depends entirely on the specifics of both the framework and your project.
For example, source code availability is a big factor. Is your project short lived, say a prototype, or do you need it working for 10+ years? If the former, source code availability of the framework might not be an issue, if the latter then you certainly want the framework source.
Another point is if you need to track the latest version of the framework for some reason, or can you live with an old version. On Windows for example, you can still use Delphi 7, released in 2002, with its VCL framework to develop applications. Won't look pretty but will work.
I've worked on projects that use frameworks, and don't.
My experience:
1. Frameworks do save time at the start of the project. There's lots of stuff that comes for free and it does get the project going faster.
2. Every project that uses a framework (and survives long enough) ends up fighting that framework. And the more comprehensive the framework, the quicker the project reaches this point and the harder the fight is.
3. If the team doesn't know the framework well at the start of the project, most of the speed gains at the start are lost, and most of the issues with the framework later are worse.
In my experience (almost 30 years now), using libraries instead of frameworks gets most of the benefits and stops most of the pain.
Architectural mismatch leads to a clash when one's own architectur (or framework, for bigger projects) does not align well with another one that one wishes to use. As a friend of mine used to say "frameworks are like hollywood: you can't call us - we'll call you".
If you can, supply your functionality as a toolbox instead.
Yeah, I think this is pretty language specific and really case-dependant. My ports-and-adapters project in golang is built so that I can easily switch out gin or gorm or graphQL in a bit. I don't really get this discussion haha
Libraries that you can call from your code are conceptually much simpler than frameworks that call your code. I don't think this means that zero frameworks should exist, but frameworks are generally not composable (hard to use many in a single application) while libraries compose trivially.
I agree that there is a problem here, but I think its a slightly different one.
Frameworks and libraries both save you time and require you to invest some time. The main question is whether the savings will be bigger than the investment, and that question can be hard to answer.
In most cases we tend to err on the side of framework optimism - we presume a framework or library will always save time (don't reinvent the wheel, NIH syndrome, etc). Sometimes when we do this, its because we realize the deep rabbit hole of building something like the framework or library we're using. Other times, its because we don't know whether the hole is deep or not - we don't have the expertise to evaluate.
I think the second case is where most of the danger lies. Which is why, paradoxically, its a good idea for a software engineer to reimplement a few pieces of general purpose software in a more specific manner every once in a while and live with them for a longer time.
Unfortunately, this is not always possible; often the next best thing is to contribute to an existing open source project and ask (in the kindest way possible) why certain things were implemented in a certain way and/or learn from its commit and issue history. Learning doesn't mean you have to agree with the authors - in fact often even authors will lament certain design decisions that painted them into a corner or increased complexity unnecessarily.
Doing the above will make it easier to evaluate wheather a framework (or library) will save time or drain time. Without it, erring on the side of caution seems like the safer option, which is why we keep recommending it. However, sometimes the drain can be significantly bigger than the savings - if you're spending most of your time fighting the framework that's a signal that something is wrong and we should have a way of listening to that signal and responding strategically.
The downside of frameworks that I think the article is correct about: general-purpose software is really hard to get right. Every author has a specific set of experiences and needs which depend on their specific situation. It may be worth spending some time researching the kind of software built with that framework (or library) to see if there is any obvious bias that would make it not fit your problem domain or your specific context.
Daniel Stone once pointed out a key difference between libweston and wlroots, two competing approaches for generalizing the work involved in building a Wayland compositor, to explain why wlroots succeeds where libweston does not. He drew the key distinction between a framework and a toolkit. Weston is the former and wlroots is the latter.
The difference is that a framework is in control and defers to your code from time to time, whereas with a toolkit, you are in control and defer to the toolkit when necessary. A toolkit-style library can still do most or all of the heavy lifting for you in a single library, but this approach is much more powerful and flexible than a framework approach while retaining most of the benefits.
Many people view the framework/no-framework debate from the angle that the no-framework side describes a hodgepodge of libraries thrown together to create a crappy half-framework in the downstream code, but that is not necessarily the case. A "one big dependency" approach works with or without the framework design, and a toolkit design offers many advantages that the framework approach cannot.
If you ever feel the need to divulge further into the concept of toolkits as opposed to frameworks, I would be most appreciative to read a blog post outlining such.
Not sure I agree with this . A dependency is a dependency and you should always think about whether you want that dependency. Whether it is a framework or not is not really the important point.
The important point is how much does this dependency "lock in". e.g. if inversion of control is a framework "thing", doesn't that in principle minimize the impact of the dependency?
To put it simply, this reflects an amateur understanding of frameworks. I know where the author is coming from, because I've been there/done that/tried that. It sounds nice on paper, but experience has shown that this is a poor way to approach software development.
I see this kind of mindset with developers who think only about code, and not about solving problems at scale with other people.
Once you go to the grocery store and pick the 25 different libraries fundamental to your application, congratulations! You've created a completely new interaction between those sets of libraries and you get to debug those interactions instead of your own code for a portion of your time.
I've seen this with python flask REST environments where folks pull all these tiny pieces off the shelf and stitch them together. Meanwhile Django REST Framework has a mostly common baseline that you adopt and then diverge from as needed.
I am getting bit in the butt right now for using the ionic framework for building a multi-platform mobile app.
If I want to build a mobile app in JS, but not use a framework (ionic/cordova/react native), how do I proceed?
While I admit framework-driven cross platform mobile apps are bad, even native code is vulnerable to OS updates shifting the ground from underneath them.
I think that says more about the maintainers than libraries vs framework. Some maintainers value backwards compatibility and some don't. Some value the time of their users more than the purity of their platform/framework. React as a framework seems to value it's users -- upgrading isn't that hard. Angular 1 to 2 didn't. Microsoft and x86 worship backward compatibility -- 30 year old programs frequently run without a hitch on the PC platform, thus showing that they value backward compatibility. Anything written against a Google sdk or api or platform will need to be reworked every 2-3 years or the app will break.
Most sufficiently complex codebases that aren’t “framework” based will have a poorly implemented, feature-lacking, bug-ridden version of a framework eventually.
If Django doesn’t fit the use case for your thing, don’t use it? Just don’t use flask and then start reimplementing Django.
Also, Rails is better Django. It’s not even a close comparison.
Every flask REST implementation I've seen has been a bespoke library combinatorics mess compared to something that could have been written in Django REST framework.
It’s impossible to predict the future. I would rather start with rails and rewrite portions later on, than start with Sinatra and shoddily reimplement rails features.
I also just think Django is terrible compared to rails, and that may be why the author has such a dim view of frameworks in general.
It’s worth noting huge companies started with frameworks initially. Just looking at rails: Twitter, Shopify, Airbnb, Basecamp, ..
More experience I do into programming, more and more I coming to the opinion that Framework is just an alias of "Technical debt". Please use libs, not framework.
While I don't necessarily agree with most of this article, it's very good. It really just illustrates why so many people get jaded with tech.
I believe you can absolutely build your own well-documented framework and be successful, but ultimately some little sh*t is probably going to come in either say, "Why aren't we using React? Let's rewrite in React!" or "I don't like how this is done so I'm just going to redo it some other way I like in this one place." From here you have your camp of people who say, "Just don't let that happen!" and then your other camp of people who say, "I need to hire people, and nobody wants our custom stuff on their resume so let's just use TodaysFlavour.js so we can hire whoever and make the investors happy". And that's, like, two scenarios of many.
I guess all I'm saying is that it's really hard to find value from articles like this one when the surface area of the context is pretty much unimaginably wide.
I like frameworks and two of my professional anecdotes are: I once worked for a company with an absolutely horrid culture yet their codebase was rails done "the rails way (tm)" and it was great! I got my bearings immediately and pretty much had no questions about where anything was (which was good because I didn't want to talk to my coworkers... don't worry, I didn't stay there long). I also worked at a much better company where one or two people were hell-bent on coming up with their own ideas while everyone else mostly didn't care and just wanted to get the work done. This is well-and-good but these people had already decided a previous defined way of doing things was no good so they changed that, and when they leave, I can bet that whoever replaces them will decide that their well-documented way of doing things was no good. I wish people would just follow the framework unless it doesn't make sense to (which you only actually know after you've tried to do it the framework's way).
Well, I've written way too much already for a comment... But I'll add that I think the biggest thing this article misses is its points around "speed of development". Speed of development is always important in the beginning. Once the idea has been proven to work market fit, then the generators this article talks about are no longer important.
Anyway ya, Imma shut up now. Overall, good article. I'm going to read it again tomorrow as I'm sure I missed a lot.
Everything or almost everything stated in the article is true. That said, it doesn't matter. All software and software ecosystems are ephemeral and you can't know what you might need or want in the future, especially years down the road. All software lives in a constantly changing world so attempts to manage maintenance needs in the future can be a fools errand.
Yes, decouple your business logic from your frameworks and libraries as much as possible. Don't expect that to make your software more maintainable.
Yes, be aware the using a framework or any technology is coupling, but also be aware that you can't decouple from everything. Make the best decisions you can with the information you have now and have test automation to check for regressions.
I decided not to use a framework. I spent about a month going over the "TodoMVC.com" demos with the intent to choose one but after a few weeks of pondering which one I concluded I didn't want to invest in any of them.
jQuery and Mustache.js do a lot and are easy to use. CouchDB and PouchDB are too and that gave me user authentication, a powerful server side DB, and offline-first/local-first features.
I've never regretted those decisions but I had no investment in SQL DBs. Over the years since I've seen other's who've did struggle with CouchDB and I get that. I came from using CGI.pm's "Save" and "Get" functions and CouchDB/PouchDB.js are similar in how you use them, but way better.
> CouchDB and PouchDB are too and that gave me user authentication, a powerful server side DB, and offline-first/local-first features
I use CouchDB / PouchDB as well, but I'm curious about user authentication: I had to implement a wrapper around it (in Node), because CouchDB auth is extremely limited. For example, I want users to sign up by email + password (not username) and I want them to be able to change their username. CouchDB itself basically has no concept of that. You make a user with a name and that's it. Can't change it without additional code.
Frameworks are designed to predict the future about how they're going to be used. They're often wrong in that prediction but people try to write frameworks nonetheless.
If you're not using a public framework then you're writing one from scratch. If you're writing a framework from scratch then you're predicting the future. If you're predicting the future you'll probably be wrong, and the person who came after you is stuck using your framework.
Since most people don't greenfield apps, most people will be stuck using someone elses framework.
The problem with frameworks is the problem with software. How do we design things such that the design has enough flexibility to perfectly anticipate the future?
In what sense? The design or contrast? Or the language used?
English isn't my first language, so I can imagine I could do better (I'm the author btw). If it's the design: I really need to tweak it a little further, but rather spend that time writing content than tweaking the blog itself :D
The grammar! Do you use something like Grammarly when writing?
I must say that anyone writing in a second language deserves high respect. English is my second language as well, so I know the struggle... Keep it up! You have good content here.
> This makes sense: if everyone in a company is forced to use, say, Django, for any project, regardless, there will be a lot of projects where Django is a very poor choice.
Sorry, if you are forced to use a framework that's your beef with the company not the framework.
> if the use of framework slows down shipping of new features today, it is causing harm. ... when the use of a framework allows shipping features fast early on, at the cost of slowing down the shipping of new features or changes later on, that is harming maintenance. ... when the framework diverts resources into work that has nothing to do with delivering value to your customers.
You just described tests. Any app will become slower to maintain as you need to update the increasing amount of tests. Guess what, framework does the bunch of it letting you focus on testing business logic, and it does so at a cost of imposing a structure.
> a last type of harm, is when a framework that was once a good fit for a project, is no longer a good fit.
That's just reality. I guess coming up with your own structure somehow makes your app immune to having to ever refactor it?
IMO the author thought framework is a silver bullet that allows you to not think or care about the architecture at all and now is channeling misplaced disappointment.
I've had extensive experience on both sides of the fence -- working on apps within existing frameworks, and also maintaining custom frameworks & libs for apps using those. Unfortunately I find this article of very little value.
The author's claimed idea of "decoupling from the framework" is generally ineffective & impractical. It leads to extra layers of adapters & SPI with high cost and almost always zero value.
These sure add bloat & make the codebase pointlessly difficult to navigate, but are improbably unlikely to ever add value in allowing the framework to actually be changed.
Difficulties include mismatched abstractions, endless adapter layers, parameter types for methods also all needing to be abstracted, restricted capabilities, difficulty conveying behaviour/ dynamism rather than static values, and -- of course -- poor performance.
Results are severe choke-points hindering functionality, broken abstractions where stuff actually had to be done, and 90% of the SPI abstractions turning out worthless if you ever did try to migrate to another framework.
I'm an architect. I've seen people's non-portable abstractions so many times. The article's advice just seems so unlikely to help.
Pick a framework that offers long-term maintainability and lets you separate out your domain model & business logic, and just code directly in it.
Rather than railing against bad frameworks from limited experience (perhaps in rickety languages too), the author should perhaps spend some time to find a good one. Spring is fine for many purposes. The MVC is coupled at the front, but your domain model need not & should not be. Focus on that, which should be your business value.
It's funny, this divide between the old world and new world.
The old world has a heavy emphasis on computer science itself, theoretical correctness, long term thinking. It has led to the role of the careful software architect, design patterns, UML, the like.
Everything about this old world is a fantasy, as it requires ideal conditions. You'll need low delivery pressure and a homogenous set of well-disciplined high-end engineers.
That's not how software is built these days. You need to ship multiple features per engineer per 2 weeks or so. There's no time to do it the right way. Worse, most programmers are bread programmers and couldn't even grasp deep computer science, most have never studied it. Even better educated engineers compromise due to time pressure. The role of software architect as it was before, barely exists anymore. It's just a senior developer winging it.
In this context, if anything, frameworks aren't opinionated enough. Many don't have "batteries included" leaving unlimited options to screw it up. And the team will screw it up.
Maintenance? The software cycle in some domains, especially web and apps, is so fast that we'll just start over every 3-5 years anyway.
>> A team that defines the standards, processes, practices, frameworks or architectures that other teams must follow..are amongst the lowest performers.
It is a matter of degree. If teams responsible for this are legitimately trying to make things better (and not just trying to infallible high priests), it can be helpful. If there are established ways of doing things, it can sometimes alleviate the need to make the same decisions over and over again.
At a minimum, Technology Standards Czar has to be earned. You can't just conjure up a spot on the org chart one day and staff it with some outside rando with a long, jargon-stuffed resume. The Technology Standards Czar should be an internal hire with a history of making good technology decisions for the org.
* promote helplessness by abstracting away fundamental but tedious tasks one ought to know how to do,
* erode the capacity for innovation by making it difficult to contemplate or impossible to implement solutions outside the framework's feature set,
* achieve an equilibrium I call 'mutually assured mediocrity' in which a programmer or organization necessarily vows to remain at the same low level of technology as their competitors.
E.G: a complex django project will have parts that don't use the framework at all. In fact, I never ever use forms with Django, and I do use raw SQL.
Not to mention you can start with a framework, and remove pieces you don't need on the way. Like Instagram did with the django ORM.
Of course, you have to choose a framework with the proper balance for this to work.
Purists want their project to be homogeneous, but it never ends up that way because engineering is a about compromises and dev is only partially about code.
And in the end, you framework will not harms more your maintenance that home made structure, it will just put the burden of maintenance on different levels, which may or may not be what you want depending of your objectives.
But usually, you are not Google, and you have neither the requirements or abilities of such a big structures. Which means a framework is likely bringing more than it's going to cost you if you look at the project average cost during it's entire life. Provided the framework is well made, chosen and integrated, which is a big if, but then you have similar ifs for custom systems.
Complexity. Specifically the complexity of the framework vs the complexity of your need.
Often frameworks/libraries solve the whole problem. For example Oauth. If you want to provide "login with {Google, Amazon, Apple, Facebook, Instagram, etc}. then you must deal with the differences and oddities of each implementation of the service. And all the different modes of "login with" and then keep up to date with changes.
The difference is the same as that between buying a shovel and an excavator. Excavators are fun - at least until you have to fix them - so if you can afford one there is a temptation.
Complexity in software is the product killer. The cost of maintaining ten excavator type solutions can kill your product and your productivity, and can require you to create a maintenance department.
Libraries and Frameworks are always a temptation and often are useful, but understanding the full cost and all the downsides increasingly makes what seems like an obvious choice not so good.
But what if you need only a very basic flow for Github? Do you need that complexity? You may need to expand your solution, so
This is what happens when you view your application as an abstract Platonic object, immortal and perfect, outside any actual concrete implementation. Making the app serve web requests is part of the problem to be solved. The problem is the problem. Looking up whether a user exists as part of handling a request is completely fine because that's the simplest way to make the app do what it needs to do.
If you have some stupid "clean architecture" layer bullshit where your own application doesn't know how any of the rest of it works and everything is absurdly decoupled via some hexagonal bullshit, you're going to get into shitty situations where e.g. you have to call the database repository to do N queries rather than just one because the "clean domain layer" is written that way and the "HTTP message delivery layer" is only an "implementation detail" that has nothing to do with the pure business domain. Then your product will fucking suck fucking shit and you haven't actually solved the problem.
> In a framework, unlike in libraries or in standard user applications, the overall program's flow of control is not dictated by the caller, but by the framework.
> In other words, users can extend the framework, but cannot modify its code.
He is talking about a specific kind of framework, not about every library under the sun. And for those he may well be right.
Back when Unity was new, most games done with it kinda looked the same. I don't know if Unity evolved to allow more control/customization or people are just better at working around it now.
And if you browse the web, you eventually run into a bunch of sites that all kinda look the same and act the same. Again, this is due to the framework imposing their way to do things instead of the developers/designers deciding it. I suppose an experienced web dev could actually recognize what framework a site like that is done on without looking at the source code, just based on behaviour.
This may be good for cheap one offs but not so much long term indeed.
Even though he has a point about harming future maintenance and how the framework has no obligation to give a damn about what you need.
Ie, see React 18 introducing double rendering for state and useEffect on strict mode (on by default in Nextjs). Makes debugging harder when shit runs twice, all for some future update.
I don’t fully agree. The author has quite a few excellent points, but when one says it may “harm” the “maintenance” of your software one must define which variables are used to measure “maintainability”. Is it MTTR, cycle times, bug density, or what?
Speaking of maintenance in broad terms makes the argument fuzzy.
I heard an analogy between writing without a framework / your own framework an nuclear energy that I found fitting (not taking sides either way). Please bear with me.
The best-case scenario is better. More energy in the case of nuclear and just what you need, more performant, less code in the case of no framework. Everything just for your use case and no more.
But the worse-case is much much worse too. If you drop checks and discipline once (key developer switching jobs without in-team knowledge, for instance) there is no way back and the consequences can be catastrophic.
I would conclude than in general it is not worth it, but if you have the discipline and political incentives and/or special requirements (big ifs) it can be worth it, as long as those ifs keep being true.
I think most of the problems come from insufficient semantic power of actual language. Most programming language, even the most advanced don't manage time, don't manage locality, and don't fit in the brain representation human makes of the code.
It's remarkably explained by Blackwell in his paper "Metaphors we Program By: Space, Action and Society in Java"
https://www.ppig.org/papers/2006-ppig-18th-blackwell/
So frameworks try to manage this gap, and the only solution, IMO, is to invent language that integrate more advanced semantics to avoid the necessity of frameworks
"In other words: enforced standardising the tech, doesn't pay off."
That's a completely different thesis from frameworks are bad. My org uses frameworks extensively and we reevaluate which are fit to purpose at every new project. Rigid enforcement of rules without thoughtful analysis is just a straw man and I've never seen an org that does that.
I'd also just disagree with the rest of the argument. Frameworks provide both speed to market and shared vernacular that makes it easier to onboard team members and find support communities online. I have a small team and some software that is 10+ years old. The maintenance team has turned over 300% since inception. Without a framework we'd be completely lost.
As everyone else pointed out, frameworks are a natural evolution of sufficiently complex applications and "framework-less" codebases often have their own proto-framework solutions to things.
I don't think the issue is frameworks but rather being locked in to a framework. I'm really interested in seeing where the micro-frontend trend as well as island-centric tools like Astro, Fresh, or Hotwire evolve. Tools like these show it might not be the frameworks themselves but rather the way we use the frameworks that are the issue. Despite React praise for being "a library not a framework", there is a very clear focus on SPAs throughout the ecosystem and I feel like its potential flexibility is really stifled by this
It discusses many of the same trade-offs, but reaches different conclusions. It is true that frameworks are not for everyone, and their benefits are likely more pronounced in larger organizations.
Though a really old one. I should really upgrade, but -being a static site- never felt an urgent need, all the security flaws in any of the dependencies are hardly relevant. :)
Frameworks come and go. What is trendy today will be deemed obsolete a few years later. By the time when the community no longer interested in said framework, it will feel like the rug got pulled leaving many projects stranded.
I'm not a java developer so I don't pay much attention to spring.
But I think the overarching point also includes versioning. For example, asp.net 1 app will still run today just fine, not so for many of these frameworks. RoR, Laravel, et al, all become a rat wheel of upgrading every 1-2 years.
It's a problem.
Contrast that with CakePHP which is still supporting CakePHP2 (I think, it's EoL is coming up soon though) over many many years. I do worry they're increasing their cadence and becoming like most other frameworks in this regard, so I may have to stop praising them for their attitude for support of older versions.
Agreed - I think most programming language communities have settled on one major framework (though there are plenty of other smaller ones) and they've survived.
Oh I agree - 15 years ago picking a web framework would have been much more difficult - for web frameworks now though I think that using the most popular choice should be quite safe.
Symfony is actually more like several different frameworks under the same name. Some of our projects are stuck with Symfony 1 and upgrading them to the latest version is aking to switching the frameworks because they have almost nothing in common.
I don't have that experience. I have personally run many different services, and most of them starts in seconds. The exceptions are usually those that start some process at startup (like syncing jobs, leader elections, database migrations, waiting for database locks etc.), but that is not something specific to Spring.
I think this article sums up my experience with frameworks. It's not to say they're worthless but that if you use them then you should minimize how much you modify them based on your stakeholder feedback. That means communicating to your stakeholders the limitations of the framework and the costs up diverging from the framework's structure to build a feature.
Whoever insisting promoting building everything from scratch, should try to live with such home grown framework.
I saw few times when after building such software, original authors left and you stuck supporting this old crap with usually no documentation.
After some time you decided to leave, but your CV does not contain now magic words as Spring, Django, etc.
> a software framework is an abstraction in which software, providing generic functionality, can be selectively changed by additional user-written code, thus providing application-specific software. [..] Frameworks have key distinguishing features that separate them from normal libraries:
You mean, whereas you call a library; a framework calls you? :)
the real reason frameworks are a burden is that you re not allowed to edit their code. We should be able to change every bit of the architecture for whatever reasons to make it an organic , coevolving part of our project. But for this to be possible we will need AI to perform external upgrades without breaking our code
Most developers only have a two year horizon, and they are always thinking about the next job. If you learn some proprietary software it will hurt your chances to easily switch jobs in the future. So you end up choosing the company that uses the framework you believe you're going to keep using at your next job.
It depends a lot how strong/leaky the abstraction layer is. For example nodejs and PHP are less leaky then the abstraction layers (frameworks) applied on top of them. So the more layers of frameworks stacked on top the faster it is to get a working demo, but the harder it will be to maintain.
My main issue with the usage of frameworks is when they are used in a situation where they are clearly not needed. It seems common in my opinion that people who use npm, react etc. as a part of their work -- where we can assume for the sake of argument that it is necessary -- also use these same tools for minor hobby projects they're involved in, where it really wouldn't be necessary.
I've seen more than one "theme" for example for any generic site generator or blogging software that does nothing more than set up some CSS rules, define some views and use some very minor JS for interactivity, but still has a minified output ground through npm with the almost mandatory 200+ dependencies that of course break and cause security warnings over time.
I've also seen entire products written in a framework that seemed invincible in the day it was created, only to be a dinosaur everybody despises five years later when new functionality needs to be added. Frameworks inevitably makes me think of the poem "Ozymandias"[1], they accumulate as dead monuments over time, and it cannot be avoided.
So, what to do? Well, my humble and highly personal opinion is that two thoughts should at least be entertained:
1) Using less code and less infrastructure to "build" it may, for smaller projects, make them a lot more maintainable and robust over time
2) For larger projects, instead of hooking your cart to one framework for everything, focus on separating the functionality into different parts, so that at least when one of your frameworks need to be replaced five years down the road, you can keep using the other separate parts that work fine.
[1]: I met a traveller from an antique land,
Who said—“Two vast and trunkless legs of stone
Stand in the desert. . . . Near them, on the sand,
Half sunk a shattered visage lies, whose frown,
And wrinkled lip, and sneer of cold command,
Tell that its sculptor well those passions read
Which yet survive, stamped on these lifeless things,
The hand that mocked them, and the heart that fed;
The criticism is mainly on last-generation frameworks that came around before React and the like. They bundled together an all-in-one approach to writing web apps. Django comes with an admin tool!
The world has largely moved to richer frontends so stacks are more flexible.
Write small, well tested services in the easiest to use framework you can find. If the service becomes hard to maintain then replace it. This should be a simple job guided by the tests.
People talk about services like libraries aren't a thing. That exact same statement with `s/services/libraries/`.
"Write small, well tested libraries..."
If you have a library with a solid, small public interface and you carefully maintain compatibility on that interface with great testing, you can be decoupled. Plus you don't have 2 network interfaces and the internet injected into a call to the interface.
Yes, this applies almost equally well to libraries as well. With the slight exception that you are not just bringing the library into your code but all of its dependencies as well. This makes it _slightly_ harder to wholesale change a library compared to a service.
If you read far enough, this is the author's actual complaint: "Yet most frameworks come with all those details up-front and mixed up. They often make it very hard, if not impossible, to be isolated." I disagree. Very few of the frameworks I've used have made it difficult for me to write all the interesting parts of my app in a framework-agnostic way. A complaint I could agree with is "frameworks tempt people to write too much framework-dependent code", but a purely technical criticism does not match my experience with frameworks.
A unit-testing framework? What does it really do? It has a test-runner. But running software isn't some black magic, its easy and solved. It has naming conventions. But those are really just something a team can pick and never look back. It has ways to call functions based on those naming conventions. But that is really an extension to the test-runner.
Now, all the assert_contains, has_called_x, those are valuable. But easily offered as library.
I strongly caution solo developers away from using a backend framework. A frontend framework is necessary for modern web development. Every HN startup should be going as minimal as possible.
Once you have 2 or more developers, you'll need to adopt a framework for new work (Rails, Django, etc.). Once you have 20 or more developers, you'll have more frameworks than you can count. And that's ideal.
Discrediting the article with blanket statements and criticizing the format of the site are both against HN guidelines which you can review at the bottom of this page.
nonsense. This is relevant to the authors thesis: If frameworks are bad and everything should be done manually or in a decoupled way - the quality of the work product of the author, should be subject to discussion. Are they hand weaving beautiful prose? or deluding themselves that they can do a better job?
I find it highlights a key discrepancy: if the author had relied on a framework for this, the quality could be far greater at less effort.
So, frameworks are bad, unless you follow standard advice about loose coupling?
I'd think most things would be bad if you failed to follow that advice about them, and the frameworks I'm most familiar with (aspnet core, ef core) seem to be pretty good about making it easy to follow.
I think this comment went off the rails a bit, but the framework people you are describing do exist. I don't think it's a majority, but I've encountered them.
A case was Celery, where despite countless other options for async tasks - we must use Celery because that's what the framework says. It was a bad fit as well.
I do stress that I do not lump all framework proponents in this bucket though - that seems like an overgeneralization.
2. If you have a talented team, that half of a framework can be much better than using a one-size-fits-all framework that is popular because it used to be lean and mean with a small surface area, but has grown over time to do everything for everyone, becoming a complex monster.
3. If you have a small team that hires slowly, it's relatively straightforward to bring new devs up to speed on "the way we do things." if you are hiring rapidly and/or have a large team, the more bespoke things you have, the harder it is to maintain them.
4. Over time, everything degrades. In the long run, many framework-free applications either get walled off as "legacy" apps with new work done in separate services, or replaced outright. If it makes you money before that happens, you win. It is not necessary to try to design architecture that will last for centuries.
5. My last and--to me the most significant--observation is this: You want to pay the majority of your attention to the code that has the greatest impact on your desired outcomes.
Using libraries and frameworks is like a business outsourcing things that aren't its core competency and also aren't competitive differentiators. Most software shops do not win by having their own framework or by not having a framework, they win by using something bog-standard and saving their attention for the part of their code that "moves the needle."
But that's only "most," and your business may be one of the few.