Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The hammer analogy breaks down from the get-go for me. The main distinguishing factor between a framework and a library is the classic "you call a library, but a framework calls you."

A better (but still imperfect) analogy might be buying a timber frame (with plan) versus home-rolling a stick frame from the ground up. With the planned timber frame house, the rough layout of the rooms and plumbing and such is somewhat predetermined, and as such it "calls you" in the sense that you're building out the amenities, but with the ground-up stick frame, you're explicitly making all the framing decisions too.

Like all things, there are bad frameworks, but scoped appropriately (simply) they can be incredibly useful. Just like houses, it turns out there are many ways in which web services are similar to each other and can benefit from a common framing.



Yes, a house frame is closer conceptually to a software framework than a hammer, but I don't think that's relevant and would only undermine the rhetorical effectiveness of the analogy.

The purpose of an analogy is fundamentally to describe some unknown thing (the subject) by comparing it with a different, known thing (the analog) that shares a common attribute with the unknown thing. The value in the analog is not in how many attributes it shares with the subject, but in how salient it makes the particular attribute you wish to highlight.

Consider when a boxer is described as having a "glass jaw". Here, the subject is the boxer's jaw, and the analog is the material glass. It would be pointless to complain the analogy is a bad analogy on account of the fact that glass is translucent whereas the human jaw is not. The point of analogy is to highlight that the boxer is vulnerable to impacts to his jaw. The value of using glass as the analog is the readiness with which we can conjure the mental image of glass breaking; the translucency is irrelevant.

Likewise, the point of this analogy about hammers and frameworks is that the author wanted something simple that would just work, and what he got was an over-engineered mess that requires considerable yak-shaving to get it to work. The fact that a hammer is more like a library than a framework is irrelevant, the point is that a hammer is something simple and familiar.


It is still a poor analogy, and the fact that a better analogy undermines the original point should suggest that the original point is flawed. Saying "I need a hammer" and reaching for a house frame is a poor choice. Saying "I want something simple that will just work" and reaching for a framework is the root of the author's woes. They don't even explain what the specific technical grievances are, it's just one drawn out analogy.

If they want a hammer to build a house, they'll need a screwdriver, and tape measure, and a table saw. They looked at a few toolkit options on the shelf, got tired of reading the instructions, and ranted.

To be fair, I'm sure frameworks in 2005 _were_ cumbersome. (I'm frustrated enough using Spring in 2021, but I still recognize that it's a fully featured house frame ready to go)


The analogy just makes so much intuitive sense to me that I may be having a "curse of knowledge" thing in trying to explain it to people who don't get it. In thinking about your response I think I may not have explained the author's analogy correctly. Let me try and correct that to see if things make sense.

The hammer here is not meant to be analogous to a framework. The hammer here is just supposed to be some sort of functionality provided by the framework. It is the store that is supposed to be the analog to a framework. Just like a hardware store provides tools, a framework is supposed to provide a collection of related pieces of functionality.

The point the author was making was that the frameworks available at the time would never just provide you the functionality in any sort of direct way (i.e. selling you a hammer). Instead, those frameworks were all about providing users with a generic set of abstractions for building or configuring the functionality you needed (i.e. a hammer factory).

Let's keep in mind that this is 2005, barely a year after the initial release of both Ruby on Rails and Maven, two pieces of software which which would later popularize the notion of "Convention over Configuration". At that point frameworks (especially Java frameworks) were generally these hideous, over-engineered, design-by-committee monstrosities. The fact that Ruby on Rails and Maven went on to be wildly successful is in fact a vindication of the point the author was making.


Thank you, I appreciate this. It drives me crazy when someone dismisses an analogy because some other attribute than what’s actually being compared doesn’t match. Yes, you’re right, they’re not the same! If what you compared were exactly the same in every way, they would be the same thing!

I think it’s part dishonesty, part emotional attachment to the things being compared (you should probably rarely bring Hitler into the mix, even if technically it works), and partly that some people just don’t understand analogies.


I think it's partly that it is easy, especially for technical people, to get hung up on details. And there is a good reason for this. It is often the case, especially with very technical topics, that the use of analogies can actually hinder understanding, because of the tendency to take the analogy too far[1]. Usually you just have to communicate a bit more on what the scope of the analogy is, and then it will make sense.

There's also a subjective element in terms of what analog will be salient. Using the phrase "glass jaw" isn't going to have the same effect for someone who first thinks of Pyrex or bullet-proof glass.

> Yes, you’re right, they’re not the same! If what you compared were exactly the same in every way, they would be the same thing!

LOL! I've had that conversation almost word-for-word.

