Join devRant
Do all the things like
++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatar
Sign Up
Pipeless API
From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple API
Learn More
Search - "pure function"
-
This code review gave me eye cancer.
So, first of all, let me apologize to anyone impacted by eye cancer, if that really is a thing... because that sounds absolutely horrible. But, believe me, this code was absolutely horrible, too.
I was asked to code review another team's script. I don't like reviewing code from other teams, as I'm pretty "intense" and a nit-picker -- my own team knows and expects this, but I tend to really piss off other people who don't expect my level of input on "what I really think" about their code...
So, I get this script to review. It's over 200 lines of bash (so right away, it's fair game for a boilerplate "this should be re-written in python" or similar reply)... but I dive in to see what they sent.
My eyes.
My eyes.
MY EYES.
So, I certainly cannot violate IP rules and post any of the actual code here (be thankful - be very thankful), but let me just say, I think it may be the worst code I've ever seen. And I've been coding and code-reviewing for upwards of 30 years now. And I've seen a LOT of bad code...
I imagine the author of this script was a rebellious teenager who found the google shell scripting style guide and screamed "YOU'RE NOT MY REAL DAD!" at it and then set out to flagrantly violate every single rule and suggestion in the most dramatic ways possible.
Then they found every other style guide they could, and violated all THOSE rules, too. Just because they were there.
Within the same script... within the SAME CODE BLOCK... 2-space indentation... 4-space indentation... 8-space indentation... TAB indentation... and (just to be complete) NO indentation (entire blocks of code within another function of conditional block, all left-justified, no indentation at all).
lowercase variable/function names, UPPERCASE names, underscore_separated_names, CamelCase names, and every permutation of those as well.
Comments? Not a single one to be found, aside from a 4-line stanza at the top, containing a brief description of that the script did and (to their shame), the name of the author. There were, however, ENTIRE BLOCKS of code commented out.
[ In the examples below, I've replaced indentation spacing with '-', as I couldn't get devrant to format the indentation in a way to suitably share my pain otherwise... ]
Within just a few lines of one another, functions defined as...
function somefunction {
----stuff
}
Another_Function() {
------------stuff
}
There were conditionals blocks in various forms, indentation be damned...
if [ ... ]; then
--stuff
fi
if [ ... ]
--then
----some_stuff
fi
if [ ... ]
then
----something
something_else
--another_thing
fi
And brilliantly un-reachable code blocks, like:
if [ -z "$SOME_VAR" ]; then
--SOME_VAR="blah"
fi
if [ -z "$SOME_VAR" ]
----then
----SOME_VAR="foo"
fi
if [ -z "$SOME_VAR" ]
--then
--echo "SOME_VAR must be set"
fi
Do you remember the classic "demo" programs people used to distribute (like back in the 90s) -- where the program had no real purpose other than to demonstrate various graphics, just for the sake of demonstrating graphics techniques? Or some of those really bad photo slideshows, were the person making the slideshow used EVERY transition possible (slide, wipe, cross-fade, shapes, spins, on and on)? All just for the sake of "showing off" what they could do with the software? I honestly felt like I was looking at some kind of perverse shell-script demo, where the author was trying to use every possible style or obscure syntax possible, just to do it.
But this was PRODUCTION CODE.
There was absolutely no consistency, even within 1-2 adjacent lines. There is no way to maintain this. It's nearly impossible even understand what it's trying to do. It was just pure insanity. Lines and lines of insanity.
I picture the author of this code as some sort of hybrid hipster-artist-goth-mental-patient, chain-smoking clove cigarettes in their office, flinging their own poo at their monitor, frothing at the mouth and screaming "I CODE MY TRUTH! THIS CODE IS MY ART! IT WILL NOT CONFORM TO YOUR WORLDLY STANDARDS!"
I gave up after the first 100 lines.
Gave up.
I washed my eyes out with bleach.
Then I contacted my HR hotline to see if our medical insurance covers eye cancer.32 -
Manager: I read an article today
Dev: oh here we go….
Manager: We must pivot to only functional programming, which means only using functions instead of classes
Dev: Actually functional programming is a bit more nuanced tha—
Manager: Any use of classes going forward is not allowed. Everything must use functions! Classes are an outdated way of programming, using classes is why we continue to miss our deadlines. Functional programming is lean, classes are waterfall.
Dev: What about the libraries we use? Many of those use classes
Manager: Wrap them in a function then, that way they are pure which is one of the requirements of functional programming. You would know that if you spent as much personal time as I do keeping up with the times.34 -
"I'm almost done, I'll just need to add tests!"
Booom! You did it, that was a nuke going off in my head.
No, you shouldn't just need to add tests. The tests should have been written from the get go! You most likely won't cover all the cases. You won't know if adding the tests will break your feature, as you had none, as you refactor your untested mess in order to make your code testable.
When reading your mess of a test case and the painful mocking process you went through, I silently cry out into the void: "Why oh why!? All of this suffering could have been avoided!"
Since most of the time, your mocking pain boils down to not understanding what your "unit" in your "unit test" should be.
So let it be said:
- If you want to build a parser for an XML file, then just write a function / class whose *only* purpose is: parse the XML file, return a value object. That's it. Nothing more, nothing less.
- If you want to build a parser for an XML file, it MUST NOT: download a zip, extract that zip, merge all those files to one big file, parse that big file, talk to some other random APIs as a side-effect, and then return a value object.
Because then you suddenly have to mock away a http service and deal with zip files in your test cases.
The http util of your programming language will most likely work. Your unzip library will most likely work. So just assume it working. There are valid use cases where you want to make sure you acutally send a request and get a response, yet I am talking unit test here only.
In the scope of a class, keep the public methods to a reasonable minimum. As for each public method you shall at least create one test case. If you ever have the feeling "I want to test that private method" replace that statement in your head with: "I should extract that functionality to a new class where that method public. I then can create a unit test case a for that." That new service then becomes a dependency in your current service. Problem solved.
Also, mocking away dependencies should a simple process. If your mocking process fills half the screen, your test setup is overly complicated and your class is doing too much.
That's why I currently dig functional programming so much. When you build pure functions without side effects, unit tests are easy to write. Yet you can apply pure functions to OOP as well (to a degree). Embrace immutability.
Sidenote:
It's really not helpful that a lot of developers don't understand the difference between unit, functional acceptance, integration testing. Then they wonder why they can't test something easily, write overly complex test cases, until someone points out to them: No, in the scope of unit tests, we don't need to test our persistance layer. We just assume that it works. We should only test our businsess logic. You know: "Assuming that I get that response from the database, I expect that to happen." You don't need a test db, make a real query against that, in order to test that. (That still is a valid thing to do. Yet not in the scope of unit tests.)rant developer unit test test testing fp oop writing tests get your shit together unit testing unit tests8 -
Is it just the novice in me that finds the Haskell community's misguided obsession over character count really annoying? Learn You a Haskell For Greater Good states
> Shorter code means less bugs
A lot of people and resources seem to share this opinion, but it's obviously false. Simpler code means less bugs, but look at this function which just means "apply this applicative to each element of a list"
> sequence :: (Applicative f) => [f a] -> f [a]
> sequence = foldr (liftA2 (:)) (pure [])
This isn't "less buggy", it's fucking madness. The same in JS, the king of unreadable languages, would be:
function sequence(seq, val, apply = (f, x) => f(x)) {
seq.map(f => apply(f, val))
}
Seriously, how can you design a strictly typed language that gets beaten by JS in readability?16 -
List of shit my superior said and wrote in the project:
1. Prefer to write "pure" SQL statement rather than ORM to handle basic CRUD ops.
2. Mixing frontend and backend data transformation.
3. Dump validation, data transformation, DB update in one fucking single function.
4. Calculate the datetime manually instead of using library like momentjs or Carbon.
5. No version control until I requested it. Even with vcs, I still have to fucking FTP into the staging and upload file one by one because they don't use SSH (wtf you tell me you don't know basic unix command?)
6. Don't care about efficiency, just loop through thousands of record for every columns in the table. An O(n) ops becomes O(n * m)
7. 6MB for loading a fucking webpage are you kidding me?
Now you telling me you want to make it into AJAX so it'll response faster? #kthxbye2 -
I found this on a wiki with Haskell Humor... it's interesting...
How to Shoot Your Self in the Foot With Haskell: Putting the unsafe in unsafePerformIO!
You shoot the gun, but the bullet gets trapped in the IO monad.
Couldn't match expected type 'Deer' against inferred type 'Foot'.
While compiling your program the compiler produces a type error long enough to overflow a kernel buffer, overwrite the trigger control register and shoot you in the foot.
After trying to decipher the type errors from the compiler, your head explodes.
After you've finally found a way to circumvent the type system and shoot yourself in the foot, Oleg appears out of nothing and shoots you in the foot for coming up with it before him.
You shoot the gun but nothing happens (Haskell is pure, after all).
Your foot is fine, until you try to walk on it, at which point it becomes mangled.
You have a shootFoot function which you've proven correct. QuickCheck validates it for arbitrary you-like values. It will be evaluated only when you end up at the hospital. You hope this doesn't come to pass, as it actually returns a bullet-ridden copy of yourself and you don't want to be garbage-collected.
foreign import ccall "shootparts.h shootfoot" shoot_foot :: Gun -> Programmer -> IO ()
shootSelfInFoot = unsafePerformIO . shoot . foot $ self -- Shoot self in foot 0 or more times depending on evaluation order
No instance for (Target Foot)
arising from use of `shoot' at SelfInflictedInjury.hs:1:0
Possible fix: add an instance declaration for (Target Foot)
In the expression: shoot foot
You go to shoot yourself in the foot but the bullet is in the ST monad and the gun is in the IO monad, so you can't.
You ask Haskell to shoot you in the foot but by the rules of lazy evaluation you don't need the result yet so it doesn't happen.
You decide to shoot yourself in the foot but get distracted devising a ballistics algebra and wondering if you can do the calculations in the type system.
You want to shoot yourself in the foot but realize there is no Gun datatype so use Arrows instead.
You shoot in the direction of your foot, but since you are inside the STM monad you can just retry until you figure out what to do.
You shoot yourself in the foot, but you are perfectly fine as long you just don't evaluate the foot.
You shoot yourself in the foot, but nothing happens unless you start walking.
Don't forget about memory consumption! If you don't look, the bullet causes heap overflow. If you look, the bullet causes stack overflow.
You *appear* to have deliberately shot yourself in the foot, and yet your program actually runs perfectly OK due to lazy evaluation. (So long as you remember to not look at your foot...)
You aim the gun at your foot, pull the trigger and remove the clip. When you look at your undamaged foot, the hammer clicks on an empty barrel.1 -
The "unit" in unit test does not mean your ENTIRE APPLICATION. Ever heard of scope!?
I am amazed how often people write overblown test setups, mock hundreds of unrelated services, just to test one tiny bit of logic.
That bit of logic could have been a pure function.
For that pure function you could write a dead simple unit test. Given that input, I expect that output. Nothing more, nothing less. (It helps even more if the pure functions only accepts primitives, like string and numbers, or very simple immutable value objects).
No I don't care that the service is used by another service, as your mocked interaction also doesn't test the service as a whole but you just assume the happy case most of the time anyway. You want to test the entire application? Let's not use unit tests for that but let's use a different kind of test for that (integration test, functional tests, e2e-tests).
If you write code in a way that easily allows for unit testing, your need to mock goes away.rant unit tests test all the things tests you are doing it wrong tdd testing don't mock me unit test1 -
Dear Coffee,
I ask for your help.
I need to pass this exam, and at the same time a client is angry.
I invoke you.
Like the function I'm in.
A function of time, a function that will probably never halt but you cannot prove it. You hope it will stop soon, but deep inside you know it will continue to compute.
I beg you, Coffee. Make this function of procrastination stop. Please.
I see no escape.
It is a tail-recursive function. You realize it as soon as you reach the end.
You can do nothing about it, you're trapped inside this loop. At each iteration you hope to reach the bottom, but you never know. You can only hope that the bottom is close.
This is the last one, you keep repeating to yourself.
Please Coffee, let it be a non-pure function.
Make the environment change.
Only then we can be saved.3 -
Firebase is pure fucking assrape!
How can these spoiled cunts of Google "develop" such a stinking pile of rotten placenta?
No, one fucking Promise is not enough... you have to return Promises for every single smegma function!
I want to just blow up this ugly afterbirth!!
It seems that Google devs are just spoiled MacCunt Pro brats who copy-paste code around until something "kind of works".13 -
Overengineering. Finding the right point between overdesign and no design at all. That's where fancy languages and unusual patterns being hit by real world problems, and you need to deal with all that utter mess you created being architecture astronaut. Isn't that funny how you realize that another fancy tool is fundamentally incompatible with the task you need to solve, and you realize it after a month of writing workarounds and hacks.
But on the other hand, duct tape slacking becomes a mess even quicker.
Not being able to promote projects. You may code the shit out of side project and still get zero response, absolutely no impact. That's why your side projects often becomes abandoned.
Oversleeping. You thought tomorrow was productive day, but you wake up oversleeped, your head aches, your mind is not clear and you be like "fuck that, I'm staying in bed watching memes all day". But there's job that has to be done, and that bothers you.
Writing tests. Oh, words can't describe how much I hate writing tests, any kind of. I tried testing so many times in high school, at university, even at production, but it seems like my mind is just doesn't accept it. I know that testing is fundamentally important, but my mind collapses every time I try to write a single fucking test, resulting in terrible headache. I don't know why it's like that, but it is, and I better repl the shit out of pure function than write fucking tests. -
!rant
so the other day i was programming and suddenly i wanted to learn haskell. (i don't know why it hit me so suddenly, maybe because it's a 'pure' functional programming language and these 2 terms i knew nothing about)
and to be honest it's really hard coming from an imperative programming language (C/C++, yes, i know they are different in their ways). it's like learning to program again! you really have to get a different mindset and for me honestly it's hard to grasp the idea that 'variables' are immutable! like, that's soooo weird it still stucks to me. for example how did they define the max or min function without using a while loop? what are monads?
I am just 2 days in but it'll be a fun ride!6 -
You add a pure virtual function to a abstract class and then you realize that class have have been inherited by 23 other classes and you add implementation to all of them. 😕😕😕
-
I got assigned to work on a new project a couple of weeks ago. We got the POC code handed off from senior management, since he came up with the idea over the weekend. The project concept is hella exciting, but the dev manager and PO I have to deal with make life unbearable to say the least.
We have only 2 devs (including me) and 1 QA on this supposedly very important project. Of course, management announced the project to the clients already, so now we have to deliver ASAP cause it adds “sizzle”.
The MVP deadline is... no one knows when, either July 30th or September 1st. The MVP requirements are... unknown. I swear if someone saw the list of tasks and issues attached to “MVP” Epic, they would call us nuts trying to fit it all in.
To make things better, each PR requires 2 reviewers, so we end up adding manager as a reviewer just cause we need him to hit that “approve” button. So in attempt to make life easier, we requested to have a third developer. We are getting another developer, but that guy doesn’t know how to unit test a pure function...
Current priorities are... unit testing with coverage of 95% and if we want to refactor code, we have to add area to the list in a Google Doc. As a result, we are not tackling big things like risk of SQL injections not to mention big features like i18n (5-6 languages to support by the way and yes, it’s part of MVP as well as SSR no one knows why). Currently, I spend 2-3 hours a week in calls with the team just to figure out what the hell MVP is, what we have to do and why we have to do it. Last time we spent an hour refining 1 spike and breaking down one story into 3.
Oh, we also don’t have a deployment plan, not even to test environments since DevOps team was not aware of this project at all. Thus, QA cannot create any test suites and have to test everything manually which eats a lot of their time.
This whole project is a big hot mess and I’m considering leaving it all together especially since I’m working on two squads at the same time. I love the project, I love the idea, but management makes it unbearable, so I’m not even motivated to work on that.3 -
Where should starting brackets be positioned if/else and function definition in C? Same line or the next line. Have not seen pure cosmetic bullshit like this.10
-
I really like helping other learn how to use a programming language or solve problems on general. I often go out of my way and stop working on my hobby projects, just to help someone.
Thag being said, I'm no prgramming god. I myself am striving to become a better programmer.
I make mistakes, I can't always help you, I am still learning, but I only have good intentions. And you are by no means obligated to follow my advice. Quite the contrary, fight me, try to prove me wrong or say point out possible flaws. THINK ABOUT WHAT I TELL YOU. DON'T JUST BLINDLY FOLLOW MY ADVICE AND BITCH ON ME LATER.
This happens rather often and I can see why you want to blame me. And I can't deny that part of this is also my fault.
Situations like these don't really tilt me.
But today someone had the fucking nerve to pop a file into the chat and get mad at me for sugvesting a cleaner, shorter and more efficient solution. LIKE I DON'T FUCKING CARE THAT IT TOOK YOU A WHOLE DAY TO IMPLEMENT SOMETHING I CAN DO BETTER IN MINUTES, I JUST WANT TO HELP YOU.
But the best thing I get afterwards: "But you told me to do it like that" BITCH WHAT!?
I have chat logs telling me loud and clear that the concept we never talked about before in private nor on a public server (bless discord's search function). And I will not accept your lousy excuse of having me cobfused with someone. You disrespected me greatly, you put words in my mouth, just to justify your pity anger, when I'm trying to help you?!
Get crucified and put on a shooting range!
I offer you out of pure goodwill. Something you'd normally have to pay for. And this is the treatment I get in return?
Just rm -rf your disastrous, dd -if=/dev/urandom your harddrive and sod off!2 -
Maybe Rant
It's 1:30 AM and I finally finished implementing a simple function after more than an hour.
Not sure if I should be upset about my stupidity or glad that I solved it.
If anyone is interested in learning Haskell I totally recommend these exercises: https://github.com/data61/fp-course
filtering :: Applicative f => (a -> f Bool) -> List a -> f (List a)
filtering p = foldRight (\a -> lift2 (bool id (a:.)) (p a)) (pure Nil)1 -
So I have a colleague who never tests and claims to not have time. I've sent him various emails with errors and their solutions, because he keeps breaking my finished code and I'll find out about it by pure luck. I've informed my team lead, I've also informed HR when he got downright nasty in email. But it feels nothing gets done. Today again I get finished code back because the save function is broken. Again changes that weren't tested were made. I'm so sick of this! Do I really have to escalate this to the CEO because nobody takes responsibility? The colleague is a junior in his first role and without a degree. But in the half year I've worked here I've not seen him improve, and he recently had his one year work anniversary :/3
-
‘Groundhogging refers to the idea that people are going for the same type of person over and over again, while expecting different results,’ they explain. ‘People pick out someone who fits their ideal type, date them, but end up feeling underwhelmed.'
From: https://metro.co.uk/2022/02/...
Awfully resembles a pure function makeLoveHappenForMe with a single arg typeOfPerson:
const typeOfPerson = Jerk
// this is a pure function
makeLoveHappenForMe(new Jerk())
// will always fail
// but does it really have no side effects?2 -
OOP is all about code reusability until you really want exactly the code Foo with non-pure functions in all your classes. You end up almost rewriting all subclasses' properties into the superclass to silence typecheckers. Is there no "I know what i'm doing, please just transpile/compile this piece of logic into these 20 places I need?" You end up doing it the functional way, dumping refs and params into some shared util function and have it do the job. I know, might as well have that one inherited also, but what's the point of adding more mess just for that ?2
-
Oh boy this may be my best product review yet. I'm totally smitten with GitHub Copilot! I always put off trying it, but I finally gave it a try recently. Man, oh man, once I got a taste of it, there was no going back. This auto-suggest feature is pure sorcery! It throws out complete function suggestions while you type, and it's all based on the context of your code.
Let me tell you if you have never tried it, it's freaking awesome and super handy! I've been learning Python for less than a month, but thanks to the freaking Copilot, my Python skills have skyrocketed like for real. I know this because I tackled a Python project and nailed it. The client was stoked because it worked flawlessly, even though my Python skills are still a bit rough around the edges.
The coolst thing is hw clean my code looks, especially for a beginner. all I have to do to add a comment is type a double slash, and Copilot takes care of the rest. It suggests what should go on each line as I type, and it's scarily accurate.
You know what's wild? On the GitHub page, it claims that Copilot writes 50% of the code. But, dude, for me, it wrote way more than that!8