Sick of Ruby, dynamic typing, side effects, and object-orientation (2014)
blog.abevoelker.com
blog.abevoelker.com
- Thanks to the proliferation of Rails and similar frameworks, most Ruby apps at least have something that resembles an MVC structure. With JavaScript, once you move past the basic TodoMVC examples you are pretty much on your own. It gives you enough rope to hang yourself, all you colleagues, and everyone in the building next door.
- The expect vs should change in RSpec is nothing compared to how fast things are changing in JavaScript. I think there are now 7 different ways of just defining a module.
- The stdlib of Ruby is pretty sensible. JavaScript has many inconsistencies (take Array.slice vs Array.splice - one modifies the original array, and the other does not), and you usually need to rely on third party libraries, or write the code yourself, to do pretty basic operations.
- The JavaScript community seems to have the opposite of NIH syndrome, so that even basic functionality is offloaded to a third-party modules (see leftpad). The project I'm working on has over 1000 modules in it's dependency tree.
for at least 90% of the problems out there, its the the best approach. There are a lot of design patterns out there, but you can do a lot with MVC. From what i've seen, the reason developers tend to shy away from it is because it's TOO simple. They don't feel proud of it, because its so cut and dry. They want to create something unique and interesting and challenging, even if a simple solution would do just fine.
But it's not a balance, or a 50/50 sort of decision making. Really, MVC should be your first choice, and you better have a really good reason for it to not be, and a really viable alternative.
To extend the analogy to its breaking point, just because some people treat every problem as a nail too be fixed with a hammer doesn't mean that you can't use a hammer if you genuinely need to push in a nail.
If we were discussing untrammeled neophilia, though, I'd note that in a fast-moving field it merits the professional to keep up a lively familiarity with the new tools which will likely soon deprecate the old, and it likewise merits the organization invested in such a field to avoid letting that investment grow so stale that it becomes difficult to find good people to work with it. There's really nothing here that hasn't happened with almost any other software specialization over the last few decades. It's only that it happens faster now, because everything happens faster now. There can be a certain fatigue in that, and from the outside - or from the perspective of one who has suddenly noticed that the world has moved on while he has not - it can seem as though there's nothing to it but new shiny things for new shiny things' sake.
I have not found it so; instead I find that today's tools enable those who know how to use them to do more things, better, and faster, than yesterday's tools could support - and I confide that tomorrow's tools will improve the situation still further. But perhaps my own perspective is the one that's flawed.
Aren't you assuming a bit too much?
What normally happens is that those new tools are deprecated sooner than the old ones they are replacing.
If you're writing 1000 lines of throwaway code I agree with you. If you're writing a 100,000 lines of code that is meant to be supported for years - then I disagree wholeheartedly.
- There is exactly one way to define a module. Write a file. Done. Webpack takes care of it.
- You were using Webpack, right?
- The fact that Webpack either wasn't on your radar or already solving your problems says a lot.
Look, I know this sounds like bullshit, and in fact it's very difficult to distinguish this from actual bullshit. But there are a huge number of people here -- old fogies, stuck in the past, yearning for the old days that are never coming back -- who hate JS, and that hatred manifests itself in ten thousand subtle ways.
Inventing the idea out of thin air that "there are 7 different ways to define a module" is simply false. It does not resemble reality. Yes, it's true you can point at all the dead module systems that came and went, but nobody bothers even thinking about those systems because they're dead. They're zombies. Yeah maybe some people use them, but realistically if you're getting shit done in JS that means you have webpack and all of these concerns are not actually concerns.
JS stdlib seems like nonsense? Lodash.
Feels like you're importing too much bloat? Webpack tree shaking takes care of that. Closure compiler eliminates all the code you're not using. There's no reason not to use a first-class stdlib, whether it's Lodash or whatever else you prefer.
- The JavaScript community seems to have the opposite of NIH syndrome, so that even basic functionality is offloaded to a third-party modules (see leftpad). The project I'm working on has over 1000 modules in it's dependency tree.
This is the power of JS. It's the thing to force yourself to embrace. You need to join the cult of bullshit and just mentally force yourself to love this rather than hate it. It's why JS won. You can hate it all you want and revel in the insanity, but there is zero reason to do that other than as a way of making yourself feel good. Which is just another way of saying we're all acting very selfish when we lash out at JS like this.
Yes, you're correct. Every one of your points is absolutely true. Yet it's all so very wrong. I wish I could put it into words better than this.
Look dude. I've been around the block. I vividly remember what this shit was like in 2008. You want pain? Holy shit, I remember trying to make a little arrow rotate on my webapp. I wanted finder-style arrow rotations. You know how on a tree view, each folder has a little arrow, and it points to the right when it's collapsed? Click on it, it rotates 90 degrees and points down, and the tree expands. YEah, I tried to do that in 2007 right when Rails 1 was first coming out. Talk about horror. The solution -- the only solution -- was to make an entire animation frame by frame, of the arrow rotating 90 degrees. Like 16 different images, just for this stupid arrow to rotate 90 degrees on command. Because CSS literally wasn't a thing back then. Yeah we had "CSS", but for all intents and purposes we are living in the future right now. We have tools that 2007-me could only dream of.
JS works now. That is not the expected behavior. It's difficult to convey how fucking strange this is. Anyone who lived through that 2006-era transition knows what I mean.
Right now you can drop Semantic UI into your project, hook up React to it, and have first class testing (Enzyme) and state management (Redux).
Don't like all that bullshit? No problem. Use Vue. It sidesteps all the Redux insanity. And the tooling is catching up.
But the way you know these things is by being a JS dev. Living and breathing it every day. There's no way around that. You either throw yourself wholeheartedly into the pool or keep one toe in while complaining about how big the ocean is.
This rant came out quite a lot harsher than I intended; it's just a reaction to the very common trope that HN throws around of "JS is shit, the web is shit, this is shit." Yes, this is true. And yet -- simultaneously -- no. No no no. We can do magical things now. Hooking up Vue with hot reloading is literally magic. If 2007-era me had these tools, I would have launched a startup that could dominate everyone else solely due to the advanced tooling that we now enjoy. Our tooling now vs 2007 is like Lisp vs C++ back in 1999.
No, JS won because the web won. There's a web browser on almost every computer out there. If you write your software in JS, you can run it just by following a link to a URL. That doesn't have anything to do with JavaScript's absurd module ecosystem.
Let's put it this way. Think of your favorite language. Favorite paradigm, whatever. All the shit you hate about JS, picture the exact opposite of that. Now imagine that the web was entirely built around that.
Surprise: now everyone would hate exactly whatever you love. It would've grown all that hair and all those warts you currently despise about JS. It's what the world does.
So when people knock on JS, it's getting much harder to take this stuff seriously. I've been a dev for over a decade and have been down a dozen rabbit holes, from C++ template metaprogramming to .NET nonsense to elisp verbosity to hardcore functional + immutable paradigms. Loved all of them, each in their own way. What we have now with JS is simply incredible from a raw "get shit done" perspective.
It includes special cases for dates, takes O(n log n) time in the number of keys, and has suspicious comments like, "I've managed to break Object.keys through screwy arguments passing. Converting to array solves the problem." There are 15 open issues and 15 open pull requests. A sane language would have this operation built-in.
Pick a project. Think of a website you want to make. At no point during that are you going to be stonewalled by "Man, if only I wasn't forced to spend the last 4 hours debugging this weird deep equality issue. I could've gotten so much more done!"
You can take that information and use it however you want. It's the truth. It's up to you to either reject the notion or integrate it into your mindset and abandon the tendency to cling to idealisms. Ivory tower development simply does not happen in reality, and I say this as someone who spent a couple years trying to build an ivory tower Lisp.
I know it's not coming across at all, but I really identify with your mindset and acutely feel your pain. This was a major mental hurdle that I had to force myself to overcome. I'm saying, it's possible, and the only thing you have to do is to choose to do it.
Let go. Realize that it doesn't matter. It's worth the benefits. You can do so much more.
I was afraid that "letting go" would translate into "now I'm part of the problem too." But it turns out the opposite is true. It's very powerful that you have a background that most JS devs lack. Because they often rabbithole themselves into complexity, and you can come along and do something simple that no one else thought to stop and do.
But you can do all of that while still embracing the wider ecosystem. It's not an either-or. You can help bring sanity to what would otherwise be a ball of hair. But the way to be in that position is to jump in and churn churn churn until you've used Vue and React+Redux and understand the concepts and tradeoffs.
I have faced this on the job. About three abstraction layers deep in a Backbone app. It took me two days to trace the exact cause and find a way to implement a better check, that wouldn't make things respond in unexpected ways.
> It's up to you to either reject the notion or integrate it into your mindset and abandon the tendency to cling to idealisms.
JavaScript is terrible. It is not the product of academic research like Smalltalk or Haskell. I can accept it is the only tool available for the job, and continually look at all the solutions for that particular issue, and I will keep doing that.
I can use JavaScript, and I can write it. Usually my code is simpler and faster, because it takes me much longer to write anything, because of how aware I am of the side-effects. My employers in the past have liked the results that has produced.
But I will never enjoy writing it.
It is a language that is difficult in ways that reveal it's sloppy roots, and spill it's implementation details. Much of the time JS feels like working with UB in C, except it is actually detailed to act that strangely, in the spec.
Just an example that has always stuck with me, this is valid JS:
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
Pretending it's puss-filled core is wonderful is going to lead to nothing but burn out, but so is hating every procedure you write in it.It's a tool. It's sharp on both sides, which can lead to a lot of blood-letting if you aren't careful. But it is still the best carving tool we have on hand.
A better example would be the extremely poor Date object, which has only a couple format functions and can't even be created from a specified format. There's also a bunch of holes when manipulating data, filled by libraries like lodash(although the standard lib has improved significantly in this regard).
Off the top of my head, Haskell has "deriving Eq", and Scheme has "equal?". I'm pretty sure Python uses deep equality for tuples as well. Anyway, it's just one example of something I wanted to do in JS recently and ended up disappointed in the quality of the code I saw to do it.
>>> {"foo": [1, 2, set([True])]} == {"foo": [1, 2, set([False])]}
False
>>> {"foo": [1, 2, set([True])]} == {"foo": [int('1'), 2, set([bool(1)])]}
True
There are better examples of deficiencies in Javascript's standard library, especially when targeting browsers, but Javascript has made massive strides lately like its native Set and Map datastructures.
For example, Set doesn't come with the classic methods `.intersection()` / `.difference()` / `.union()` / etc. but it's just not a defining moment of my overall experience with Javascript.
We're long past the days where you had to bring your own `Array#map`, but I don't know if all of these commenters are.
irb(main):002:0> {'foo' => [1, 2, [true].to_set]} == {'foo'
=> [1, 2, [false].to_set]}
=> false
irb(main):003:0> {'foo' => [1, 2, [true].to_set]} == {'foo'
=> ['1'.to_i, 2, [true].to_set]}
=> trueSure, you can perhaps override some methods on an object, but given two arbitrary objects (like two dicts in Python), knowing if two are 'equal' is not easy and certainly not built in.
That being said, JS doesn't make implementing this easy or simple at all.
See my other comment.
irb(main):001:0> require 'set'
=> true
irb(main):002:0> {'foo' => [1, 2, [true].to_set]} == {'foo'
=> [1, 2, [false].to_set]}
=> false
irb(main):003:0> {'foo' => [1, 2, [true].to_set]} == {'foo'
=> ['1'.to_i, 2, [true].to_set]}
=> trueAny Turing tar-pit can do incredible things. And when it has a monopoly on its own niche, of course incredible things happen.
JS has un unfair monopoly.
Just give us a decent language on FF, Chrome et Edge, and everybody will stop using JS withing 5 years.
I do think however the current trend is OCaml / Haskell influenced languages like Elm, Purescript, Reason, etc. WASM is only going to make them better.
The king is dead, long live the king!
But even without that, then chances that you have exactly the same build than somebody else in cache is very weak unless it's very popular. And to get it popular means a lot of people has to download it, taking the several Mo hit download on first load. And most users will just quit the page before that, thinking it doesn't work.
The solution would be for browsers to stop the madness and decide by community to adopt a new standard with a decent language for the web. Be it Ruby, Lua, Python, at this point I don't care. I'm partial to Python, but I won't fight for it if it means I can get anything with a real stdlib, good builtins, namespaces and a readable syntax.
The same thing happens now with regular browser caching, it's not that big of a deal. People will design run-times targeting webassembly to be lightweight, but if they end up being too heavy, developers will use CDNs the same way they do now with other large front-end dependencies.
> The solution would be for browsers to stop the madness and decide by community to adopt a new standard with a decent language for the web
A subjective and impossible consensus to achieve. The community will never be able to agree, that much is obvious. The answer isn't "pick a language that works today and hope for the best", that is how we got where we are today, rather, we need a solution that gives the community the power to experiment with better solutions that aren't constrained to a single language.
There's a Rails way, Python famously aims for one obvious way of doing things. That just isn't true of Javascript exactly because there is a history of developers writing several styles of JS, the "right way" to write JS being redefined by diligent people like Douglas Crockford & John Resig and things changing yet again and yet again.
And look at ES6, the JS ecosystem barely resembles what was considered good, idiomatic Javascript just a few years ago. There are a bunch of devs who have managed to stay on top of what's current and I'm sure are laying down examples of good practices & building tools in that style. But you are also talking about an ecosystem that includes people that started writing JS 4-10 years ago, have adopted some of the absolute newest flavor of the month practices but also have seen JS change so much over the years that they aren't throwing themselves into everything that is now considered a best practice because they know their code works and there could be another seismic change in 8 months.
Writing Javascript nearly every line of code is haunted with "is this still the way I should do this?" and no other language has that much hassle.
Again, this is a symptom of the "one toe in the pool" syndrome. You have to throw yourself in.
Yarn is a perfect example. It came out very recently, relatively speaking. And yet it's clearly the future. Like, the only reason not to use yarn is if you have a legacy app that explodes for some reason if you try to type "yarn" instead of "npm install". But the common case is that you do "git clone foo && cd foo && yarn" and everything works perfectly.
It's so much faster, and almost never causes problems.
So why embrace that? It sounds like horseshit yeah? I hate to use heavy handed metaphors like that, but that's exactly the feeling that you get when you hear "Oh, now we're supposed to use yarn? what? npm install isn't good enough now? Those fucking JS idiots have no idea what they're doing."
In reality, you're seeing evolution in action. This is what natural selection looks like. The good ideas triumph. And yes, it's subjective what constitutes a "good idea." But when yarn comes along and makes all my npm installs 3x faster, you bet I notice and you bet I embrace it right away.
That's what I mean about throwing yourself in, though. If you don't actually force yourself to love this stuff, then of course you end up hating it. It's insanity incarnate. Yet if you just embrace that fact, and take it as a given, you can actually find it quite fun. It's an adventure to get to learn these new systems, not a chore. If you run across something that doesn't seem to make sense or doesn't work for you, just ignore it.
It just seems like we as developers run the risk of having our heads stuck so far up our own rears regarding our favorite language paradigms or the lack of greenthreads in JS or whatever it is you hate about the ecosystem, that it's very easy to lose sight of the bigger picture. Right now you can build a team of 50 engineers, and if you choose React, that codebase probably won't devolve into utter chaos. React makes it possible to do large-scale coordination. Like, I can send you my React component and it'll probably work in your codebase.
Ditto for Vue. If you hate the complexity of React, and you're a small team (usually just you alone), then you can just use Vue and not have to care at all about React+Redux's monstrous complexity.
You see? You can pivot however you like. If you hate X then just avoid X1 It's really hard to take these concerns seriously when there are so many options.
Ah, yes, that's the crux of it. We'd love it if the world would just stop changing so we can relax and stop learning. Well, too bad! Here's the uncomfortable truth: the moment you let yourself get too comfortable, your career dries up. That fear is a powerful motivator, so I suggest internalizing it. If you can't force yourself to love learning, then become afraid that if you don't learn it you'll find yourself unemployable after 5 years.
This almost happened to me, so I'm speaking from direct experience. I came from gamedev, and low level skills like that really do not translate into "I'm getting paid $INSANE/yr in a hot new startup." In fact, you can barely pass webdev interviews because you have to go "Uhh... Yeah, I worked on Rails back in 2007 or so. I guess I have some learning to do. But just trust me, I can learn it as I go. Oh wait, you don't believe me? But... I've spent my whole life learning as I go... It's fine if I don't already know Rails even though you're hiring for a senior rails dev position."
That situation is exactly what happens when you stop being on top of all this stuff. Go to sleep and wake up 5 years later and suddenly getting a job is hard. It's easy to smirk ad feel like it won't happen to you, but FWIW the way you feel about JS now is exactly how I felt about Rails in 2007.
The truth is that we'll never have enough time learn everything we should learn and every minute I spend re-learning a different way to do something I already know how to do is a minute I'm not spending learning something actually new and useful.
If, for example, I'm writing a web app related to storing and processing geology related measurements (which I am) I should be spending most of my 'learning time' studying things related to geology and the processing of said measurements, not re-learning how web development is done this week.
And there you are a few comments above telling us we have to use Webpack because other older module systems are zombies that came and went.
Something about this smells.
What is it.
Is it the way "we would love it if it stopped changing" but it's us who is changing it?
Is it that the changes are reinventing the wheel? Churn because frothy churn is easier and more profitable than meticulous, solid, long-lasting foundations?
Or is it that we still haven't managed to orient the programming industry around 'finished' software such that if we ever 'finish' software we immediately stop being employed, so we have a pathological need for software to continually need to be rewritten, at the level the average programmer can rewrite?
How is this client side rewrite every few months fundamentally different from the broken window fallacy? as in, unsustainable because it adds no value overall?
Node threw themselves into Semver, and it was supposed to be great. Nobody needs a lockfile because everyone obeys semver, so every time you do 'npm install' your app is guaranteed to work because everything is semver'd!
Oh wait, no, that didn't work out. Better freeze every dependency and sub dependency because who knows what will break when we update!
This is why throwing yourself at whatever shiny new thing without thinking or looking at how other languages do it is not always a great idea.
Last I checked its issue tracker was a pile of "hey, you, uh, didn't implement this npm feature at all, so things break" and "you're missing yet another obvious sanity check here, so things break". No wonder it's faster. The last thing I need in my JS stack is another thing that can fail under ordinary use, for marginal benefit.
You do you, though.
Before I get into the details, as a general comment I find that while you're not wrong, I've found that I need much less 'diving into a pool' when I enter other language ecosystems. I understand why this is the case with JS, and personally I have a soft spot for the language, but even if it's not JS 'fault', I find that it is not a good thing that it takes such a 'deep dive'. They're valid concerns.
> - There is exactly one way to define a module. Write a file. Done. Webpack takes care of it.
it's a lot better now, but this has not been true even until recently. I've probably lost weeks of time over the years figuring out how to load module <x> using import statements where require() worked instantly, and from what I understand it can be a serious headache for module developers to support both 'ESNext' imports and CommonJS requires.
I can't tell how often I still need to search whether it is import x from 'x', import {x} from 'x', or import * as x from 'x', or in some cases the only thing that works is require(x).
> - The fact that Webpack either wasn't on your radar or already solving your problems says a lot.
Not really. I've used Webpack since the early days, and I've tried switching to Rollup, Brunch, and Gulp because Webpack just didn't make any sense to me. Then came Webpack 2 and half the tutorials and documentation stopped working.
FWIW I generally go for Webpack 2 these days, and it's an improvement. But it's a solution that causes quite a bunch of problems of its own. Plus, it's a solution that isn't even needed in anything but front-end JS. For good reasons, and I don't think JS is the cause of the problem (rather, it's bandwidth and general front-end concerns). Nonetheless, it's not even remotely simple.
> JS stdlib seems like nonsense? Lodash.
Why yes. I love lodash. But it's a huge library that I'd rather not load in its entirety if I'm not using most of it. Have you actually tried loading parts of lodash using import statements? Last I checked, a few months ago at most, this was not possible. I had to do require('lodash/blah'). That's not obvious until you've figured it out.
> Feels like you're importing too much bloat? Webpack tree shaking takes care of that. Closure compiler eliminates all the code you're not using. There's no reason not to use a first-class stdlib, whether it's Lodash or whatever else you prefer.
Webpack tree shaking is relatively new. Much of the online help (tutorials, etc.) still refers to Webpack 1.
> - The JavaScript community seems to have the opposite of NIH syndrome, so that even basic functionality is offloaded to a third-party modules (see leftpad). The project I'm working on has over 1000 modules in it's dependency tree.
> This is the power of JS. It's the thing to force yourself to embrace. You need to join the cult of bullshit and just mentally force yourself to love this rather than hate it.
I don't see how defending JS by telling someone to embrace the suck is any kind of valid argument in favor of the JS ecosystem. Could you elaborate?
> It's why JS won. You can hate it all you want and revel in the insanity, but there is zero reason to do that other than as a way of making yourself feel good. Which is just another way of saying we're all acting very selfish when we lash out at JS like this.
First of, JS won despite its quirks and the insane ecosystem. And second, selfish in relation to who? Brendan Eich? I think complaining about the things that do suck about JS and its ecosystem are important toward improving things. As a fan of JS, I don't feel offended when people say it sucks. It sucks, and while I think that's not primarily the language's fault, I also don't get my self-worth from being (predominantly) a JS programmer.
> Yes, you're correct. Every one of your points is absolutely true. Yet it's all so very wrong. I wish I could put it into words better than this.
Without meaning to be snarky, I'd love for you to elaborate. In the grand scheme of things I'm not a great programmer, and I got started with JS, so it's quite possible that I'm overestimating how much better the non-JS ecosystems are.
> Look dude. I've been around the block. [rant that I fully agree with]
> JS works now. That is not the expected behavior. It's difficult to convey how fucking strange this is. Anyone who lived through that 2006-era transition knows what I mean.
> But the way you know these things is by being a JS dev. Living and breathing it every day. There's no way around that. You either throw yourself wholeheartedly into the pool or keep one toe in while complaining about how big the ocean is.
> This rant came out quite a lot harsher than I intended; it's just a reaction to the very common trope that HN throws around of "JS is shit, the web is shit, this is shit." Yes, this is true. And yet -- simultaneously -- no. No no no. We can do magical things now. Hooking up Vue with hot reloading is literally magic. If 2007-era me had these tools, I would have launched a startup that could dominate everyone else solely due to the advanced tooling that we now enjoy. Our tooling now vs 2007 is like Lisp vs C++ back in 1999.
This I do agree with. I'm incredibly happy that front-end development has made massive steps in being saner than it used to be. And it does often frustrate me to read low-effort criticisms that don't really add to the conversation.
But in the past year I've ventured further and further out of my JS world, and I'm starting to understand why so many people are so negative about JS. If I were an experienced dev with little JS experience, the ecosystem would strike me as insane, to the point of just giving up and doing everything with 'server-side' languages. And honestly in the past few months I've been wondering if perhaps I've underestimated how much the JS ecosystem sucks. How much perhaps I've been Stockholm Syndrome'd into thinking this is normal in any way.
All that said, the constant criticism is grating. It doesn't solve anything, and it often carries a whiff of 'if only sane people were working in this area things would be different'. Which is utter bullshit. The JS ecosystem sucks, but it's the best we have, it's not because 'JS devs r dum', and in the end it often offers enough advantages to be worth the trouble. But that doesn't mean it isn't insane. It's batshit insane even now, but for the first time in years it's at least less frustratingly insane. We're moving in a good direction.
EDIT: let me add that I do agree that comparing JS to Ruby/Rails is not perhaps the best way to argue that JS isn't good. I'v encountered plenty of batshit in the Ruby ecosystem.
Regarding "embrace the suck," the best I can say while being brief is...
Ah man, this is such an interesting topic, and it's worthy of a blog post in its own right. You have to trust me when I say "there's something here; it's worth tugging at this thread to find out whether it might be true."
It is counterintuitive. But the fact that it's counterintuitive is a hint that it might be worth checking whether it might be true. Relativity was counterintuitive too.
If you embrace the suck, you can pull the simplicity out of the chaos. But only after you've mastered the chaos.
That sounds like some combination of naive or impractical. Who could possibly master chaos?
You can. And that's all I'm saying. Step one is to force yourself to choose to try.
I do think it's a great situation where one single programming language allows one to not only create complete applications that run on every computer under the sun (without installing Java), but allow you to fucking debug it in a pleasant way on pretty much each of those computers.
But all that said, I wish I hadn't started out with JS and blindly followed the 'chaos'. I've wasted so much time using React and Redux when simply React, or in some cases even good old Backbone of jQuery would have sufficed. I wish I'd learned good programming practices from more overtly functional or perhaps more overtly OO languages, before learning JS. I wish I hadn't spent many hours dealing with Grunt, no, Gulp, no Webpack, no Webpack 2, only to become a 'master' at something that is entirely irrelevant outside the JS ecosystem.
Sure, I learned the intricacies of the 'chaos' and I find myself going more and more for simpler solutions within the ecosystem. I'm comfortable using Baobab.js or MobX instead of Redux. I'm comfortable using only lodash instead of a whole bunch of modules that do part of what lodash does.
But I don't feel any of that made me better as a programming. In fact, as the JS ecosystem is improving, I find that a lot of my arcane knowledge of how to, say, enable hot code reloading in Webpack 1 is entirely useless now that Webpack 2 sort of does it out of the box.
More and more I'm inclined to let the JS ecosystem do its crazy shit and wait for something semi-standard to shake out before I even bother. Because everything I learn about the specifics of this chaos will not be worth knowing in <x> months.
You're right, in a particular way that I hadn't thought of:
Most people don't have a background in programming. They weren't doing it when they were teens, and many people probably started writing code within the last year or so.
In that context, I completely agree. It's absolutely true that at the end of all that chaos, you won't end up a better programmer.
I was speaking as someone who was in the inverse situation: I'd amassed a lot of theoretical knowledge, and spent a lot of time chasing the phantom of "being a good programmer." I researched memory models, read whitepapers, explored how Google implemented bigtable, went through rtm's 6.824 Distributed Systems course just for fun (it's freely available online)... You know, a bunch of hardcore stuff that it seems like "real programmers ought to know."
Yeah... Turns out that doesn't always translate into dollars. It came really close to being a bad situation (explained here https://news.ycombinator.com/item?id=15642428).
Let's put it this way. If I had to do it all over again, it's very possible I would swap skillsets with you. Because you know all of the stuff you rattled off. You are now prepared to avoid it. So yes, it's easy to feel like you've wasted your time. But when it comes to employability, you are far better positioned from a career standpoint.
Stuff like this may feel "out of bounds" of traditional conversation. Normally we're supposed to make up arguments that support our points purely through reason alone, right? Like it would be much more persuasive for me to say "Well, this matters because X" where X is something related to programming. Talking about career stuff and employability may seem like punting. It might also seem like it's something you don't really need to worry too much about.
But when you relax and let yourself stop learning, and stop going through the motions of all that stuff you hated, it's merely 3-5 years before you end up in a similar position. Maybe. Or maybe you'll get lucky.
But that doesn't make it less shit. I'm actively re-schooling myself as a more backend-ish, or perhaps full-stack-ish developer that allows me to use more of Elixir, Clojure, or even Ruby/Python, and less of JavaScript.
I'd say there are basically three perspectives on this:
1. development ease/quality, where JavaScript is not the worst, but far from the best. 2. ecosystem health and best practices, where I find that JS is not doing a great job. A lot of churn, a lot of reinventing the wheel, and a lot of stockholm syndrome defending the mess. 3. money, where being a good front-ender is worth most of the effort and frustration.
I'd say 3 is the most contentious. Most people seem to agree on 1 that JS and its ecosystem are not a paragon of good development. It takes work to even just get a good initial setup, which is not a problem in many other ecosystems. Transpiling, to name one example, is just not necessary. I think a sizable portion of multi-lingual devs would agree on 2 as well.
But 3 is difficult to quantify. Is it a good thing that I can me a good chunk of money building React/Redux apps when I could've built a saner, more stable version in Django/Rails/Elixir in a fraction of the time if the only downside is that it requires a full page reload? I'm not so sure anymore. But it's worth a discussion.
Point 1 and 2 strike me as obvious enough that bringing them up ad nauseum on HN is just pointless and frustrating.
I find myself often frustrated at criticism of JS that really is a criticism of the need to know the ins and outs of the ecosystem as a whole to be productive.
It's frustrating because blaming, well, anyone for that situation just seems a bit utopian and unrealistic. It implies that JS devs are not aware of the problems, when in my experience most non-fanatical ones are aware, but pragmatic.
I'm at least old enough to have been working within various ecosystems where arcane knowledge was pretty much a prerequisite to being productive in said ecosystem. One of the most common frustrations I had was people criticizing this need for arcane knowledge, where my thoughts were "sure, but that doesn't change the reality of day-to-day programming in ecosystem X, and the advantages of doing so perhaps maybe offset the shittiness".
I've experienced this with obscure Delphi-related issues concerning the app's 'chrome' (title/task bar coloring). I've experienced this doing PHP development and being told I'm a shitty dev for even touching PHP. I've experienced this with jQuery, being told that I should use Backbone (which FWIW was a good choice moving forward, but it never really solved my fundamental issues in my previous jQuery work. If anything functional approaches did).
There's a point where it just gets exhausting to hear people bring up the same tired old argument, again and again, for karma or whatnot, against a particular ecosystem, when the arguments are theoretically sound, but where they disregard the pragmatism of 'participating' in said ecosystem.
It's really not that different from a libertarian getting uppity about capitalism when you're busy volunteering for some non-profit civil society-related endeavor to improve things. It's not technically wrong, but it's a hell of a lot more pointless than pragmatically working within said system (and yet, confusingly, still worth pointing out).
And of course then there's a bunch of people who build something that vastly improves a possibly shitty ecosystem, using lessons they probably learned from other ecosystems. I'd say Redux as well as React are great examples of that. I'd love to go into how these are fundamentally very much about functional programming principles, and how I think all these tired discussions about languages hide the more important discussions, but that's unfortunately probably seen as tangential to this discussion.
So the JS ecosystem is a giant pool right? Everyone is swimming in all possible directions with all sorts of contraptions like rubber tires, inflatable dinghies, pieces of wood, plastic garden flamingos, etc. A lot of the swimmers naturally pee in the pool because it's more convenient than exiting (that was frowned upon at the beginning, but people kinda got used to it - and it keeps a steady development speed!).
This might look quite horrifying to those on the outside, but for the swimmers it's nice and warm, while stepping outside is cold and scary, because they would have to learn all sorts of complicated and frightening technologies.
For someone like me that got out when the pool was small around 2006, there is no incentive to jump back in. I mean yes, if I closed my eyes and jumped I would probably adjust after a while. But why jump in the JS pool when I can swim in the open sea? :)
And you think you have any idea what you're talking about when you talk about modern JS just came outdevelopment?
You know when AJAX first became possible? 2005. ES3, the latest version of JavaScript available at the time, was released all the way back in 1999, the next version (ES5) wouldn't come out until 2009. Strict mode didn't exist.
MSIE had an 80%+ market share, Firefox was hovering around 12%. 2006 was the year IE7 came out. Building a website meant you were targeting IE6 if you were lucky but had to worry about compatibility with IE5 (and also the completely different but identically named MacOS version of IE5) -- but in practice IE4 and Netscape 4 were still a concern.
You know the song "IE is being mean to me"[0]? That was first published in 2009.
Your comment is the equivalent of showing pride about "getting out of" automobiles in 1903, when Ford started working on the first mass-produced car.
JavaScript was used mostly for decorative purposes and AJAX where it improved experience.
As far as benefits to the users are concerned, why is today's web better? It's just a souped up Model T with bilboards on all sides, a 360 degree camera on top and more cameras on the inside.
But I get why it's awesome for front-end developers, they get to rewrite everything in the framework of the day every couple of years and they are handsomely paid. They get to invent new contraptions to keep up in the eternal race with native apps.
It does get a little annoying when someone points out that the emperor is naked, but otherwise life is good.
There's nostalgia and then there's outright denial. The reason you think the web was glorious in 2006 is that you forgot everything that was shit about it.
Want to know what made those shitty parts go away?
Modern JavaScript.
Flash was not shitty, it was quite good for writing apps, but it was proprietary and like a lot of contemporary tech it was (becoming) a security liability.
You're giving waaay too much credit to JS. Apple almost single-handedly buried Flash.
Absolutely there's a class of applications that wouldn't be possible with this approach, and I'm glad they exist. But it seems the "correct" answer to any problem to be solved on the web, no matter how straightforward, is to reach for React or a similar framework.
It used to be possible to escape; now it no longer is.
> Want to know what made those shitty parts go away?
> Modern JavaScript.
Modern JavaScript didn't make the shitty parts go away; modern JavaScript made the shitty parts universal.
It does more. Significantly more than "back in the day".
JS is nicer because it's a standard and it's supported everywhere.
"Besides this major technical difference, there is basically no major technical difference" :)
I was right there with you.
If you can find a way to retain your career and not have to worry, maybe it's not worth it.
But for me, I came precipitously close to having no marketable dev skills, by accident. I loved gamedev, and I spent my life learning it. It's what got me into programming.
Most cities don't have gamedev shops. And if you're not at a gamedev shop, you're not really a gamedev. Yeah you can try your hand at indie stuff, but that's roulette. Wanna be forced to move to whichever city has a studio? Be a gamedev.
So... Backing out of that career trajectory led to an uncomfortable realization: I'd amassed a bunch of low-level skills, had a deep understanding of Unix/C, and could implement https://lmax-exchange.github.io/disruptor/ without breaking a sweat. (Not merely use it; implement it.)
None of that translates into dollars. If you show up to a recruiter, they don't know what to do with you. There are literally hundreds of Rails gigs.
One interview went like this: They sat me down, opened up postgres, and said "Accomplish these goals." The goals were simple things like write SQL statements to query for certain types of users, or join data together.
I never had any reason to learn any of that. I knew that I could learn it if I needed to. I understood conceptually what joins are, why to use them, and what to avoid and why. The "why" is the crucial ingredient, and I naively thought that would protect me.
No... It's not fun when you have to sheepishly admit in front of three engineers that you have no idea how to write those SQL queries.
It was the same deal with Rails. Ditto for JS. Eventually I went through 5 interviews and struck out on all 5, in a row.
That's deep shit. When you start worrying about paying the rent, you're not in a happy position.
The way out of this mess, and not to end up in it, is to own it. Embrace all the shit. Become Elvis of code. Literally throw in the kitchen sink just because you haven't tried it out yet and this new kitchen sink might help you.
This story might not seem too relatable, and you might feel like your career is impervious. But a wise person once said that we overestimate the impact of years, and underestimate the impact of decades. "One decade" is so powerful that it's hard to overstate how much the world changes during that time frame. Are you absolutely certain you can get by without swimming in that pool that gives you the heebie jeebies?
Let go. Once you start swimming a few laps, it's not so bad. And in my case, I discovered I kinda like it. You're not supposed to like it, but it really is kinda fun. What other career would get to play with an endless box of legos?
I mean I think I understand why you chose JS, but we each make decisions that can take us on different paths.
I also do systems programming and have been doing C++ for most of my career. Instead of choosing JS I chose to invest in mobile and developed for iOS, Android and Nokia. Then I got back to system programming and will probably transition to software architecture.
I'm currently very interested in safety, security and reliability, which is basically the opposite of JS development culture. It seems to me that it's a big world development world out there.
I think that's actually worrying. While I'm not in the 'JS sucks; avoid at all cost' camp, I do find it a bit worrying that as I'm getting better as a developer, and as I'm getting more experience with non-JS ecosystems, I find myself avoiding it whenever possible. Even to the point of going for old-fashioned server-side apps just so I can use saner language ecosystem <x>.
I'm sure the loss of me will not affect the JS ecosystem much. But I'd be surprised if the same is not the case for many other, better developers. TJ Holowaychuck left for Go? Jose Valim moved on from Rails to Elixir (even to the point of creating it to solve problems he encountered with Rails).
I'm confident JS is important enough to keep a hold on many good devs, but I do hope we keep improving the ecosystem so that the really good developers stay on board to help improving it.
I agree 100%. If you're not infected you don't get it. Just like a healthy person may not understand the babbling of a delirious patient.
>I've been around the block. I vividly remember what this shit was like in 2008.
All the way back to 2008? Quite the block.
>JS works now.
JS doesn't 'work'. The language is still a mess. But the platform is beautiful. The runtime and compiler and the JIT are great. In the same way that NAT gave a ipv4 a lease on life, transpilation is what makes JS development tolerable.
When built-ins remain missing from the language, HN complains about JS being useless and "inverse NIH".
> All the way back to 2008? Quite the block.
I've used JavaScript in the 90s. Compared to today, 2008 was firmly in the stone ages.
No. Just no. There is a difference between 'bloat' and a sane syntax.
>I've used JavaScript in the 90s. Compared to today, 2008 was firmly in the stone ages.
I agree. It's not saying much but I agree. In the 90s JavaScript was useless.
And why I pretty much ignored JavaScript for the first 8-10 years of my career, now with much regret. I'm catching up though.
The benefit of hindsight...
But there are indeed still several module systems in use:
* globals (i.e. none)
* CommonJS
* AMD (just kidding, nobody uses this for new code)
* UMD (which mixes AMD, CommonJS and globals)
* SystemJS
* ES modules (via Webpack, browserify, whatever)
* ES modules in the browser (which behaves slightly differently)
That's 7 so I'll stop there. Yes, it's cheating a bit but of those I'd say AMD and UMD are the only ones that are dead as a doornail (for new code anyway -- plenty of libraries still use UMD for nostalgia). You'll only end up using one of them (or maybe two if you mix ES imports and CommonJS requires for some reason) but which one depends on which part of the ecosystem you end up with.
It seems that most of the community has adopted Webpack as the one true bundler for apps. Rollup is generally seen as better for libraries though.
Angular I think still promotes SystemJS, React is half-way between CommonJS and ES modules (via Webpack/Babel). I have no idea what Ember is doing.
If you want to add type safety, Angular strongly favors TypeScript while React is slanted towards Flow for obvious reasons.
The JS ecosystem is complex. Even if you cut out all the nostalgic stacks (MVC with Backbone and jQuery is still cool, right kids?) there are still many paths to pick from.
But I agree with your final conclusion: the reason the JS ecosystem is so complex is that it has changed a lot over the years and has seen massive improvement while still maintaining backwards compatibility at a language level with tons of legacy code that's still out there and still running in production.
Lulz, our Oracle-owned ERP system chose AMD for its module system less than two years ago. All new code will use AMD here for, I expect, the next decade.
Does that work yet? Last I heard, tree shaking was completely broken...[0]
I remember what shit was like in 1998, which is why I get the same sort of aggressive reflex anytime someone is criticising Rails.
Back then, a web project could, and this is only slightly hyperbolic, include a file ```/project/htdocs/version-2.0-old/real/includes/templates/config.passwords.production.INC.php3~```
...and that file would start with ```<table>``` and, somewhere, include the SQL to delete a user.
That was the state of our industry when Rails was released. Which is why anybody who went through that transition weeps whenever people today regurgitate this bullshit about "magic" and "OOP considered harmful". Maybe functional programming is incrementally better. Maybe Rails is past its prime. But on a purely emotional basis, I feel defensive when some article doesn't start with a paragraph praising the genius of DHH before offering its criticism.
Yes, the state of the web in 1998 was as you describe, but by 2005-2006 there was an explosion of MVC web frameworks in many different languages, of which Rails was just one.
However, Rails is what really launched the "MVC renaissance." Because of it, soon Java, C# and many other languages moved to predominantly MVC cultures.
I wasn’t familiar with ActionCable, Asset Pipeline or CoffeeScript but felt they were all easy enough. All the basics were still there, the MVC application structure, DB migrations, etc.
I share the sentiment that JavaScript and many other languages used for web development are great but seriously lack some of the essentials Rails provides.
The essentials haven’t really changed so jumping in at 0.14.5 or 5.0.1 shouldn’t really matter.
Come on...
I’ve experimented with most of the alternative frameworks and micro-frameworks. I have a real fondness for Sinatra. I’m happy most modern languages have their own Sinatra but I’m sad that most modern languages lack their own Rails.
Ha so on the name, I’m transparent at least. I’m no longer a programmer but am a business customer for teams building on JavaScript. I think they have much opportunity and suffer from lack of convention in their day to day work.
That was about a year ago, and these days my biggest challenge is identifying and filling knowledge gaps. For instance: the mere fact that ActiveJob exists isn't obvious.
I think if you're new to most server side languages and javascript SPA's are your wheelhouse your experience will be very foreign and dogmatic feeling. I switch between the two worlds often and am still amazed at how productive I am in ruby/rails.
Erb / vanilla js is still the default stack for beginners. But they've started to move away from the asset pipeline and they've built in webpack.
It's such a non-issue.
In fact, what's impressive is how Sprockets (part of Rails asset compilation) can chain together arbitrary file transformations by looking at the extension. `file.coffee.erb.whatever` will get processed as with the tool configured for `.whatever` files, then it'll eval Erb's <%= ... %> tags, and then finally get processed as Coffeescript before being concat into the bundle.
I always thought that it was a really intuitive way to specify transformations.
But the thing is that you need Rails experience to appreciate a solution like that, and it's easier to write off Rails entirely because someone says that it depends on Coffeescript. In reality, Rails just shipped with the Coffeescript handler so that Sprockets could understand .coffee extensions if you chose to write .coffee files.
Technology-hate only serves to confuse beginners by making them think everything is black and white. And by making them think that they are making a mistake by learning one ecosystem over another when in reality everything has trade-offs and it's better to learn something over wallowing in the paralysis of indecision.
Half of these comments aren't even capable of comparing Javascript to Ruby without bringing up Webpack and the complexity of client-side bundling as if Ruby is a client-side language.
Still quite easy to pull out.
Psyched to see Rails adding native webpack support though.
If you fight it, you are in a world of pain and that's even much worse if you don't the design choices they have made in Rails.
Having said that, if you jump into Rails the whole project structure will start to make sense after a while.
I completely agree on your impression of Ruby vs Rails.
Eg for "Hello World", you're not going to touch 99.9% of the auto-generated code. But you need to know where to look.
That said, could you perhaps elaborate on how studying the innards of PostgreSQL is relevant in relation to ActiveRecord?
Rails absolutely is a framework where you need to abandon some control and trust the framework though. If you need to know exactly how your abstractions work under the hood, it's a poor choice IMO. I doubt there a single person who has comprehensive knowledge of how every single part of Rails works.
SQL is really not going away anytime soon (it's demise has been falsely predicted many many times). It even fits the current language hype in that it's functional!
I love AR, but there are use cases where you just need to create or optimize your queries manually.
Ok, that could be the reason why you don't like Rails :)
Regarding postgres, its innards become relevant when you have partitioned tables with billions of rows and need to run queries on them for analytics purposes. In these cases you often need to manually create some complex queries from scratch; other times, you can use ActiveRecord "magic" up to a point, but then you either need to add special indexes (eg partial indexes, that saved my ass many times), or you need to replace the automatically-generated queries that ActiveRecord uses and which are good for small numbers, but become a bottleneck when scaling.
I agree that a lot of people don't make the distinction between rails and ruby. I had interns who where quite surprised you could use ruby without rails, and that "it's actually a complete language!". Ruby on its own is charming indeed. Rails gets the job done: few other tools enable you to finish a functional MVP in a day or two. But if you start to add gems for everything it just becomes a pain in the ass.
edit: I was f*cking mad when they added coffeescript. fortunately it's simple to disable (just removing the gem and changing a setting for the file generators)
Any framework seems "Crazy" and "Magical" at first. But once you get to know it, it becomes clear.
Rails is an opinionated, full featured framework with plenty of bells and whistles.
The core of rails is convention over configuration which means you will have a hard time going against the it.
Rails is like a culture. There are a lot of pre-baked things when you run "rails new blurb", but most of it is useful, and you'd create them anyways. But to a newcomer like me, that's a bit overwhelming. That's my lament about it. Wrt Node.js, that's just a product of lots of ignorance. All you actually need is a JS file, or a makefile with ".js.ps:\n\tpuppyscript -c $< > $@". But the wheel is reinvented with such pace and redundancy that it's a hell of a platform nowadays. Even its creator, which is a very smart guy, has said farewell.
Why is that a number you care about? Is it causing you actual problems during development, or are you just offended that it's a big number?
(Dependency bloat can be a real thing, sure. But if I have to choose between adding a dependency on a solid, well-built module and spending the time to reinvent the same complex wheel all by myself, I'm going to pick the option that gets me more quickly to done, 100% of the time. I'm paid to bring business value, and while minimizing technical debt where it counts is a big part of that, spending unbounded time to satisfy my own peculiar notion of software perfectibility is most emphatically not.)
Doing this bare minimum of due diligence is easy if you have 10 dependencies, but quite costly for a 1000.
The number is misleading anyway, because many "packaged" libraries that you would normally look at as a single module are split into individual modules for perf reasons.
Consider the destructiveness of someone malicious befriending the left-pad developer, taking the project over, and doing a malicious push.
I'd say the scale of the potential destruction in so many tiny, few-eyeballed modules is unique to the npm ecosystem for better or worse.
It's one of the security downsides of the ecosystem especially in the online casino space where I work. For example, getting an online casino's `npm ls` (full depth) would be a good place to start.
The scale of transitive deps we're talking about when compared to any other ecosystem is quite excessive, but also just how tiny many of those deps are.
Not different from someone befriending a corporate employee and asking them to insert some malicious code into the codebase. You still rely on a web of trust - in the company's case, the code reviewers, in the open source example, the maintainers of the libraries that use left-pad. I don't think this argument really holds, I don't know what you're comparing it against that's different.
Even the smallest transitive dependency in our largest dependency graph in the Java ecosystem isn't someone's 6-liner afternoon project.
I think the ease of publishing + ecosystem of small modules is a good thing, it just has what we consider an ecosystem-level security trade-off that matters for some applications.
I find it also funny that JS is at the top of the discussion about of article about ruby.
Many readers will be web developers. The biggest and most lucrative alternative to Ruby in that space is JavaScript.
Therefore: lucaspiller decided to remind people that switching to JS is not a good solution to Ruby's problems.
I wonder about this. C#, Java, Python, PHP, hell, even Scala are all viable options.
JavaScript is a beautiful platform and an atrocious language. I do not understand how anybody can tolerate it if they are coming from any other sanely designed language.
Transpilation is what makes JavaScript tolerable. Did I ever mention I love Dart? Because I love Dart.
>With JavaScript, once you move past the basic TodoMVC examples you are pretty much on your own
Yes! Those TodoMVC examples are great! Now write 100,000 lines of code and tell me you don't want to tear your hair out.
>I think there are now 7 different ways of just defining a module.
Thank you! I don't know what the hell is wrong with the community. There is no correct language enforced module system, so everyone rolls their own. It's a mess and nobody seems to care ... probably because if you'e doing that kind of development you simply transpile from a sane language and you side-step JavaScript ugliness.
>The stdlib of Ruby is pretty sensible. JavaScript has many inconsistencies
Yeah. Best not to dwell on it. It is the way it is because of legacy reasons.
>The JavaScript community seems to have the opposite of NIH syndrome
I would say that the JavaScript community is paradoxically suffering from NIH _and_ IH. You roll a lot things in-house and you also add dependencies on 'modules' with single-use functions. The community is really strange. I think its quirkiness is due to being dominated by young kids who have no experience with anything other than JavaScript, so they don't know what they don't know and they don't demand better. The rest of the people simply side-step JavaScript and use TypeScript (or Dart a criminally underrated language).
I personally ran out of reasons to prefer another dynamically-typed language over Javascript on the server. In fact, with ESLint, I'd say Javascript has some of the best static tooling among them before you even get to Typescript.
With async-everything, promises, and async/await, I think Javascript is one of the nicest dynamically-typed languages.
I don't like node.js, but I occasionally use Typescript like a more powerful C#.
C#'s type system is usually better except from the times that I feel creative. Works perfectly for large codebases with many changes. Not fun for side-projects.
Sadly, I'll probably never have a stretch of time to re-learn the C necessary to build one.
I also miss being able to eval code in my buffer while writing Clojure against the same process my server is running in.
Server-side Javascript has the perk of being able to use Chrome's debugger UI. I personally haven't used it much though.
It's interesting how much your core feedback loop / workflow can change between ecosystems. Pry is definitely a highlight of the Ruby ecosystem. The craftsmanship there alone is inspiring.
1) It requires another window to be open, which requires screen real estate. I don't always have an external monitor attached.
2) Navigating around requires clicking buttons with a mouse. These buttons are quite small, so Fitts' law dictates that it takes longer to navigate. It is much faster to be able type "next", "c", or "up 3" in the same text box that the output appears than to have to keep moving the mouse back and forth between buttons and the console.
3) Because of point #1, it is harder to get as much space for the output of running some javascript.
4) It takes longer to make the connection happen and (at least in the past) has been unreliable. This is a significant annoyance if starting and closing a debugger window frequently, as one might do if trying to navigate to a breakpoint in a particular test case.
Larger teams have different requirements.
Following a GET request through a web server usually just involves some middleware, a dozen lines of route handler, a dozen lines of database queries or service calls, maybe an html template, and you're done.
This is a big problem that's addressed quite rarely. There's very few open JS codebases that cover the sorts of concerns most web developers face. There are open codebases for build tools, codebases for graphics editors and web frameworks, but few relevant to writing a typical frontend app and frankly few that are well written.
As a JavaScript developer myself I often wonder if there'd be demand for a 'boring webapp' open codebase, something that could showcase perhaps two or three different ways of writing garden-variety JS applications.
I tend to like to hear about people switching languages that also cross paradigms, OO to Actor, Actor to FP, etc..
I would be sick of that, too.
I'm also sick of criticism on Ruby when you actually want to criticize Rails. There is a significant overlap in the two communities of course, but both have a distinct profile and you can't just lump them together.
In this case, it's also not helping that they have to stay on an ancient Rails version. With Rails, it's a much smoother experience if you can follow the major releases but especially the upgrade to Rails 3 was a painful one.
Edit: I don't want to imply that you shouldn't criticize Ruby but if you do, don't confuse issues of Rails with those of Ruby. Rails and Ruby code do have quite a different feel to them. It goes this far that when I write a clever little Ruby snippet in a Rails app, I almost feel dirty as it doesn't belong in there.
What I find fascinating is that when I read more recent articles/books, the approach is much more functional in nature, with the OO part sometimes seeming little more than namespacing (Sandy Metz, for example).
I do think Rails, for all the good stuff it did, promotes 'bad' use of Ruby. But even 'idiomatic Ruby', based on the books-you-should-read suffers from similar problems.
It's all fun and exciting to write Ruby code, but if I hadn't been subjected to the 'avoid too much inheritance' and 'write your OO code in a hybrid OO-and-functional way', my output would've suffered from the same issues Rails code does.
That's not to say that I dislike Ruby. I love Ruby. But it doesn't strike me as a good thing that maintainable Ruby code means avoiding a lot of the cool stuff.
Ruby is in that regard a lot like C or Perl. It gives you lots of power and options to solve a problem your way but that doesn't mean you should always do so. Rails has used those options extensively and that explains a lot of the criticism you hear about it.
This also means Ruby is not for everybody but what language is? IMO you can write unmaintainable code in any language and there is none that makes that hard enough, so I'm firmly in the camp that I'd rather have the full power at my fingertips when I need it than being restricted.
Although with the renaissance of functional programming, I would also love to discover a functional language that felt as fresh, powerful, and elegant as Ruby was for OO programming.
Elixir?
I had 2 coworkers that were fanboying over it, so I already got some opinions but I haven't had time to look into it seriously.
But the key there is that the meta-programming involved is very, very limited for a very high payback. As it is, it raises the barrier for new hires, and we want to make sure not to raise it higher.
And most of the rest of the code is taking an increasingly functional approach.
I tend to think there is "too much magic" in a lot of Ruby projects, so I try to be very careful and limit it to places were it so drastically cuts down on the amount of code that we can justify quite a lot of explanation and still come out far ahead. But when everything lines up, the benefits can be dramatic.
Sure there have been changes in both Ruby and Rails since then, but nothing like maintaining javascript.
Honestly, I think part of maturing into a senior software engineer (and later, a good manager) is accepting that while things aren't perfect, they're plenty good enough to solve your problems and make money.
I'm not saying there aren't occasionally valid complaints, and sometimes these new tools (Docker, et al) are really good, but the sorts of developers I'm describing here always think the grass is greener when it's programmed in another language. No, of course they aren't factoring in the months it takes to convert over for a 1% productivity "boost". All this grumbling does is hasten your language and tools dropping out of fashion and never improving.
If you want things to get better, contribute to your language and its tooling. If you don't, just switch out and use something else. Can we skip the swan song each time you decide something isn't good enough for you?
At some point (and if the codebase is not that good to begin with) one might conclude that the language is being hostile. A bit excessive maybe, but understandable.
It's the maintenance that's driving this guy nuts, not the language itself. Haskel just happens to be his side project, which will, of course, look cleaner. I felt the exact same way when moving from Perl to Python.
> It’s hard to reason about code when it does something entirely different depending on what code has executed in the runtime before it.
> What we really need are more explicit guarantees on every line of code that we write [...] than what Ruby can provide
Maintenance has a cost on any language, but in some cases you also have to make up for the lack of guarantees the platform gives you. Tooling, as you said, can help, but substantial effort is required to develop and mantain, say, a (production-grade) static type checker. You can't just tell $random_ruby_dev to "help improve tooling" if there is no tooling to begin with.
I don't think this at all. I think part of maturing into a senior dev is having the experience to know what makes you happy, what makes you unhappy, and still make money.
For many the journey matters, and for the more passionate, "good enough" is a give-up mentality. And it's a good thing you don't have to keep these thoughts to yourself...you should feel free to share.
Maturity as a programmer means being able to identify and do what it takes to get things done. Whether a developer is "happy", or "passionate" only begins to matter when they're doing what needs being done.
A true sign of maturity is when a programmer is faced with a workload that they are deeply unhappy about, but still get it done, because it needs to be done. The corresponding sign of mature leadership is acknowledging that developer's unhappiness and giving them extra money, work they enjoy, and/or time off after the crap work is done.
That some programmers truly enjoy their work is a gift that they are lucky to have; not a sign of maturity.
Then I quit my job. As a quality senior you have the leverage to pick where and how you work. Otherwise, you may be thinking of just a tenured junior or someone who was given a title of "senior". This is why I said earlier "part of maturing into a senior dev is having the experience to know what makes you happy"...not just doing what someone tells you.
If it means "no, we can't change that method with a 200+ cyclomatic complexity because the NY office wrote it and they would be upset about it" then yeah, that would suck. (Real story in a recent contract with a bank.)
I’d like to pause the ruby discussion here to point out this is a deeply unhealthy viewpoint—it’s your own funeral if you knowingly go to a job that makes you “deeply unhappy” every day. That’s not maturity, that’s self harm. Maturity is responsibility, including to yourself.
Leaving if management is not mature is a perfectly reasonable thing to do; but not doing the work you've been given before you leave is irresponsible at best, petulant at worst.
A personal anecdote: I've been pushed into QA for several, because we needed it to be done, and I had the prior experience. I hate doing QA work. After the crunch was done, I took a break, then went back to work I wanted to be doing. And yes, perhaps this denotes a lack of hubris, but I consider that to be mark of maturity as an employee in me, and in my manager.
Personally I would never work with other peoples rails again without seeing the code before hand. Rails outfits pay nowhere near enough to deal with method_missing and rails magic.
Adopting something like Haskell instead of Ruby isn't just an exercise for magpies who like new shiny things (In fact, Haskell is older than Ruby, and many concepts in functional programming are far older than most OO design patterns). It's embracing a different way to think about programming which can have fundamental improvements to the maintainability of the code you write, rather than just cursory ones.
No one is saying that a business problem can't be solved, or money can't be made, using Ruby.
Sure, rewriting a project from one language to another is very expensive and usually not worth it, but does that mean that we shouldn't explore other tools at all? At some point, a new project will begin, and it'll be valuable to have a more robust decision about which tools to use than just "Rails worked ok for us last time."
That is to say, picking products mature enough for production use, and executing your migration without feeling the need to justify it to the world by shitting all over your old environment.
Age has little to do with it. FWIW, Haskell is trendy right now. Probably for good reason. My issue isn't with the direction, it's the method.
With time, you will see the problems with the new language/tool/environment. Is it better than what you had before? Maybe, maybe not. But you are not in a position to accurately evaluate it while you're in the honeymoon phase.
Without this "bitching about their and others' programming environments" we'd still be using punch cards. The author indeed does not contribute anything "new", but it's still pretty well written and to readers who are at a similar stage in their education/maturing in a more modern time it does a pretty great job of introducing concepts the typical ruby-only developer might not be familiar with.
I could have written a very similar article 15 years ago from a perspective of a black belt perl developer who found lisp to realize that his code already was lisp. Just in perl. Would it help a 25 year old other version of me today? No. Because he'd probably be proficient in ruby and not in perl. Nobody under 35 understands rants about lwp or Moose anymore and thus does not even have a chance of getting the point without lengthy research.
I’ve personally built rails app that have been running for the last 5 years with clients using it to process millions of USD and I rarely have to touch it. And even now when I have to make changes it’s easy to fix and patch up because it was built right.
Most founders who don’t understand development “need things done yesterday”. If your business doesn’t take into account technical debt you are going to skimp on things and cut corners. It’s not ruby’s fault. It’s the business owners job to understand development and the process of building risilient long lasting software and not put developers into impossible timeframes.
From my experience business and marketing people who “need it now” don’t know what they are doing business wise too. Businesses take years to build. Nothing is ever needed “right now” if business is well planned and well executed. There is always enough time, and if there really isn’t technical debt is accounted for and fixed quickly.
That said it’s also important that technical leadership constantly inform and communicate with business end regarding development time and the concept of technical debt.
Don’t even get me started on business people who “need it now” based on “projections”, and then forget about everything they asked for the next day. Or “I need it now” “make it happen” to stroke their ego.
When you find yourself blaming the tool look at yourself as an individual and look at your team.
JS achieved popularity because it was the ONLY choice in its domain. That's a rarity in PLs, and can't be extrapolated to any other language that I can think of offhand.
Linguistically, my second choice would be Scheme, but I still find JavaScript to be more ergonomic for most tasks.
It's also way more familiar to more people, obviously, so I think it's a totally reasonable choice for a lot of tasks.
The big problem with Javascript is that conceptually it's closer to a functional language than C or Java, yet it opted for a C-style syntax with a bunch of hacks (semicolon insertion being arguably the biggest) so I find that its syntax doesn't really match the way it's used and you end up with rather clumsy looking code even for very idiomatic constructs. Not to mention the super weird type conversions.
But that's rather subjective, IMO the biggest problem is simply the lack of a comprehensive standard library even for basic things. I'm not really a webdev but I have to maintain a web interface for one of our products, it uses JQuery, underscore.js and d3.js for various things. There's a significant overlap between these libraries when it comes to standards algorithms and DOM manipulation so you have to learn two or three ways to do the same thing depending on the situation. I shouldn't need external dependencies to have access to underscore.js's "map" or JQuery selectors.
Coding in JS feels like coding in C if it was standardized without stdio.h and string.h. Have fun re-implementing strcat every time you need it.
Been a while since you did need. document.querySelector and .querySelectorAll are everything about jQuery that's worth having, and every browser has implemented them for years. Arrays have a map method that does what you expect it should, although do be aware of the odd calling convention. Objects don't map natively, but their keys do, which I very rarely find fails to suffice. (And for those things that really can't be expressed in stdlib without considerable reinvention, Lodash is a strictly better Underscore.)
I maintain my point though, so far most sizeable JS projects I've seen depend on JQuery for one reason or an other, so clearly even competent JS coders feel the need to supplement the functionality of the standard library. As for the built in map, the fact that you can't use it on objects is the reason I ended up requiring underscore.js (alongside with the .find and .uniq methods, and probably a few others).
I could also have mentioned how hacky and messy it becomes if you decide to split your JS project in multiple files. Or the hack to create "modules", which is at the same time very clever and pretty terrifying.
Client-side applications have baggage (infinite deploy targets) that you don't have with server-side applications (one deploy target), so the comparison is disingenuous.
If Javascript had stopped being a thing in browsers do you really think Node.js would've gained significant traction despite the numerous alternatives?
As far as I can tell the main selling point of Node is that you can use the same technology on both ends and even share some code. If you remove this from consideration then Node competes against Python, Ruby, Perl, PHP... And it's not clear how it's better than these.
BTW, the main selling point of Node over those languages was that the runtime was faster and more capable at multiplexing I/O in server code.
> Coding in JS feels like coding in C if it was standardized without stdio.h and string.h. Have fun re-implementing strcat every time you need it.
That's a really bad example, stdio.h and string.h are notoriously horrible. Should I use strcpy? That can cause buffer overflows. Maybe I should use strncpy then? Oops, that's a buffer copy function, not a string function(it can result in non-strings)[1]. What about strcat and strncat? Well, strncat actually appends a null character, so you have to keep that in mind. How do I even use gets, getchar, fscanf properly? Here's a compilation of coding standards and pitfalls, many of which involve the standard library https://www.securecoding.cert.org/confluence/display/c/SEI+C...
It's got map, filter, reduce, just like all modern browsers, and it's also got nice and easy builtins for JSON parsing/dumping, HTTP serving, regular expressions, etc.
And still the stdlib isn't bloated with lots of weird stuff, it's kind of nicely minimal. Not perfect at all, but in a pragmatic sense it's often very satisfactory.
My real favorite language is Haskell, and that language is also both loved and hated, and one of the problems with it is the standard library. There's no regexps, no HTTP serving, no JSON, hell, people even import external dependencies to get convenient records.
I'm kind of cynical and picky but tell me a language and I will give you a litany of horrible problems with it—really.
Go's type system is stupid; Rust's compiler is slow and it's hard to learn; C is unsafe and has undefined behavior; C++ is a mess; Ruby is full of monkey patching; OCaml's syntax is idiosyncratic; Haskell has problems with laziness, records, the proliferation of language extension, an "im very smart" community, etc; Smalltalk is Unix-hostile and insular; Common Lisp is too mutable; Scheme is too fragmented; and so on and so on and so on.
So I think of choosing a programming language as answering the question "Which horrible nightmare seems least awful for the particular thing I want to do right now?" and JavaScript is, for me, quite often a reasonable answer.
Is this the order you learned programming languages in or something?
"Well, it depends on if you mean SRFI-44 maps, SRFI-69 hash tables, R6RS hash tables, Racket hash tables, MIT hash tables, Scheme-48 hash tables, or . . ."
- UNIX and C.
- Android and Java
- Windows and .NET/C++
- JME feature phones
- iOS and Objective-C/Swift
Or to taking it down to memory lane,
- Burroughs and ESPOL/NEWP
- IBM RISC systems, IBM zOS and PL/8
- IBM 400 and PL/S
- Lilith and Modula-2
- Native Oberon and Oberon
- UCSD and Pascal
- Lisa, Mac OS and Object Pascal
- Lisp Machines
- Smalltalk workstations
- Xerox Star and Mesa
- SpinOS and Modula-3
- .... (plenty more to list)
The alternatives to the languages I listed, don't enjoy the same support to 100% of plaform APIs, and respective SDK tooling.
Going outside the eco-system means manually writting FFI bindings, not being able to use the GUI designers if available, lack of debugging and profiling support at the same level as the platform tools.
Not true. .NET is VB, C#, which are completely different from C++, and you can write a Windows application in almost any language imaginable.
Sure you can write a Windows application in anything else, but be prepared for a 2nd class experience, writing FFI bindings on your own for the Windows API, without access to the tools provided by Visual Studio.
JS has its own problems, but Ruby makes it extra easy to shoot yourself in the foot
My time is pretty much 50% Ruby, 50% JavaScript. "stdlib can be patched to do random stuff" is a complaint I've often heard about Ruby, but in practice, I've encountered it precisely once in the last five years (extlib breaking with recent Ruby because of a to_h conflict, IIRC). I've lost way, way more time than that to JS idiosyncrasies.
We've had something like 20 of those in the last year alone. 70% of those come from Rails, and some have been quite severe. Maybe it's tied to what we do which is definitely not a simple app, for which Ruby is not entirely the right one for the job but it's definitely not obviously the wrong one either. With years of business logic, tuning and bug fixing there are things you should never do[0], but even coming to terms with what Ruby is and what its limitations are after all these years in the trenches doesn't mean we can with absolute certainty avoid getting hit by structural damage coming from idiomatic flaws which we have clearly identified through proper root cause analysis to be endemic to the Ruby way (which includes a complete disregard for backwards compatibility, even when it can trivially be made so[1]).
[0]: https://www.joelonsoftware.com/2000/04/06/things-you-should-...
There's perhaps an argument for "Ruby - the Good Parts"... but you could argue that it exists and it's called Crystal.
Avoid Rails and Ruby becomes a far more pleasant place. Certainly not flawless, but you avoid a lot of the pain.
> Math.abs(-1)
1
> Math.abs = function(x) {return x + 1}
> Math.abs(-1)
0It's the ONLY language on the web. If there were alternatives with a useful standard library and a way to define functions and objects that programmers of other languages are used to then the alternative would be more popular.
One of the struggles that the writer seems to have is that programming applications is not science, but he seems to think it is. DHH has a great keynote on this phenomenon: "Writing Software by David Heinemeier Hansson"
https://www.youtube.com/watch?v=9LfmrkyP81M
As mentioned in the comments of the article you will run into issues with any programming language. One of the tricks is to not hold on so tightly to 'rules'. Like (take from the article) 'break functionality into lots of small objects'. This is horrible advice if applied to all situations. You should only do this when it makes sense. I see so many programmers breaking up everything in useless classes and methods/functions/whatever just because someone wrote a blog post about doing so. This just makes complicated code look simple at a glance, but when you want to find out what the code really does you have to jump up and down through files looking at what each function does, you have to open split screens between abstract classes that have some dedicated piece of code in a class that had to exist in order to satisfy the 'break things up' rule, etc.
Long story short: just relax, write code (in whatever language you like, for whatever reason), go home and enjoy your family, friends and hobbies.
Much as my dislike of JS grows as I venture further into other programming ecosystems, I still love the ability to muck about with any web page I come across. I love being able to use the Chrome/Firefox devtools for debugging, and haven't found anything quite as nice outside of the browser. I love being able to package a bunch of js and a minimal html file, and just dump it anywhere that provides basic hosting.
It only barely offsets the many problems I have with JS, but because my day-job is mostly front-end, I need to deal with these problems anyways.
But man I'm looking forward to a situation where I could use <preferred language> as a drop-in replacement for javascript.
Want to muck around with websites with JS: https://bookmarkify.it/ (Disclaimer: shameless self-promotion on my part)
Also, I am not against Javascript at all. I just don't understand the role it has been given on the back-end. There are better languages and on the other hand I don't agree with the amount of engineering that goes into front-end applications that are built in things like React. It seems silly to me to rebuild standard functionality of your browser in a framework in order to gain some interactivity that was already there to begin with through plain-old-javascript. Rather than invest all that time and effort into React, Redux, Redux-sagas, Ember, Vue, etc, etc, etc (there are a whole bunch of etc) people would have spent their time a lot more productively if they'd help out with making web components happen properly.
Ruby's slowness is often mentioned, but Ruby is quick enough for many situations. I am very productive in Ruby and servers are cheaper than developers so for many purposes it works out just fine. I have tried Phoenix (Elixir) and I found it too verbose and complex to work with. I am sure though that others love it, so to each his own.
Thank you
I've seen people create classes containing only a string or a list/array of other (existing) objects, it's not even funny anymore.
I get why people would like to pretend that everything is made up of beautiful uncomplicated small pieces, but that is not how life works. At some point you have to understand your tax returns, mortgage contracts and communications with incoherent external APIs. Making me jump to section 4.1.2 and from there to section 7.2 in order to understand the parties mentioned under 1.1a are subject to the rules set out in Appendix A section 42.1 does not make the contract easier to understand. So why would code that feels like a legal document be easier to understand?
That can be a good way to improve type-checking in code that would otherwise pass around bare strings. It reduces the chances that e.g. a plain text string is confused with an HTML string.
If your language supports it, an opaque type alias would be more explicit:
But that's in specific cases, not all cases
And yet I never see people getting sick of functional programming after a few years. People either try it and dislike it immediately, or they switch and don't go back.
There really are better and worse languages, better and worse ways to write software.
Since its early days, I was hopping for it to gain AOT/JIT compilation support, eventually by getting some inspiration from Dylan.
RubyMotion seemed to be it, but because it is commercial product, it is largely ignored by the community.
The JRuby work is awesome, then again some in the Ruby community suffer from Java allergy and won't touch it.
Now we have Crystal as the best way to get a bit of both worlds, AOT and Ruby like syntax, but still alpha quality.
Ruby is the only programming language I've ever used where I didn't feel like I was fighting it, or struggling to express what I wanted. It was easy to express complex behaviours and data structures without reams or syntactic or structural noise.
But yes – despite that, there was a lot of shoddy and poorly performing code out there. The ecosystem never saw the kind of massive investment that JS (for example) did, so performance was always lacklustre, and I'd particularly love optional typing.
Still, there are other options now for specific use-cases, which is good.
I'd take a smoke test and some high-level functionality test before the over-testing preached by the TDD "gurus" or any crap spouted by uncle bob. 100% code coverage is a myth, your code still can fail spectacularly with a good code coverage and guess what, most of the software in production today was not TDD'd let alone unit tested.
People sell TDD like a OCD inducing religion instead of something that might be a good idea in some specific cases
Magic is extremely useful in the right place (e.g. building ORM or admin frameworks) - these can save you from writing a ridiculous amount of code.
Unfortunately since it's an 'advanced' feature lots of programmers want to shove it in places where it not only isn't necessary, but is actively harmful.
Python has all the same features and allows you to write code that is equally horrible (or powerful), but it benefits from a cultural bias in favor of simplicity.
That said, I've still seen unnecessary magic code written by people looking to prove that they are no longer "intermediate developers".
>People sell TDD like a OCD inducing religion instead of something that might be a good idea in some specific cases
I think TDD with integration testing works in almost all cases, but unit tests fail or work poorly in about 85% of cases. Unfortunately, unit test driven development is what the zealots preach.
Totally agree. Python does it in a more explicit way, so that you know "Here be Dragons" (in this object, that was defined in that specific place)
It's not like a piece of casual code in any module can turn your world upside down.
It's not a cultural bias. It's a critical difference in the language designs.
In python, monkeypatching is scoped to a module.
In Ruby, monkeypatching is global to the execution environment.
So in Python, you can look at the source code for a module in isolation and deterministically reason about what it does.
In Ruby, you can't. Because you can't know what the execution environment will be.
IMO, it's the main reason why Ruby projects become harder to manage as they grow. Somewhere, someone is monkeypatching, and reasoning about the code becomes harder and less local. I spent 2 years with Ruby and will never use it again if I can help it.
- Patching a library for testing purposes
- Fixing a bug in some library you can't change
Imagine you need to know what time it is, and you're offered two options to find out.
One is to recite an incantation, a magic word, and the current time will appear in the air in front of you.
The other option you are offered is a clock or a watch. With this option, anytime you need to know the time you can simply look at the clock face and simply and immediately know, but when peeling back the surface, you can see an intricate set of gears all working together to keep track of the time.
On the surface, both of these options are equally easy to use and useful to find out the current time, but the clock will be far more fixable and extensible.
IMO we should strive to make our frameworks "mechanical" like the clock rather than magical.
'Missing' brackets are merely a syntactic choice, though I will grant you that variable case is quite weird (though in that sense, I suppose Go is magical too :))
This is all true about Ruby: the things that make it feel so powerful come at a big cost. But of course what the best solution is depends on what you are trying to achieve.
I'm curious if the author pursued learning Haskell and what he thinks of it now. Side effects are inevitable in any non-trivial application that interacts with the real world. They may only happen outside the runtime, but Haskell's design makes allowances for the perfection of its type system when it comes to interacting with other systems. Ultimately, the extent and impact of side effects have everything to do with the design of the program, and your compiler won't save a poor design. The true test of the design is years of real use and evolution and maintenance, and so I'd love to hear from people maintaining a huge years-old Haskell codebase how it compares to other languages.
Having said that, now I predominantly use Phoenix/Elixir for most new projects. And the framework is moving ahead blazing fast. It has its own pros and cons, but overall, it's been a VERY positive experience and it actually saves me a LOT of time because I'm able to find code errors at compile time.
It's almost the only alternative to Rails which seems like home if you're transitioning, but it still has its own issues. For example, they screwed up the code organization with contexts, renamed the web folder a couple of times and so on. But these are small issues and I'm amazed at the productivity I gained by using Phoenix.
I wrote a full fledged Stripe API library in under 12 hours. Well tested and rock solid. Pattern matching is heaven and in many ways, your code is more robust. I have written libraries in Ruby too, they take more time simply because there are lot more tests that need to be written.
I would never go as far as saying "I'm sick of Ruby", simply because it's still a great programming language, if you're getting started and also because, I believe in the man behind it - Matz. He has a philosophy and believes in it. It takes enormous passion and dedication to believe in what you've created, support it over decade(s) and keep on improving it. I can point you many languages that have died over the years because they lacked this passion and dedication.
Same thing goes for DHH as well. I really applaud him for patiently tolerating so many people bashing the framework he helped to create that revolutionized web development. He's also very very chill and respectful about others' opinions. [1]
Having said all this, I hope Ruby 3.0 has a strong come back which is much needed at the moment.
[1] https://www.quora.com/What-do-you-think-of-Elixir-and-Phoeni...
Just to add a bit of information to this, they were all in RC or pre-releases. I was bitten by this myself, but if you choose to run RC code then you need to own that a little bit.
Like AOLServer, Vignette and our very own at the startup I was working on during the first .com wave.
The big deal was that many developers weren't aware of such stacks.
You would declare an "entity" type and all CRUD operations would be automatically generated for Informix, MS SQL Server, Sybase SQL Server, Oracle and DB 2.
With the possibility of extending with extra queries that look like entity methods.
[edit]
Oh right, your in-house solution. Well congrats on having it figured out in 1999.
Digging a bit on past memories,
I don't know Elixir.
How do you do that? Do you use Dialyzer?
Few would dispute that Ruby is a great language for getting things done with small, expressive code. And Rails, which is what probably brought most of us to Ruby, was at its time the ideal web framework. It was able to be generations ahead of most other frameworks because of the capabilities Ruby afforded it.
However, time moves on, versions of the language, framework, and gems change. Projects grow and evolve. These are where the pains really begin. But this is not really so much about the language but about real world project lifecycles.
For me, the first real pain was performance. At some point, you cross a threshold where the performance goes from reasonably ok to WTF is happening?. Then you start profiling and discover that the wonderful collection and ORM operations you've been doing are extremely expensive. That's when it stops being fun.
Then, if you explore other languages, you may discover the absolute joy of Clojure (once you devote the time to think functional and appreciate Lispy syntax). Plus you get a big performance boost (as well as access to tons of Java libraries that are usually very performant). But alas, then you discover that there's no real Rails equivalent for Clojure. (I now understand that there are great options if you're willing to cobble your own together.)
Finally, you might hear of Elixir + Phoenix. Suddenly (again, if you're willing to learn and think functionally), you find joy. Performance is much better than Ruby, the Phoenix framework feels Railsy, and you get the benefit of the industrial Erlang VM underneath it. The downside, however, is that Elixir and Phoenix are young. Fortunately the community is friendly and helpful.
For me, it's not that Ruby is bad; it's just that I now realize how much better functional programming is for me personally. And when I just need something quick and dirty, Python is already installed. Ruby is like an ex-girl(or boy)friend that you still like, but who no longer fits into your life.
Really hoping for more advances in distributed type systems in the coming years, but most folks don't really need the very specialised performance envelope that the BEAM gives, and would be better off elsewhere with a type system that caught more mistakes up-front, and provided better domain modelling tools.
Do not regret one bit
I feel like the happy memories are more for greenfield development than maintenance. I don't have any particularly happy memories of Ruby anyway.
I wanted to quickly prototype an app, so I used Groovy. It was very productive, esp since I deal with lots of JSON. Over the time, the prototype has grown to be a serious app, and boy I hate refactoring it. Stupid mistakes such as method renaming can be a nightmare. Yes I should have written more unit tests, but my excuse was it's just a prototype.
Never understood this point "well, you don't need types, you can just write tests for it". IMO you should never have to write tests for something a type system can find for you. Why should I waste time with something which can be found by the compiler?
For now types+tests are a happy medium. No need to throw the baby out with the water just because 100% correctness is still unfeasible for everyday business problems.
I'd rather use a combination of tests and stricter type checking. There's no sense in being a fundamentalist about either approach.
Completely agreed. I tend to prefer pragmatic solutions over strict adherence to some methodology. As a sibling comment noted the natural end of specifying everything beforehand would be formal systems, which are usually not worth the effort. On the other hand I don't see "let's just throw everything the compiler could help us with out, because it's a bit more effort" as a sensible strategy.
(Protip: use Scala, it combines the expressiveness of Groovy with the safety of Java. It's often seen as Haskell-like, to come back to the article)
This is your problem, not the lack of tests. When you use Ruby or Apache Groovy to prototype something, it needs rewriting in a statically typed language as soon as it starts growing into something you want to be production quality.
Groovy's good for glue code, build scripts, and tests. Don't build actual systems in it.
One can write unmaintainable code in any given language/framework. I am not a fan of OO but in this case I would not blame OO but the one who developed this messy app.
There is no way that I am anywhere near as productive in Haskell as Ruby, but I like Haskell and for some things I very much prefer it. I would argue that it is a good thing to use two very different languages.
dynamic typing: old debate and author contributed nothing to it.
side effects: with enough effort and discipline ruby can be very much functional and side effects are less of an annoyance.
oop: yeah, but more specifically "what oop has become in past 30 years".
Not when importing a module written by someone else, as all non-trivial apps need, can impact your code.
The idea of having a build environment and language specific package managers for deploy and pulling in hundreds of dependencies directly leads to dependency hell, a user-hostile setup process and inevitably limits the language and apps to saas type use cases.
The only major end user focused ruby apps left are what, discourse, redmine, jekyll? Discourse probably recognizes the complexity of their setup process and has a docker only install which just hides and postpones the complexity, Redmine tries to be available via distribution package managers and user frustration with updating Jekyll is well known.
The people who benefit from this kind of adhoc ecosystem of hundreds of small packages, package managers, anything goes are the completely self interested jockeying for influence and move on to the next new thing, the language is left with the debt and its entirely the fault of the language developers.
The same thing exists in Node and has now been adopted by the PHP ecosystem taking away the easy setup benefits of PHP.
To see this pushed to the extreme, and to have a glimpse of the future, check out Edwin Brady's book "Type Driven Development with Idris": https://www.manning.com/books/type-driven-development-with-i... - I don't expect this style of programming to become the norm until at least another several years, but it essentially allows you to push all behavioral specifications into the types, rendering most unit testing tests obsolete. Of course I would still have smoke and integration tests to for sanity checking sake.
You can write, 'I hate X because of dynamic typing, side effects, and object-oriented programming' for many values of X. Similarly, the reasons why the author is drawn to Haskell can be applied to a large number of other languages.
Because not everything I do impacts on the finances of a million people?
- Fat models (huge number of hooks, scopes, many methods stuffed inside in the name of "domain-driven design", etc)
- Fat controllers (huge number of shared methods, hooks, shared variables and hooks, concerns, etc)
- Fat views/helpers/templates
In multiple years of working with Ruby (+/- Rails) - there is one talk that changed my whole mind of scaling systems - aka ways to build the majestic monolith [1]. And I believe the author of that talk would be laughing silently at this post right now, thinking, "I know what you're talking about".
Models, Models, Everywhere by Chris Griego: https://speakerdeck.com/u/cgriego/p/models-models-every-wher...
Check out those slides, and check the codebase. This is not a Ruby problem. Splitting things mindlessly into microservices, trying to go "fully functional" (answer: nope, nothing in the world is pure or perfect), everything has trade-offs.
[1] Majestic Monolith: https://m.signalvnoise.com/the-majestic-monolith-29166d02222...
Ruby and rails were awesome in the late 2000', when most people were trying to get their essence and do crazy and smart things with them, always focusing on making things easier for the (dev) user.
But then, soon after the start of the 2010', it started to get really ubiquitous, and there were a lot of people using it who weren't especially passionate about development. They started to make everything complicated, not bothering about trying to make things easier, and kept talking about "good practices", following them blindly without having any clue what problems they were supposed to solve.
This is probably something that occurs naturally for any successful tool. I'm not even blaming those people. And it seems quite normal to me that after spending years among passionate only people doing cool things, we feel bored when things normalize. Time to find an other community, no hard feelings.
But for core business logic? Definitely not my first choice.
I have an alternative perspective. It's clarity, refactorability and testing ability make it a great choice for core business logic. In fact, I am yet to see a cleaner alternative. I've seen rails app's go from monolith to Go microservices, and the clarity of whats going on and agility for change is just gone. It becomes a nightmare to work with.
Wish I had time to look into Clojure. Excellent programming paradigm along with the interoperability, libraries, and platform support of the JVM.
On the other hand I think pure languages, like Haskell, take it too far.
My ideal language would be something like Haskell + limited side effect support(for IO) + ecosystem of something like Python or Java or Golang.
Even C++ has more tooling love than what F# currently has.
Anyone that wants to be sure their code will run in whatever platform Microsoft might think of supporting next, should not focus too much on it, unless the wind changes again.
There is an argument for performance, but static typing really gets the performance benefit when you have fixed size data type arrays. Elixir has powerful bit and byte manipulation in the standard library for many such operations, and if you're really looking to do mathematical transformations of arrays and matrices, you shouldn't choose elixir.
> time assurances of correctness _in a majority of cases_
So basically, let's do it and pray it works, maybe?
I would consider Nim. Maybe the ecosystem is not there yet but they are getting many things right.
I love ruby, and agree it's not perfect, but thats not what technical debt is. And blanket including all "OO patterns" in your equation, and never having really used ruby, leads me to believe you don't know what you're talking about.
1. installing rvm breaks sometimes due to random code changes (i think the maintainers fix them recently)
2. they seem to think every app has just 1 database so they dont support db sharding themselves without a third party gem.
3. Net::Http is probably the most unintuitive api for crawling web pages.
And thus the centralisation/decentralisation wheel turns again because the new generation think they have discovered something new but ignore the lessons learned in the past.
If only we could fix that human tendency with a code upgrade.
It's a compiler that is built for each project with types specific to the domain problem being solved.
Language type checking misses the point. The types I want to check, and the extent I want to check them, are in the spec files.
Go type inference, for example, is deeply primitive and an awful lot of Go code seems to spend its time implementing duck typing via work arounds. It looks an awful lot like dependency injection for the 2010s.
A rich type system lets you mold and shape the types to fit nicely over your domain, effectively becoming a machine-verified DSL for your business problem. It will catch flaws in your mental model before you even begin to write tests or an implementation, and is a cheap way of sketching out your ideas and great documentation to have over the lifetime of your project. Of course you can't fit it exactly, so you need a smattering of spec tests, and probably some property-based tests for good measure to fill in the gaps.
It's worth incorporating a way to express these things directly into the language proper. That way all your tools will understand them (e.g. automated refactoring will already know what needs to be updated) and you can talk about them in the language.
> Go type inference, for example, is deeply primitive and an awful lot of Go code seems to spend its time implementing duck typing via work arounds.
Yeah, Go is the exception. It's profoundly and proudly ignorant of 65 years of language design progress. If Go were the only language type system I had access to I'd think language type checking was pointless too.
> It goes like this. You try one strategy on a problem. It fails. You retreat, dispirited. Later, having forgotten your bitter defeat, you try the same strategy again. Perhaps the process repeats. But eventually—again, thanks to your forgetfulness—you commit a slight error, a tiny deviation from the path you’ve tried several times. And suddenly, you succeed.
I think we're a bit better than that, but it pays to remember it the next time you see the young whippersnappers publishing an NPM package doing the same thing you did years ago and deemed to be a failure. By all means, share the war stories with them - it's important we get better at appreciating history, but do it from a position of encouragement. They may yet succeed where you failed. :)
- [0]: https://mathwithbaddrawings.com/2017/09/20/the-state-of-bein...