[1]https://byorgey.wordpress.com/2009/01/12/abstraction-intuiti...


I remember the first time I heard the phrase “glass jaw”, by then I was early college age and it pretty much just made sense without requiring much thought. The only context I needed was that it’s a boxing term.

If I contrast that with the difficulty I had understanding the hammer factory analogy having just read the linked article , I’d say there is some value in creating better analogies. Not all analogies are made equal.

That said, I finished the article and didn’t feel completely connected with the analogy other than, true frameworks do make me jump through a bunch of hoops sometimes. Is that what he means with this analogy?

If an analogy is a tool to aid comprehension, or make a point, I can’t follow what this is supposed to mean.

Also FWIW, glassjaw is a great band if anyone likes 00s screamo


The analogy is that the hardware store represents framework, and the hammer represents a piece of functionality the framework is supposed to provide.

The point is that frameworks of the era rarely provided a simple, direct API for performing some task. Rather, there was often a whole bunch of "Abstract Factory Factory" patterns, which would require a bunch of ceremony before you actually had and object that did the work you needed to do.


I agree, it’s of course also possible for analogies to be strained or unclear. You need to keep the audience in mind as well.


If the analogy is misleading then it hardly seems a defense to tell me that a more accurate one would lack the same rhetorical force.


> "you call a library, but a framework calls you."

This is why I don't like when people say "React isn't a framework, it's just a library". Almost all of my React code is "called by React" with the one exception being `ReactDOM.Render()` (I don't count that since every other framework has some analogous "bootstrap" instruction).

Now if folks want to argue that React only handles the "view layer" without providing a built in state management solution, that's absolutely true (and considered a separation-of-concerns positive by a lot of people including me). But I feel like so many folks just boil this down to "React isn't a framework, it's just a library" and then use that as a segue to negatively comparing it with their chosen tool.


> Almost all of my React code is "called by React" with the one exception being `ReactDOM.Render()`

It only feels this way because your calls to React are hidden away behind JSX. I believe this is also why you can't write any JSX without importing the React module first.

If you've ever had the "pleasure" of writing React with plain React.createElement() calls (what your JSX ultimately gets transpiled to) then I think you would more likely agree with the notion that React is "just a library".

Create-react-app is much more akin to a framework in that it bootstraps an environment for you where you don't have to do any of the things that make React feel like simply a fancy library for rendering HTML.


> If you've ever had the "pleasure" of writing React with plain React.createElement() calls (what your JSX ultimately gets transpiled to) then I think you would more likely agree with the notion that React is "just a library".

I'm not sure why someone would unless you're strictly writing static JSX with no components whatsoever as some sort of weird replacement for just writing the equivalent static HTML. The minute you write a `render` or lifecycle method, React is now calling you. Not to mention stuff like Suspense asking you to throw a Promise to render from latest render cache.

I think something like Crank.js[0] is more a view library since it puts all the nuts and bolts into userland.

[0]https://crank.js.org/


You use React APIs to do everything you would normally do with React. You use the API directly if you don't have a build step for your web app and you cant or don't want to add one. Since React is indeed simply a library with an API, you can progressively integrate React into an existing web app in this way (a big selling point in the early days that people have sensibly forgotten by now). You couldn't progressively integrate a traditional framework like Django for example.

Lifecycle methods like render, componentWillMount, etc are just callbacks that get fired when you render you a component. I don't think any library is immediately graduated to the class of "framework" the moment a callback is added.


> You couldn't progressively integrate a traditional framework like Django for example.

I dunno here, is Rails a server application library because I can progressively integrate the different components of its total API, e.g. first use ActiveRecord, then adopt rails-api for the frontend, then adopt ActiveView and Turbolinks for the end-user frontend? Or is there different idea of framework at work here?

> Lifecycle methods like render, componentWillMount, etc are just callbacks that get fired when you render you a component. I don't think any library is immediately graduated to the class of "framework" the moment a callback is added.

But I don't write the code that says when they're called. Backbone is more of a library, for example, since it lets me do all that and it can be progressively integrated into an app too (I can just use models, I can just the views, etc). I mean thats part of why people ran to Ember and Angular when they appeared, they didn't feel like doing all that.

Also see Crank.js: you can emulate React's Component API in Crank, but the reverse is not true. If I'm not writing the code that "turns the gears" per se, then to me I'm using a framework. That framework might have a small API surface, it might have a large API surface. That's how I see it at least. A framework to me is defined by a certain threshold of abstraction.

This is an async task library because I can opt-in and out of, as well as control, or simply replace, the scheduler[0]

[0]https://github.com/mitranim/posterus


>I dunno here, is Rails a server application library because I can progressively integrate the different components of its total API

