> 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.
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.
This is why I refer to frameworks as an insane asylum as I described here to 27 up votes: https://news.ycombinator.com/item?id=32914694