7 ms·
I read the whole thing waiting for the aha-erlebnis which never came. I'm a full stack JS/TS engineer with a decade of experience. I expected this article to be
by gehen88 4y ago
I read the whole thing waiting for the aha-erlebnis which never came. I'm a full stack JS/TS engineer with a decade of experience. I expected this article to be written for someone like me. It didn't click, even though I already love and use functional aspects like immutability and pure functions. I feel like it's the whole new set of terminology that puts me off (and I'm talking about `scan` and `Task`, not even `Functor` or `Monad`). I have confidence I can learn and apply this in a few weeks, but I can't realistically expect junior/medior devs to quickly onboard into a codebase like that.
Maybe I'm biased against "true" functional programming because I've been on Clojure and Scala projects in the past (as a backend dev) and both experiences have been good for my personal/professional development, but a shitshow in terms of long-term project maintenance caused by the enormous learning curve for onboarding devs. The article talks about how great it is for confidently refactoring code (which I bet is true) but doesn't talk about getting people to understand the code in the first place (which is still a requirement before you can do any kind of refactoring).
My only hope is for ECMAScript (or maybe TypeScript) to introduce these OK/Err/Maybe/Task concepts as a language feature, in a way which befits the language rather than trying to be "complete" about it. We don't need the full spectrum of tools, just a handful.
- zmmmmm 4y agoAlways makes me sad that Scala got sucked into the pure-functional priesthood type culture rather than the "better Java, by being mostly functional and immutable and then practical as hell when appropriate" pathway. I really like coding using Scala but the way I like to do it feels totally non-idiomatic.
- piaste 4y ago> "better Java, by being mostly functional and immutable and then practical as hell when appropriate" That's very much what Kotlin is aiming for.
- gehen88 4y agoSo true. I was involved in two very different Scala projects. One was the sensible "better Java" way, which was mostly great. The other was a big enterprise project with a core group of "hardcore" FP enthusiasts which was very stressful because of imposter syndrome and troubles to onboard new folks. I have been against Scala ever since, exactly because of this FP cult.
- wiseowise 4y ago> The other was a big enterprise project with a core group of "hardcore" Spanish enthusiasts which was very stressful because of imposter syndrome and troubles to onboard new folks. I have been against Spanish ever since, exactly because of this Spanish cult.
- davedx 4y agoScala tried to be too much. Too many paradigms. Too much flexibility and power. Many people might think they want that, but a subset are probably going to have an easier, happier life choosing a less powerful language...
- piaste 4y ago> I read the whole thing waiting for the aha-erlebnis which never came. I'm a full stack JS/TS engineer with a decade of experience. I expected this article to be written for someone like me. It didn't click Don't worry, it's not about you. The article is genuinely underwhelming. It walks you up the abstraction tree to the building of higher-kinded types, but then just handwaves it with 'and now you can do a lot of things!' but doesn't show them. It needs a final part where the flexibility is displayed. Something like 'if (debugMode) runpipeline(synchronousDebugWriter) else runpipeline(promise)'.
- fleddr 4y agoI couldn't agree more. I feel that some thought leaders debating intellectual concepts in computer programming have no idea how real world software development takes place these days. Developers are under enormous time pressure to deliver. They face an exponential skill curve as their scope is massively broad (i.e. devops). Things need to be shipped fast, time for "proper" engineering is compromised. Team members working on the codebase are of various skill levels and ever changing. Finally, a lot of products being worked on have a limited shelf life. For 80% of developers worldwide, the concepts discussed in the article are too steep, and therefore unusable.
- itronitron 4y agoI've occasionally watched colleagues give presentations on functional programming over the years, and while I can see why certain people are drawn to it the stated benefits of functional programming have never seemed that significant to me. The advantages that FP provides aren't likely to be needed by developers that are capable of learning it.
- wokwokwok 4y agoI’ve had similar experiences with scala and clojure professionally. I now actively oppose people attempting to add functional code to projects I work on. …because when they say “more functional” most people mean: I want less code. I want the code to be shorter, because I’m lazy and I want it to be all on one screen. …but that’s actively harmful to almost any code base. You want simple code, not dense complicated code. Dense complicated code is for people who wrote the code, and a few smart talented people. Other people have to work on the code too. They cannot. Actual functional code doesn’t strive for code density, it strives for code purity and algebraic structures. That’s fine. Do that. Dense map reduce reduce flow reduce functions can die in a fire.
- bigDinosaur 4y agoPretty poor attitude to just adopt so generally. I've seen 'actively harmful' qualities from all paradigms. Once peoples start adopting attitudes like yours they've just become the mirror of the condescending FP type and just kill outright any of the really cool features that are useful, as well as any discussion of them.
- wokwokwok 4y agoDo whatever you want with your own code bases; my responsibility is to make the ones I work on maintainable by other people. /shrug
- cpursley 4y agoSome of us don't find OOP code maintainable.
- wokwokwok 4y agoIt doesn’t matter if it’s FP or OOP. Here’s the real question: do you think dense code is more maintainable? Generally yes? More than a verbose multilayered abstraction, probably? …but where do you draw the line? Map statements instead of for loops? Collapse all the white space onto a single 200 character line? Make everything one big regex? Dense code means that every change has more impact, because there’s less code; it’s unavoidable: less code to do the same work means more impact from changing any part of that code. That is why it’s difficult to maintain; because you can’t touch it without making side effects; you can’t reason about a small part of the code, because the logic is dense and difficult to unpack into small parts. Certainly OOP can often be verbose and annoying, but that’s a different thing. Code density and being functional are orthogonal; some OOP is too dense too. …but generally I’ve found that inexperienced people see density and strive for it, believing this makes it functional; but the truth is the opposite. Good functional programming is often naturally concise, but most people don’t actually seem to understand FP. They just seem think it means to put more “reduce” statements in the code, remove for loops and generally make the code harder to debug and denser. …in my, limited experience, working with lots and lot of different folk at many different organisations.
- davedx 4y agoOK/Err/Maybe can be trivially implemented with TypeScript, if the project development team wants them. We have it in the current project I work on and it works well with GraphQL. For OK/Err, in my experience it kind of depends on "how happy is your dev team with using exceptions for general purpose errors"? The orthodox school of thought says "exceptions only for exceptional errors", in which case things like OK/Err give you a nice way to structure your control flow and its typings. `Maybe` is used by `graphql-code-generator` to explicitly mark optional typings in generated TypeScript types for a GraphQL schema. I don't think it's necessary (TypeScript has `?` after all) but some people prefer it.
- Cthulhu_ 4y agoI've used patterns like that in Scala; I see their value in building a correct system etc etc etc, but only if it's consistently used throughout the codebase. As it stands, most JS/TS projects aren't very consistent to begin with; error handling is either not done at all (let it fail), or a mix of exceptions, failing promises, error responses / types / states, etc. But that's not really down to the language, more the underlying culture.
- substation13 4y ago> My only hope is for ECMAScript (or maybe TypeScript) to introduce these OK/Err/Maybe/Task concepts as a language feature When using these concepts the need for do-notation comes up pretty quickly. It would be like using JS promises without the async keyword! Of course, follow this to it's conclusion and you will have a functional language.
- Cthulhu_ 4y agoI mean they could ADD it, just like nowadays individuals can choose to implement it themselves, but it wouldn't supersede any existing error / result implementations (success/error callbacks, throw/catch, promises which use both, etc). To improve or change a language, I think you should get rid of another feature if it solves the same problem, instead of add another option.
- substation13 4y ago> just like nowadays individuals can choose to implement it themselves I don't think this is possible with JS right now?
- jerf 4y ago"I read the whole thing waiting for the aha-erlebnis which never came." This is increasingly my go-to metaphor for this: This article and many of its kind are talking about bricks. They really like bricks, because they're square, and they come in several nice colors, you can really bash a clam with them, they're cheap, they're quite uniform, they make great doorstops and hold down stacks of paper really well, and they have a personal preference for the texture of bricks over other possible building materials. These people think bricks are great, and you should incorporate them into all your projects, be it steel bridges, mud huts, a shed out back, a house, everything. Bricks should be everywhere. Then they build you a tutorial where they show how it looks to build a mud hut, and how nice it is to put some random bricks in to it. Isn't that nice. Now your mud hut has bricks in it! It's better now. But that's not what bricks are about. Bricks are not about textures or being good at bashing open clams. Bricks are about building walls. Walls that may not be the solution to every wall, but certainly have their place in the field of wall building because of their flexibility, easy of construction, strength, cheapness, etc. Trying to understand bricks out of the context of using them with mortar to build walls is missing the point. Contra the endless stream of tutorials that make it look like functional programming is essentially mapping over arrays and using Result/Option instead of error returns, that is not what functional programming is about. That is a particular brick functional programming is built out of. It isn't the only brick, and if you scan a real Haskell program, isn't even necessarily one of the major ones in practice. They turn out to be a specific example of a very simple "recursion scheme". These simple "bricks" show up a lot precisely because they are so simple, but generally the architecture layer of the program is built out of something more interesting, because "map" turns out to be a very small and incapable primitive to build a real program out of. In my considered opinion and experience, if you spend time with "functional programming" and come away thinking "oh, it's about 'map' and 'Result'", the point of functional programming was completely missed. And stop telling people that's what it's about! You're putting a bad taste in everyone's mouth, because when all the imperative programmers look at your so-called "functional" code in imperative languages and say, "That's a nightmare. There's all this extra stuff and noise and it's not doing anything very useful for all that extra stuff."... they're completely right. Completely. It is a net negative to force this style in to places where it doesn't belong, quite a large one in my opinion. And especially stop being sanctimonious about they "don't get it" when people object to this style. It is the one advocating this style where it does not belong that does not "get it". The worst thing that can happen in one's education is to think you've been exposed to some concept when you in fact haven't, and come away with a wrong impression without realizing there's a right one to be had. I still encourage curious programmers to clock some serious time with real functional programming to learn what it is about. This style of programming isn't it, and your negative impressions of this style don't necessarily apply to real functional programming. (It does some, perhaps, but probably not the way you think.)
- ravenstine 4y agoMaybe I'm wrong, but I think all the talk around weird ideas like Functors, Monads, etc., are mostly red herrings and aren't that applicable to most everyday software engineering tasks. Just use functions, avoid state, use map/reduce if it's more readable, avoid OOP most of the time (if not all of it), avoid abstracting every single damn thing, and what you're writing seems functional enough even if it doesn't totally satisfy the academic view of what functional programming is.
- PartiallyTyped 4y ago> Maybe I'm wrong, but I think all the talk around weird ideas like Functors, Monads, etc., are mostly red herrings and aren't that applicable to most everyday software engineering tasks. They are a red herring. In most cases, all you need to know about a monad is that it defines some kind of transformation of the enclosed data by applying a function onto it that returns a Monad of the same kind. e.g. the list monad [a] says that if you bind it with a function f: a -> [b] (ie a function that takes a value and returns a list of b), the monad will transform to [b] by concatenating the lists. the maybe monad Maybe[a] says if you bind it with a function f: a -> Maybe[b], if Maybe has type Some(a), the data of the monad is replaced by the result of the function. If the monad has type Nothing, then it retains nothing. It's no different to a = f(a) if a is not None else a So a monad is just an object that defines the transformation of the underlying data when applying a function that returns a monad of the same type, nothing more.