Live data from Hacker News

Write Libraries, Not Frameworks

brandons.me

331–338 of 338 posts

Re: Write Libraries, Not Frameworks

#331
post #326

Earlier quoted context omitted.

I didn't say your experience was an outlier, just that you're surely a bit biased towards a certain point of view having taken up Clojure right after it was birthed. But yes, your experience is bound to be an outlier compared to people starting to use it in much a more mature state, which will be nearly everyone in the long run. As for jdbc, I don't use it currently, but did at my old job (along with honey sql). If y…

The old library has always been painfully slow on large datasets, and is no longer actively maintained so that isn't getting fixed. And because Clojure people expect you to compose libraries not use frameworks, these sorts of upgrades are never transparent. Thus, a whole new library, the Clojure way. And again, this is every year I've used Clojure (e.g. the Shadow migration you yourself went through on what I can onl…

Not sure what you think your many straw men are going to accomplish. Pretty sure almost no one but the two of will be reading this...?

I guess you think your attitude is a mark of superiority, but in reality you sound about as intellectual as Holden Caulfield in The Catcher in the Rye.

Re: Write Libraries, Not Frameworks

#332
post #326

Earlier quoted context omitted.

The old library has always been painfully slow on large datasets, and is no longer actively maintained so that isn't getting fixed. And because Clojure people expect you to compose libraries not use frameworks, these sorts of upgrades are never transparent. Thus, a whole new library, the Clojure way. And again, this is every year I've used Clojure (e.g. the Shadow migration you yourself went through on what I can onl…

Not sure what you think your many straw men are going to accomplish. Pretty sure almost no one but the two of will be reading this...? I guess you think your attitude is a mark of superiority, but in reality you sound about as intellectual as Holden Caulfield in The Catcher in the Rye.

I'm not trying to sound intellectual, I'm just trying to convince you my experience is real. I posted a very simple response to the article, detailing one direct consequence of a preference for libraries over frameworks. You're the one that jumped in to tell me I was making it up.

You can take personally any criticism of your favourite language and its proponents (I'm still one of them, honest!), or you can approach technology with a degree of scepticism. Really no interest of mine, and it's clear the feeling is mutual. Good luck in your future endeavours (and for what it's worth, I used to work for a Clojure NLP startup so I do genuinely mean that - wouldn't it be nice if there was a nice cohesive framework for NLP tasks in Clojure?)

Re: Write Libraries, Not Frameworks

#333

Earlier quoted context omitted.

React is a great example of a library that provides enough structure that you typically don’t need a framework. I don’t think you always need a framework for this reason. And it’s definitely battle tested as are all the extras like router etc.

Aside from the fact that create-react-app itself is pretty much a framework, even if you don't use that and roll it all yourself you end up with a codebase that has many of the same hallmarks of a framework such as directory conventions, common class patterns, a bootstrapping mechanism, etc. There's plenty of messy React codebases out there that screw this up.

[deleted]

Re: Write Libraries, Not Frameworks

#334
post #191
post #141

The more I program, the more I am convinced that owning flow of control is one of my primary jobs as a programmer. If I surrender this to a framework, there are a lot of decisions I can't make with regard to performance, and I have a lot less certainty about when and in what order exactly things are executed. There are of course some exceptions, but in general I want libraries to provide me simple, synchronous functi…

This hits home for me right now. I'm currently battling some performance problems related to a lot of "magic" that happens when using the Apollo GraphQL framework and am strongly considering ripping it apart and taking back control of what happens and when.

Is Apollo GraphQL helping you more than REST + queries?

Re: Write Libraries, Not Frameworks

#335
post #104

Earlier quoted context omitted.

Just use a language where it's possible to implement those things in plain old code. When you have higher-kinded types you don't need any bytecode manipulation, you can just have a type that wraps anything that needs to happen in a transaction, and compose together transactional operations in a visible but type-safe way - and you don't even need the runtime cost. How anyone can look at Java as it's actually used and…

> Java .. Scala To be fair, there's something to be said about a seasoned/documented library versus the cooked up micro-framework/function that a random coworker invented in Scala to do the same thing, and which might be implemented differently in each project in your company! Source: I'm about a year into Scala after many years of Java. I like a lot about Scala, but 4/5 places where we have "plain old code" where in…

I'm all for using standard and documented libraries provided they follow the rules of the language, and I don't think Scala goes against that - if anything "microlibraries" that do one thing and do it well seem to be more common in Scala than in Java. What I'm objecting to is frameworks that violate the rules of the language and require their own special understanding, even if those frameworks are well documented.

Re: Write Libraries, Not Frameworks

#336
post #191

Earlier quoted context omitted.

This hits home for me right now. I'm currently battling some performance problems related to a lot of "magic" that happens when using the Apollo GraphQL framework and am strongly considering ripping it apart and taking back control of what happens and when.

Is Apollo GraphQL helping you more than REST + queries?

I think it helped us to go really fast at first. Observable queries and subscriptions made it relatively easy to make the site feel very live and collaborative. Not sure how much help it is now as some of the magic is causing performance challenges

Re: Write Libraries, Not Frameworks

#337
post #133

Earlier quoted context omitted.

You can also do it visibly in Java without too much noise IMO. The point of AspectJ is to hide this stuff completely from application code (but it's still visible in its definitions). Whether that makes sense or not I'm not going to debate (I personally don't think AspectJ is particularly great) but arguing that other languages allow you to do that in a more or less visible way is besides the point. AspectJ is a lang…

> AspectJ is a language, these aspects are visible and have their own language abstractions, just separate from the application code. Just like you have monad implementations separate from their uses. So writing aspects is also "plain code". Code containing aspects is certainly not plain Java code, because the aspect annotations (or, worse, invisible string-name based pointcuts) change the behaviour of the code they'…

> Code containing aspects is certainly not plain Java code,

I didn't say it was. AspectJ is AspectJ, as you surmised correctly "a language in its own right", and so when you define an `aspect` that's it's own thing, not a `class`. You seem to demand that the language is Java, but that's not really a criticism of AspectJ, the language, then, rather denying that it is a language.

It's like saying a C++ class and some implicit behaviors that change behaviour of user code (via a custom assignment operator override) is crap because it's not C. Maybe it's crap because you don't like it and like C better but it's still not quite fair to demand it be "plain code" when it is plain code.

Please look more deeply into https://en.m.wikipedia.org/wiki/AspectJ. It has its own syntax and is not just some annotations plus a framework you have to run.

FWIW, your arguments against AspectJ work just as well against any language with macros or metaprogramming in general (although you probably don't like those either, and that's fair!).

> If you want to say that AspectJ is a language in its own right, then it's a language that breaks all the rules of good language design

Frankly, the kind of things that AspectJ offers or proposes to use are IMO no less sane than some of the things languages like Ruby (e.g. monkey patching, middleware decorating/nesting calls via including a module, defining methods is a dynamic call that can be intercepted and customized, etc.), Python (e.g. decorators), JS (e.g. messing with prototype behaviors), or even Prolog (e.g. metainterpreters that metalogical predicates to implement different resolutiom strategies) typically encourage.

People have called monads the "programmable semicolon", and so you can do all kinds of things that don't at all represent what a user of the monad would anticipate unless they read the docs/implementation. It could enforce some form of order of evaluation, or store additional state that is hidden, etc. Sure, this is not the same thing as aspects or metaprogramming/macros, but what they have in common is that some external definition defines the exact semantics of a application/user piece of code and has potentially a whole lot of freedom to stray from what may look like it's "obvious".

The goal of AOP is to find a solution to challenges were modularization by typical means hasn't worked. And the typical examples are usually valid. Is it great? Is it needed? I'm not sure either, but your criticism sounds a lot like you only look at it from a lense of a pure statically typed functional programmer. From that POV a lot of language designs probably look impure and crap, whether justified or not.

> It (or other libraries that do much the same thing) is the vast majority of Java as it actually exists in the real world.

Are you specifically talking about AOP or AspectJ? I believe the former. And I don't think it's AOP, you are talking about various frameworks implementing a wild set of changes to the core language via reflection, code generation, or other such things tailored to their specific use cases.

Say what you will but that, while it might fall into the AOP class of doing things, is quite different from AspectJ's goals. The idea is/was that you don't need all these different frameworks with their own conflicting custom implementations. Rather, that using AspectJ should be the common language in which these metaprogrammatic aspect-oriented concerns are defined (for instance by such a framework that's currently using it's owm custom implementation with no common set of rules), which can be analyzed and provide static tool support (e.g. "who"'s amending, wrapping, early aborting behavior for this particular method).

So, again I don't think the criticism of AspectJ is fair (abd that's what I addressed, not the modern state of Java and frameworks in general). If at all, the problem is that AspectJ itself isn't actually used but instead that its superficial ideas have been coopted and turned into a metaprogramming wild west. Maybe it's AspectJ's fault but I think it's just a coincidence. That state of affairs is not unique to Java at all, either.

Re: Write Libraries, Not Frameworks

#338
post #133

Earlier quoted context omitted.

> AspectJ is a language, these aspects are visible and have their own language abstractions, just separate from the application code. Just like you have monad implementations separate from their uses. So writing aspects is also "plain code". Code containing aspects is certainly not plain Java code, because the aspect annotations (or, worse, invisible string-name based pointcuts) change the behaviour of the code they'…

> Code containing aspects is certainly not plain Java code, I didn't say it was. AspectJ is AspectJ, as you surmised correctly "a language in its own right", and so when you define an `aspect` that's it's own thing, not a `class`. You seem to demand that the language is Java, but that's not really a criticism of AspectJ, the language, then, rather denying that it is a language. It's like saying a C++ class and some i…

> I didn't say it was. AspectJ is AspectJ, as you surmised correctly "a language in its own right", and so when you define an `aspect` that's it's own thing, not a `class`. You seem to demand that the language is Java, but that's not really a criticism of AspectJ, the language, then, rather denying that it is a language.

By building on Java AspectJ tries to have it both ways, which I think is a mistake. It's normal, and I'd even say semi-encouraged, to use non-AspectJ-aware tools when working on an AspectJ codebase - and of course an upstream library maintainer may not even know their library is being used in an AspectJ codebase. Which causes real problems because they will refactor according to a different set of rules.

> FWIW, your arguments against AspectJ work just as well against any language with macros or metaprogramming in general (although you probably don't like those either, and that's fair!).

> Frankly, the kind of things that AspectJ offers or proposes to use are IMO no less sane than some of the things languages like Ruby (e.g. monkey patching, middleware decorating/nesting calls via including a module, defining methods is a dynamic call that can be intercepted and customized, etc.), Python (e.g. decorators), JS (e.g. messing with prototype behaviors), or even Prolog (e.g. metainterpreters that metalogical predicates to implement different resolutiom strategies) typically encourage.

Yes and no. You list a bunch of things that are bad to a lesser or greater extent, but the method-name-pattern-based stuff I've seen done with AspectJ is the most cryptic form I've ever encountered. Not only is nothing visible at the declaration site or the call site (not only no decorator but no magic import either), you can't even grep for the method name to find the thing that's messing with that method.

> People have called monads the "programmable semicolon", and so you can do all kinds of things that don't at all represent what a user of the monad would anticipate unless they read the docs/implementation. It could enforce some form of order of evaluation, or store additional state that is hidden, etc. Sure, this is not the same thing as aspects or metaprogramming/macros, but what they have in common is that some external definition defines the exact semantics of a application/user piece of code and has potentially a whole lot of freedom to stray from what may look like it's "obvious".

That's not really true in my experience; monadic composition is programmable only in the sense that an abstract method in an interface is programmable (indeed monad usually literally is an interface with abstract methods, or the closest equivalent in the language you're working in). Syntactically you can see that monadic composition isn't regular composition and so you know that some effect is being invoked, and as with any abstract method you might be able to click through to a specific implementation or you might have to accept that it's just "some unknown implementor of this interface". But in an important sense there's no magic: all your values are just values, all your functions are just functions, all the normal rules of the language still apply. I do object to things like thoughtworks each where a seemingly normal assignment gets magically rewritten into something monadic.

> The goal of AOP is to find a solution to challenges were modularization by typical means hasn't worked. And the typical examples are usually valid. Is it great? Is it needed? I'm not sure either, but your criticism sounds a lot like you only look at it from a lense of a pure statically typed functional programmer. From that POV a lot of language designs probably look impure and crap, whether justified or not.

Well I came to that precisely because of experience with that problem. It was seeing the bugs introduced by AOP that made me look for a better way to do things, and that was how I got into functional programming.

> The idea is/was that you don't need all these different frameworks with their own conflicting custom implementations. Rather, that using AspectJ should be the common language in which these metaprogrammatic aspect-oriented concerns are defined (for instance by such a framework that's currently using it's owm custom implementation with no common set of rules), which can be analyzed and provide static tool support (e.g. "who"'s amending, wrapping, early aborting behavior for this particular method).

That's fair. But in that case you have to see at AspectJ as a failure in terms of today's Java ecosystem. Even codebases that use AspectJ don't manage to avoid using all those other metaprogramming frameworks as well, and I don't think I've ever heard of a framework deciding to move away from a custom AOP implementation into doing something via standard AspectJ. (And I do think that AspectJ offers too much flexibility to ever make for a comprehensible codebase, even with the help of better tooling support).

> That state of affairs is not unique to Java at all, either.

It's not unique, but it's embraced to an unusually high extent in Java (Ruby would be another example). And I can't help thinking it's because of Java's deliberate, advertised simplicity, because a lot of the aspect-based stuff seems to be there to paper over missing language features (or, even more tragically, to paper over language features that are now there as of newer versions of Java, but that Java programmers have got used to having to step out of the language for).

Post reply on HN