I'm not familiar with Rails but it sounds like the individual components you list can be used independently of your traditional Rails web server so that would indeed make them libraries. I'm not sure that makes the entirety of Rails a library. Could you rewrite an endpoint with Rails within another Ruby web framework (I don't know of any) without needing to run two servers? If so, Rails is a library.

> But I don't write the code that says when they're called.

That's simply not true. Every lifecycle method is the direct result of a specific programmatic call. Whether it be a render (ReactDOM.render), prop change (also ReactDOM.render), or state change (setState). If you don't setup the logic to call these APIs appropriately no callback will ever be fired. It only feels like React is firing these events for you because these API calls are likely hidden behind JSX and hooks and they are also asynchronous by virtue of React having to manipulate the DOM.

> If I'm not writing the code that "turns the gears" per se, then to me I'm using a framework.

The only gear you don't get to control is specifically how the DOM is manipulated. Everything else is in your control when using React.


> I dunno here, is Rails a server application library because I can progressively integrate the different components of its total API, e.g. first use ActiveRecord, then adopt rails-api for the frontend, then adopt ActiveView and Turbolinks for the end-user frontend? Or is there different idea of framework at work here?

I think you misunderstood parent comment. Progressively integrate here means: you have a web page (facebook.com), you want to replace a part of it with react (chat function), you rewrite just that portion of the webpage in react.

You can't get a Sinatra application and replace just one route with rails. Well, you can use ActiveController, which is just an opinionated wrapper around Rack with a lot of sugar, but that wouldn't be rails and you won't get any rails benefits of doing that.


Great resource for anyone interested in this. It’s really enlightening: https://pomb.us/build-your-own-react/


yes, well if I didn't use most of the built in functionality of a framework I suppose it would be a lot more like using a library.


Support for JSX is not built into React. React is simply a JS library and JSX is not valid JS. So if you add React to a web page, and attempt to write logic with JSX, you will get syntax errors.


No, it's literally the case that JSX compiles into (indirect) calls to your own functions. It's not a magic 'framework' that calls your code when you use JSX, it's... your code.

When you write

   return <MyFunction foo={bar}/>
that gets turned into

   return React.createElement(MyFunction, { foo: bar }, [])
Which returns a refreshable wrapper round the result of calling your function.

It's really a reactive-functional type system, rather than a framework - with a syntactic sugar that makes it easy to generate a reactive wrapper round a function.

Then you take the result of passing all your functions into that syntactic wrapper and hand it to ReactDOM to have it synchronize it with the DOM.

React transcends the framework/library discussion because it really isn't either. It's a higher-ordered type factory.


React is a library that should have been a framework.

Literally everyone has to cobble some n-factor framework together and given the amount of inexperience out there, what results is a damn nightmare.

React solving the state problem natively would have made it an industry game changer. What we have is an industry mess.


Angular Vue and Svelte fit your description and none of them are more popular than React, I guess people have made their choice.


It's an open question whether React succeeded because of technical advantages or because of Facebook's initial support and the job market creating its own dynamic (people go where the jobs are).


> React is a library that should have been a framework.

React is a library that powers several different frameworks, as well as lets people use it without those frameworks. If one size fits all, answer-for-everything frameworks were the optimal solution for all problems, Angular would own the world and we wouldn't need React.


Google rug pulled angular, I know at least one very large company that pulled all Google tech from their stack over angular 1 -> 2.

React really isn't the thing people have decided is the optimal solution, jsx and keeping presentation tightly coupled to business logic is.

What is see with react is constant attempts to work against that ideal.


> React really isn't the thing people have decided is the optimal solution

My point is there is no one thing people have decided is the optimal solution. React is an element of snow me of (several different) things people have found is optimal for some problems, and not part of others.

> jsx and keeping presentation tightly coupled to business logic is.

JSX is more generally than React is, which is why many not-React solutions use React, too, though even that is far from universal. Tight coupling between business logic and presentation is, OTOH, far less generally what people have decided is optimal.


I've seen entire apps written as React components/hooks, the whole thing, no redux/mobx/etc managing state above the level of necessary local UI state. React markets itself as just a library but the truth is people tend to go all in precisely because there's too much pressure to research a whole stack for yourself.


Those are likely some really solid applications as a result.

In my experience redux just enables developers to sprinkle global state everywhere which makes tests a pain to write and code hard to debug.


I think React's original goal was to be a library, but the community made it a framework, because they could not conceive of any other way to operate.


Less that they couldn’t conceive of any other way, but more so we are slaves to the vdom diffs. That’s what we signed up for, and boy did we get trapped. Go ahead, put a little jquery into your React app, or that animation library that looks cool, you’ll blow up the whole point of React.

Sorry, you will have to do things React’s way until the end of time if you want your rendering to be optimal. That means whatever it means, hooks, suspense, fibers, context, so on.

A library means I get to plug in other stuff without totally crippling another library, as React claims it is.

Nothing wrong with React, just become the framework you are and provide the built in solutions.

Think of it this way, imagine the React team made curl. Now they say you can curl anything. So now you say, ‘ok, I want to curl this’ and they respond:

‘Oooo, I don’t know about that, that’s gonna mess up all the curl internal optimizations, hmmm, no no, you SHOULDNT be curling that’

And then we all walk away going ‘oh’, silently. Checkmate, hoodwinked.


Hmm, I don’t really agree on this one. Just a day ago I’ve added a totally not vdom, stateful component that was mutating DOM and adding nodes on it’s own to fix performance problems with critical part of the app that required instant feedback to user typing.

React was not bothered at all. From the start there were ways to escape React model in components and integrate components into other frameworks. Been there, done that, it was never a huge deal.


Yeah, that's been my experience, too, for instance in one of my toy projects dropping a rotjs game display into a React app.


Can you describe what you did? Breaking out of React for rendering means you are in deep shit. In fact, I’d love to see the hoops you jumped through, which I’m certain you will brush away as ‘not a big deal’.

But I am an American, so I won’t put up with any inconvenience and don’t consider it virtuous to do so (we fought a war over a tea tax after all).

But I’ll take a wild guess:

A bunch of useRefs? I’m excited to hear all of this.


React only re-renders a component if the state changes, the props change, or a parent component re-renders. In my app, I only have one component where I needed to break out of the vdom, and none of the parent tree ever re-rendered (except when navigating to a new page, which correctly tears down the component), so it was as simple as just one useRef to grab a reference and one useEffect to pass it to my other code after the component rendered.


A pretty straightforward pattern here (and one that I actually just implemented with no hiccups for a non-React animation library) looks like:

    import { useEffect, useRef } from 'react';
    import { Controller } from 'some-animation-library';

    const SomeWrapperComponent = ({ options }) => {
      const elementRef = useRef(null)
      const controllerRef = useRef(null)

      useEffect(() => {
        if (!elementRef.current) {
          return () => {}
        }

        if (!controllerRef.current) {
          controllerRef.current = new Controller(elementRef.current, options)
        } else {
          controllerRef.current.setOptions(options)
        }

        return () => {
          controllerRef.current.doSomeCleanup()
        }
      }, [options])

      return <div ref={elementRef}></div>
    }


Thanks, that’s exactly the simplicity I wanted you to share, you did good.


The most recent thing was the typing app where we had to change style if each character after user typed it. With long texts (10k of characters) performance of tree diffing was not acceptable (especially in Safari) so we replaced whole text component with manually managed DOM and were mutating nodes directly.

I’ve been using React for quite some time (started with version 0.11 or something) and had to integrate quite a few libraries on my own (stuff like OpenLayers for maps, etc) and it also worked pretty well. Also made few apps that had only few widgets (search UI, calendar, etc). It usually worked quite well.

Mixing React with non React is quite easy. You only need to encapsulate it - keep all non vdom stuff in one component and never escape single DOM node.


And with hooks that's become even more true, there's now a distinction between React functions and regular JavaScript functions, and you can only call a React function from another React function.


Not entirely true. Hookless function components can be called as regular old functions just fine


It stops being a library when you structure your entire codebase around it.


Or any part of your codebase for that matter


It used to try to be like that. Only calling setState re-renders things. And you control state and when to render.

Until the hooks introduced.

Now it also want to handles all the state and timing for update. And you are no longer able to call from outside or decides when to render (in a simple manner, as there are still workarounds).


> > "you call a library, but a framework calls you."

> This is why I don't like when people say "React isn't a framework, it's just a library"

Eh, this is just a breakdown in the "framework calls you" heuristic. It's still a reasonable heuristic, but it doesn't completely describe all distinctions people make between frameworks and libraries.

The distinction missing from the heuristic is the overall scope of the software project relative to other popular software projects in the same area. When people say "React isn't a framework, it's just a library" they're not saying much about the coding style one uses while using React. They're just comparing the overall scope of React to some of its close competitors (like Ember and Angular).


> "React isn't a framework, it's just a library"

There may not be a clear line between framework and library, but as written in the homepage of reactjs.org, it claims itself: React - "A JavaScript library for building user interfaces"


HN: Use the right tool for the job.

Also HN: Always and every time do use a carpenter analogy... or something involving woodwork.


I think a lot of programmers secretly want to be carpenters.


What happened to good old car analogies? This carpenter stuff is a little too waxed moustache hipster for me.


Modern cars are incredibly complex and car engineering/manufacturing has really complex lifecycles. It is quite difficult to make an analogy with a thing that requires a lot of analogies to in the first place to explain.

Carpentry/woodworking is somewhat simple. With a saw, planer, router, sander and a few primitive hand tools you can finish most woodworking projects. Most of the complexity of woodworking is in the accuracy/quality. Woodworking is simply easy to be conceptually* familiar with.


There's no irony in this statement unless you assume that "HN" is one person who you expect to be consistent.

I think we all visit HN because of the many people and varying opinions and ways of thinking. I hope we continue to see conflicting thought processes like this!


Also HN: lets take a few comments and pretend that's everybody on HN ;)


So what do carpenters use for analogies?


Software Engineering.

"Just imagine the facade is the frontend."


I liken this instead to GOTO vs COMEFROM. A library is a GOTO statement, while a framework is a COMEFROM statement. Deity help you with the latter if you have problems and not enough knowledge about the framework.


I always saw it as a tight-coupling with whatever framework you are working with but a loose-coupling with whatever library you are working with, but I like this more. It's much more emotional, almost psychological horror to a programmer.


It is...and then you can't help thinking about the "no-code" solutions.

Anyway, also:

1. any application with sufficiently complex use cases requires configuration

2. any configuration can be made programmable

3. frameworks are application configuration with an open-end configuration programmability

4. ...

5. profit



> The main distinguishing factor between a framework and a library is the classic "you call a library, but a framework calls you."

This definition does seem to match how I generally hear the terms used, but I think whether you call something or if something calls you depends more on the function of the library/framework than anything to do with the code itself.

I think we generally have "web frameworks" and not "web libraries" because if you are making an HTTP sever, then yea stuff is going to be calling you. ie.e the incoming HTTP requests are going to trigger your code. Now if I have a piece of code that extracts URLs from a string, that is obviously going to be called by me. That I can see, who is calling who has nothing to do with the design of the framework or library, and everything to do with the sort of task the framework or library performs.

Anyway, engineers obsesses over the distinction between library and framework, but it seems fairly mundane from my perspective.


> because if you are making an HTTP server, then yea stuff is going to be calling you.

Not necessarily. You could write the

  while True:
    request = getNextRequest()
    ...
yourself. A web server library would have functions for parsing headers, creating http responses, handling cookies, generating html, etc., and could have data structures that make it easier to dispatch requests to individual handlers, but your code would be in the driving seat as to what gets called.

Also a web framework could call a function to extract an URL from an incoming http request without any involvement of code you write.

A framework provides a main method; a library doesn’t.


The thing is that computer guys got too much in love with the word and started to think framework === full blown 15-tier industrial facility.

A good framework removes a chunk of work, guides you for the remaining part so you get there quickly but it should stay narrow if possible.

here's a small framework: https://imgur.com/a/rBBdRSO

here's j2ee 4 understanding of the term: https://imgur.com/a/EH3vpXD


It's trivially easy to reframe the hammer as a framework; just take the point of view that what you're bringing to the table is the nail and the two pieces of wood (or other kinds of parts on which some type of hammer might be used).

These pieces of yours are "called on" by the "hammering framework".

This would all be easier if we had a metaphor-factory-generating factory.


It invokes some of the particular absurdity of Spring or AspNet, though.


I personally have often drawn the analogy of frameworks-as-general-contractors. Subcontractors (devs/engineers) are hired throughout the lifetime of the project and are the ones actually building all or most of the individual components, using tools (libraries), but their work streams are specified and directed by the GC.

Some GC's are super opinionated (Rails/Django/Sails) and others kinda let you do what you want (Sinatra/Flask/Express). Neither disposition is inherently bad, but can have serious consequences as a direct result of both.

I think this maps pretty well to the "framework calls you" concept you point out, a nod to inversion of control I assume.


If we go down the woodworking analogy path, I guess the main difference between a library and a framework is that the former is a set of transformative actions and the latter is a set of building primitives.

A really great analogy wood be a wooden window. A router/planer/saw in a workshop are libraries: they can take a piece of timber and transform that piece in a certain, somewhat adjustable way. A set of standard hinges/locks/mounts and router/drill sizes is a framework.


When you instead call it a factory analogy, exactly as the story reads, it suddenly fits well.

Confusing a framework for arbitrary reuse is perhaps the best way to identify developers who aren't the mythical 10x developer. It is no different than confusing decoration for something useful when you are fending off destitution.




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

Search: