13 ms·
How to stop functional programming
- braythwayt 11y agoMy methodology for avoiding this confusing “functional” programming: 1. Write: function add (a, b) { return a + b; } 2. Refactor to object: class AccumulatingIntegerWidget { constructor (...numbers) { this.accumulation = 0; this.accumulate(...numbers); } accumulate (...numbers) { for (const n of numbers) { this.accumulation = this.accumulation + n; } } getAccumulation () { return this.accumulation; } } Presto! It’s stateful and object-oriented and handles future cases like adding three numbers, even though WeArentGonnaNeedIt! If this does not satisfy, I progress to making my classes observe each other and update themselves automatically. “We’re doing two-way binding!” I exclaim proudly, while leaving debugging as an exercise for my colleagues.
- defiblep 11y agoYour first example is actually procedural. Needs more lambdas.
- braythwayt 11y agoIt never lasts long enough to get complex, it appears in a virtual functional/anti-functional pair and then they annihilate each other. Only in the presence of a powerful gravitational force, like the edge of a corporate programming style guide, will one of the pair be sucked into the maw, leaving the other to accumulate cruft. For example, the second can incorporate two-way binding as noted, logging, synchronization via Operational Transforms, and so much more...
- BerislavLopac 11y ago> Needs more lambdas. I'll be using this in every code review from now on.
- dudul 11y agoYour design lacks a `Factory` I think. You don't use design patterns enough.
- braythwayt 11y agoIt’s factories all the way down.
- Lawtonfogle 11y agoSo if you have some object named Obj, and you have some interface for it, and you have a factory that creates objects matching that interface, and that factory has an interface, then what do you call the factory that builds implementations of that interface? A.) IObjFactoryFactory B.) IIObjFactory C.) IIObjFactoryFactory D.) An abomination upon mankind. E.) IObjFactoryIFactory
- onnoonno 11y agoJavaProxyEnterpriseBeanConnectorAbstractInterfaceFactoryImplementationMockup or something.
- strmpnk 11y agoWon't pass code review till you can use dependency injection to pass a + operator mock for testing.
- goalieca 11y agoThis is one reason I hate our industry. No one engineers anything. They all just abuse OOP so that code is packaged together in some arbitrary heirarchy and then refactor it every single time a user story is added.
- pekk 11y agoIf we forced everyone to switch to Haskell, do you think this would really be any different? People would still do the bare minimum to implement the latest user stories, because that is literally what the boss is paying for.
- davexunit 11y agoI think the point is to not force any single paradigm. OOP is what is being forced today, but it would also be bad if the industry forced functional programming. Large programs typically call for multiple styles of programming. One piece may suit an imperative style, another functional, another logic/relational, another object-oriented, etc. In general, I think OOP is nearly always the wrong tool, though.
- emerongi 11y agoI'm in university right now and there is an object-oriented programming course (which is required by most other advanced courses), but no functional programming course. That shows how skewed the industry is. It's a pretty forward-thinking university as well. OOP is sometimes the right tool, but most times it definitely is not. It's important to be able to know your tools and choose the right one. The current situation is disappointing though.
- johan_larson 11y agoWe force everyone to switch to Haskell. OK. Even the fair-to-mediocre programmers? Yes. Who tend to program by copypasta and change stuff until it gets the right answer? Yes. Run away. Run far, far away. You don't want to see what "design patterns" and urban legends these people layer on top of Haskell to make it intellectually manageable.
- jksmith 11y agoI'll need an interface for that so I don't have to read into the code to see what it does.
- Cthulhu_ 11y agoI think you need to pass it a NumberFactory instead of this magic dot-dot-dot syntax, I can't read it.
- merpnderp 11y agoI love this so hard. I've been a dev for over a decade and just recently discovered functional programming (in a now undergraduate academic sense) and it has changed all my code. Things are so much simpler, easier to follow, and far far less code as I focus on data structure as state, and functions as things that operate on the data structures. Everything is just so much simpler now.
- xyzzy4 11y agoBut where's your specs?
- mavelikara 11y ago-1; please add a logging/tracing call in your add method. Since that introduces impurity, make an algebra for effects you can do with logging, construct the program as a free monad in that algebra and evaluate it.
- ruggeri 11y agoWith great comedy, you never know if they're being serious...
- JanneVee 11y agoLike "functional" programming can't be abstracted so it becomes way too generic.
- andrewmcwatters 11y agoI feel like there's potential for a "How to stop being a smartass" rebuttal article here.
- throw19238 11y ago
- throw19238 11y agoApparently this submission is flagged and sinking. In addition to being bureaucrats, the OO hordes are apparently without humor, too. Or perhaps one goes with the other.
- emodendroket 11y agoIt's not really that funny.
- vinceguidry 11y agoWorse, there doesn't seem to be a point. It sounds like a Haskeller's rant over how OOPers don't understand basic concepts. And, to be fair, a lot of them don't, can't count how many times people have mistaken static typing for object-orientation. But this isn't the way to point that out. Should we be surprised that a modern multi-paradigmatic programming language can be used to code in a functional style?
- douche 11y agoOver 200 points and on the ninth page, when older stuff with less points is on the front page. Hmm...
- the_af 11y agoI've had some success explaining, mainly through pair programming, code reviews and an educational use of the console, the basics of FP-ish constructs such as map, fold, filter, pattern matching, control of side-effects, etc. It's amazing what you can do if, instead of assuming an arrogant attitude, you take your time to teach other programmers and review their code to explain how to avoid pitfalls, and accept that some people will remain unconvinced about some aspects of FP that you cannot adequately justify (a good reason to seek a better understanding of those justifications!). And it has the added benefit that this situation will never reach your manager, so he/she doesn't have to get involved :)
- sundarurfriend 11y ago> such as map, fold, filter, pattern matching, control of side-effects, etc. map and filter have become natural parts of my thinking, fold too is getting there, and avoidance of side-effects even gives pleasant tingles to the math-guy in me, but I've never understood what pattern matching brings to the table. In my admitted limited understanding, they seem to be a syntactic sugar for if-elseif branching that ends up scattering the logic of a function to multiple blocks of code, while bringing no obvious benefit compared to them. Since you mentioned your success explaining the justifications for these things, I thought I'd take advantage of that here. :) Could you explain what I'm missing with pattern matching?
- kinghajj 11y agoPattern matching is not just sugar for an if-elseif chain, since compilers will check for exhaustiveness. This is especially important when used with sum types (which are the primary motivator for this feature): data Thing = Foo String | Bar Int Double | Baz String String case thing of Foo s -> putStrLn s Bar i f -> -- ... Baz s1 s2 -> -- ... If you later add another variant to Thing, the compiler will check that all pattern matches against it account for the new case. (Wildcard matches alleviate the need always to handle every case.) An if-elseif chain, however, would still compile after adding the new variant, so you must track down the usages manually.
- sdegutis 11y agoThis satire is more sad than funny, because it's true. A manager's job isn't to understand good code, it's to understand business and to know how to effectively get rid of road-blocks for programmers on the team. But how can they make decisions about how to make progress easier/smoother for every programmer, if they don't understand programming? It's kind of like when my kids are arguing without being able to solve it on their own, and I hear it from my office, and have to go over there to potentially solve the problem for them. What if they're arguing over a dispute over Pokeyman cards? I don't know anything about Pokeyman, and I can't learn well enough to give helpful advice or make firm rules on the spot. It seems like the best solution in both cases is to trust the person who's most "senior", either the senior developer or the oldest kid or whoever, to make a judgment call to know what to do here. Probably the other programmer should be brought up to speed on how that code works so when they encounter it next time, it's not confusing. Is that always practical or even possible? Probably not in a large corporate setting. But in smaller companies, I'm confident it probably always is. Of course, so long as the code isn't intentionally clever. As long as it's at least trying to be clear what it does, that should be good enough. But intentionally clever code should almost always be rewritten, because it's usually so clever that even the author can't understand what it does in 6 months' time.
- zaphar 11y agoThere is an even better approach than trusting the most senior that will have a longer term payoff. The dispute is usually caused by a lack of people skills in one or both of the parties. If you can instead take this as an opportunity not to resolve a pokemon dispute but instead to teach dispute resolution skills to both then you don't need to know enough pokemon to resolve it. And the next time a dispute comes up around something you don't have enough information to be authoritative about the involved parties might be able to resolve it themselves.
- SCdF 11y agoI've found usually if you cleanly explain what you're doing and go through some examples people are willing to learn. Not sure if I've been lucky in that regard, but I've never had the problem this guy clearly has before, with integrating functional ideas into code. I've also found that quite often I actually am at fault because it is reasonable to want to break up dense code into smaller understandable blocks, and while you _can_ write an entire function (or application) as one statement in an FP style, your job isn't to show how cool you are, it's to write code that your peers can maintain. _(Like that last paragraph. It probably should have been more than once sentence. We live and learn.)_
- falcolas 11y agoI realize this is mostly frustrated satire - but it is an actual issue when working with coders of different skill levels. The solution is to simply drop the use of flatmap (or any other function which eliminates loops). In my experience, that level of abstraction is the kind of thing which confuse new developers who have not (yet) been exposed to the terminology introduced by functional programming. It comes across as "clever" and "obfuscated". And it really is quite clever - you turn a 4 line for loop with accumulators into a single line of code. But it's also legitimately obfuscated as well, until you grok how flatmap works. Ultimately, a for loop can be understood by almost any programmer you will encounter. There's more code, it does the exact same thing as a flatmap, but (as the OP points out) the function is still pure.
- pklausler 11y agoIt is counterproductive to cripple the programmers on your team who can handle abstraction to avoid confusing the ones who can't. Why turn 10x coders into 9x coders or worse just to retain your 1x coders? Or work with the ones having trouble with a pattern until they get it?
- steven777400 11y agoThat's the management decision in the article. And I make the same decision. We're not an organization that attracts nor hires rockstars (or, as you say, 10x coders). We have a couple really sharp folks but are predominately staffed by "1x" coders. Therefore, it is important and the responsible thing to do to write all code so that it can be understood and maintained by a 1x coder. Even if it is being written and currently maintained by one of our sharper folks, people move on or change roles, and projects shift to other staff for long term maintenance. Who's going to be maintaining this project in 2-4 years? This project needs to be written with them in mind.
- Jtsummers 11y agoI have to ask, where do you draw the line? I had a team lead that disliked me writing things like (in C#, been a bit so forgive errors): List<AClass> original; // perhaps as a parameter to the function List<AClass> filtered = original.Where(x => x.Field > 10); Arguing that I should instead have just used for loops (showed him foreach and he agreed that that was better, at least) like: List<AClass> filtered = new List<AClass>(); foreach(x in original) if(x.Field > 10) filtered.Add(x); Ok, so it's only two lines longer (three if you split the if and its effect, 5 if you also add in braces, 7 if you put opening braces on their own lines). The `Where` version is not that complicated, and only requires understanding one (potentially) new concept for programmers, namely anonymous functions. Wouldn't the briefer, but still clear, code be preferable for maintenance?
- rnavarro 11y agoWell, if the functional code people are complaining is on the same level as the one the author used on the post, then I agree that a quick pair session is enough to "solve the conflict". But IMO there is problem when (assuming Scala here) you include a library like Scalaz on the codebase, and then start using more abstract functional concepts. While I think these concepts are amazing, I usually don't use then on my day job as I know that my team don't have the knowledge nor the timing to quickly grasp such concepts without impacting the project's pace.
- incepted 11y agoWe need more reasonable people like you :-)
- incepted 11y agoSounds like the author is sharing a personal story here. I'm guessing he wrote some FP code and one his coworkers complained about it. OP, two pieces of advice: - Ask yourself why your coworker went to your boss instead of talking to you directly - Work on your communication skills with your coworkers. I'm guessing you have an attitude that's rubbing them the wrong way (I've seen a lot of this coming from people who are trying to impose advanced techniques upon a team that's not ready for those). It's startling how so many bright programmers possess so little social awareness.
- cname 11y agoIt's amazing how you can tell so much about a person just by reading one short article. To me, your advice comes across as condescending. Maybe you need to work on your communication skills too? Regardless, what's the practical solution to managing complexity in a team "that's not ready"? At some point, most projects get complex enough that you're going to have to do _something_ that someone is going to find confusing. It could be functional, OO, whatever. If you've got complexity to manage and can't use reasonable tools to manage it, you may have bigger problems. Pandering to the hypothetical lowest common denominator developer isn't going to help much, because they're probably not going to "get it" anyway and will likely make a mess in any case.
- zymhan 11y ago> To me, your advice comes across as condescending. Maybe you need to work on your communication skills too? And now we've come full circle
- lmm 11y agoBrian McKenna is a public figure who people could easily have encountered in other ways. In my experience many functional programmers, myself included, do generalize where they don't need to (e.g. writing a function to accept any F[_]: Foldable when it's only ever called with List). At which point asking them to justify the abstraction is entirely justified. Conversely in cases where fancy functional techniques really are improving maintainability it's usually pretty easy to demonstrate this by comparing two implementations side by side.
- agentgt 11y agoI have never seen a manager complain about the use of functional programming. What I have seen is amazingly intelligent programmers with FP backgrounds (who I pushed to hire) try to write in languages that are sort of FP (ie Java and Javascript). They end up writing code that is not canonical (which I don't mind) and using academic/haskell variable names (ie single letter variable names which I do mind heavily) and then fail to write any documentation (anecdotal observations). I'm not saying this always the case but I have seen it quite a few times.
- boothead 11y agoIsn't that a bit like hiring a sniper and then sending them into battle armed with a nerf gun? ;-)
- jawilson2 11y agoProbably more like sending them in with an AK-47. Each is great at what it does, but you will fail if you assign a person trained with a different weapon to the wrong task, and ask them to use an AK47 like a sniper rifle, or vice versa.
- lmm 11y agoFWIW I have had a manager complain about it.
- seivan 11y agoI can understand that concepts like flatMap, merge, reduce and zip can be intimidating at first. It would help to explain what they are and how they work with smaller examples outside of project code base. https://jsbin.com/bemasodemi/edit?js,console https://jsbin.com/bemasodemi/edit?js,console
- Cthulhu_ 11y agoOne argument I'd like to use at one point is to explain a for-loop and what it does - intimidating? How about initializing a numerical variable, then creating a loop that checks the value of said variable, increments (or decrements), and in case of array operations, attempts to get an entry in that array in each loop. Versus for-each-entry-in-list-do-this.
- seivan 11y agoBe pragmatic, there's a higher chance that a developer has used said concept than the FRP mentioned above. Funny you should mention that for loop as it's been removed from Swift 2.2 ;-)
- lacksconfidence 11y agos f g x = f x (g x) k x y = x b f g x = f (g x) c f g x = f x g y f = f (y f) cond p f g x = if p x then f x else g x fac = y (b (cond ((==) 0) (k 1)) (b (s (*)) (c b pred)))
- js8 11y agoYou don't need if-then-else, you can emulate it by applying k and (s k) (which can represent true and false).
- catwell 11y agoAdding two numbers together without being pure? Isn't that how we always do it? MOV edx, 1 MOV adx, 2 ADD eax, edx
- wiredfool 11y agoDoes that actually work?
- crimsonalucard 11y agoOne way to solve this problem is to show them this article. I'm bookmarking this in case the situation ever pops up.
- kaio 11y agoWelp. The code would add the user himself as his own coworker in both versions. I'm a Java programmer by day, but i have definitely learned a lot by writing some "functional" (i.e. in a "functional" language) code as well. But this is just concepts. You can also take those concepts and write clean (and not too bloated) OO code. I really don't get what all this exaggerated "functional programming" vs. "bad object-oriented enterprise code" ranting is good for
- kelvin0 11y agoI sense a little bit of a condescending attitude in such posts, and that does not help 'non-fp' progs to want to join the super world of fp elite programming. Personnally I've started learning Haskell and I love it. But having a denigrating attitude towards OOP-ish programming is simply polarizing and does not help the 'cause' ...
- Joof 11y agoOh no problem. fac n = result (for init next done) where init = (0,1) next (i,m) = (i+1, m * (i+1)) done (i,_) = i==n result (_,m) = m for i n d = until d n i
- methodover 11y agoWait, am I missing something? Isn't the "non-functional" code here wrong? There seems to be no filtering for only those departments that belong to the user's business, unlike the functional example where it uses "user.departments"
- aidenn0 11y agoWhat language does the article use for examples? I don't recognize it.
- logicfiction 11y agoScala
- relevate 11y agoThis is where I think LINQ does a good job. var coworkers = departments.selectMany(department => department.employees); Nearly equivalent to the Scala code, but uses more approachable keywords like `select`, `selectMany`, and `where` instead of `map`, `flatMap`, and `filter`.
- domlebo70 11y agoOr people could just learn the correct terminology.
- douche 11y agoIt makes a lot of sense in .NET land, because it maps to SQL, which people tend to have some kind of grasp on. Although that LINQ expression syntax can go die in a fire. It's a great way to end up with people using borked up joins in Linq-to-SQL and EF that don't work the way they think they do, rather than the actual foreign-key relationships.
- annasaru 11y agoI think a lot of the abuse happens in Java, and java-derived languages. There is a culture,and the more lines of code you have , and the more classes you have , the better. The language environment and frameworks only re-inforce that stuff. Scala is (I guess ) functional - particularly when contrasted to Java. In his example, I suspect he is conflating that one-liner chained function call with functional programming? Sort of like how coders like to use ternary one-liners especially when they first learnt them (and end up with unreadable code). But his first snippet is obviously simpler, compared to the OOP-cruft of the second and third snippets. As more Java programmers migrate to coding in Python, they are bringing that toxic culture in to Python too - where boilerplate and sugar were relatively less. Its like everyone is doing rocket science, which is despicable, given we are mostly coding CRUDs. Any language is susceptible to abuse, its also a human trait to de-simplify something to gain a fake intellectual satisfaction.