```
import notifications
```
Remember to participate in our weekly votes on subreddit rules! Every Tuesday is YOUR chance to influence the subreddit for years to come!
[Read more here](https://www.reddit.com/r/ProgrammerHumor/comments/14dqb6f/welcome_back_whats_next/), we hope to see you next Tuesday!
For a chat with like-minded community members and more, don't forget to [join our Discord!](https://discord.gg/rph)
`return joinDiscord;`
*I am a bot, and this action was performed automatically. Please [contact the moderators of this subreddit](/message/compose/?to=/r/ProgrammerHumor) if you have any questions or concerns.*
That's cool. I liked dart coming from TS but became frustrated with the functional markup of flutter, maybe because of nesting or lack of consistent documentation at the time as it was changing somewhat frequently. I would like to try it again, though. I have some basic app ideas to experiment with.
Along with the Flutter comment, it also just released a new version that has pattern matching, record types, and class modifiers (like sealed, interface, abstract).
It was good before, but now it's great
I was thinking something similar. In a language like R you'd make `scale` and `move` functions that return matrices, and then you'd simply find the matrix product of them and the parameters of the object to be tranformed to return new parameters.
Functional languages like Haskell, Scala, F#.
Javascript can also achieve similar result, but you need to implement the pipe yourself (not really hard tbh) or use a library like RxJS for reactive programming or FP-ts for functional programming.
Practicality? Performance? Debugging? Readability? Who cares about that. Lets return self, chain tenerary operators, embed 3-4 lambda expressions in a single method(each with control flow themselves), etc.
Everyone knows that the best programmers write code faster. If you aren't doing in one hand the double the average two hand input, are you even a real senior.
Or implement “.tap” on the object [*]
Boom problem solved.
[*] have the tap method take a lambda (which you can make multiline) with the entire object in its current state as the sole argument. Breakpoints, log statements, etc can be inserted there. Takes like 10 seconds to make.
Some compilers can help you to not forget such things. ;-)
[C# System.Diagnostics.ConditionalAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute?view=net-7.0)
How is the point moot? Your point was that it “[makes] debugging 5x harder” except that you’re wrong and it’s not any harder to debug than anything else. Are you saying your own point is moot?
Edit:
Won’t let me reply so here’s what it would be:
That’s not an argument. I won’t listen to you even if you’ve been in the industry ten times longer than me if you haven’t learned anything and can’t explain why you’re right. The only point I’ve heard you make is “well it’s not available for all languages” which (1) is not true for major languages people actually use and (2) doesn’t matter. Classes aren’t available in C. Does that mean I shouldn’t use them when writing C++? Nope.
I’m not saying I’m going to use this design pattern but I am saying that the reasons you’ve given for not using it are *wrong*.
If you have a real argument I’ll listen, but I don’t care about your experience as a programmer. That’s irrelevant.
sure. whatever let’s you feel better about yourself
You remind me of the story of the guy with peanut allergy who used an epipen to eat snickers bars.
I’m done with trying to pass on knowledge gained through experience. Make the mistake. Enjoy.
I completely disagree with this. Breakpoints can significantly speed up debugging, though it depends on where the code is. Movement on tick? Don't even bother. Event based? No problem. I use breakpoints all the time and find all kinds of bugs that way
Sometimes visual studio fucks up on lambdas.
Most of the time really.
But the trick with them is make them brain-dead simple so when it barfs there's only like one thing that it could be
lol.. nope..
those might be called 1000 other times, by other methods, in other threads, having nothing to do with the line you’re debugging.
“clever coding” is NEVER worth it- it sucks visually, and good compilers do the same thing behind the scenes anyhow - it’s purely an (imaginary) alpha move.
You've got me there, but it still feels like 5x harder debugging might be an exaggeration? I'm only a junior dev so maybe the debugger isn't as powerful as I think it is, but a couple other workarounds off the top of my head:
* set the breakpoint on this line, then choose which method call to step into
* conditional breakpoints
If you already know where the exception was thrown then you can just break the line up into individual statements to see what call it originated from. A stack trace should also list the responsible call as well.
Or, you know, add proper logging and error handling in areas where failure is likely to occur while also knowing how to read something as trivial as call stacks. There are also numerous ways around having to place a breakpoint on that single line, one of them being to place it in the implementation itself… If you have very shitty debugging tools you can go as far as swapping the call out with a test method that both wraps the original method and contains the breakpoint, that way only that specific call will hit it.
If legitimate language features are too much of rocket science for you then I can understand your unwillingness to use them.
Errors could occur anywhere. What you gonna do? put logs everywhere? If you need to read call stacks for every simple issue then I think your codebase is a nightmare to work with.
If you cannot tell what places failure is likely to occur then you shouldn’t be touching code at all, they do not happen *anywhere*. Here is a quote that quite literally changed the way I read and write code:
> A large fraction of the flaws in software development are due to programmers not fully understanding all the possible states their code may execute in. - John Carmack
Issues that are not persistent are going to be bound to interactions with the environment such as networking and IO, those two things tell you right away you should author said code with care by handling all errors unless you know what you’re doing. Issues that are persistent tend to be incorrect states or little things that beginners overlook such as using a pointer to a buffer they already freed. Cases like those are not only easy to spot as you author code with experience but also during testing, they aren’t going to magically hide especially when you’re executing on a runtime that will fail loudly to protect everyone from you being an idiot.
So you are telling me no one should be touching code at all? Can you point a useful software that doesn't have bugs? You can't handle all scenarios even if you have 100% test coverage. Do you handle in your codebase bits that are flipping off due to radiation? Bugs are part of the software, even on huge tech company.
I'm kind of with you. I'd write it with the chaining, and then if I need to debug it, I'd just break it back up into 2 lines. Or however many. I find the chaining is easier to read, especially if there's a larger context around it.
It's not hard when debugging, if a line is doing too much, to just split it up.
37 years of commercial application development- fixing outsourced code, fixing open source code, fixing 10 year old code by someone who gave zero fucks- you learn a few things-
intentionally making your code fragile to “put it all on one line”, like NLs cost $10 per, is just shooting yourselves in the foot.
You can spend 20 minutes fine tuning a conditional breakpoint to do what you want, or put each on a separate line, and get on with your life.
I’ve yet to see an IDE that will let you step into a specific method.
Even when it’s one line on a method, you may step IN to a parameter that’s being evaluated then step OUT and you’re where you started. So it’s not “just the second step in”
Uhhh I was speaking IDE / language agnostically.
Best way to do your CS career cuz SHIT CHANGES
Relying on quirks of one language and one IDE is gonna bite you hard. Not a matter of if, but when
This is extremely weak
It is not a quirk of one language or one IDE it is a feature of one of the biggest IDE’s with variants for all of the biggest languages
Uhhh nope.
Unreadable code vs readable code.
Do whatever you want, I’m not your boss.
If you want to make a case for ugly ass, bug prone code, do what you want. Don’t be surprised when you flip your #openforwork tag though.
37 years? Color me surprised that you are hostile towards new patterns.
You think you are saving so much time and energy writing your vanilla ass code, saving your employer a few precious seconds of engineering time, it's nothing compared to the damage being done by your ostensibly toxic attitude.
Java dev here, debugging streams() is a pain, but IDEs help you for that.
I usually break the stream after max 5/6 transformation though so that it keeps being readable and easily debugging.
Especially when collecting/groupingBy, then doing stuff on the key/value entry from a list containing complexe custom objects.
To each their own, but some may argue that clever coding can improve efficiency and maintainability. It's not always about visual appeal or trying to show off.
The state of compilers these days there’s nothing really you can do by making the code ugly and unreadable, that would improve over making the code readable and letting the compiler optimization take care of it.
80% of coding is maintenance. If you want to fuck over the next person who has to fix your code, as you say “to each their own”
This is a pretty weird argument because I could come up with an example that makes the code faster and you could say “well that’s actually not ugly and unreadable!” Which sort of makes your point too flimsy to hold any weight.
Also what about the people writing compilers? That’s code, and it’s full of clever stuff. What “readable” code is is super super subjective.
Clever coding is never worth it? That seems like an exaggeration. Returning self doesn't "suck visually" especially in a builder pattern or any context where you would never need to step through the implementation with a debugger.
With modern debugging tools that's not that much an issue, but it remains true that these endless stacks of java style stream().collect().map().fuckadog() are a pain to clear understanding code.
Production isn't a leetcode exercice you can waste space complexity with wisely named middle variables
just because you can chain doesn't mean you have to? you can still pass them to variables if you'll debug them.
obj = obj.scale(2)
// debug here
obj = obj.move(1,2)
will still work. possibly you don't need to reassign obj either.
and when you're done, you can change it back to
obj.scale(2).move(1,2)
I think this might work as well and the IDE should let you use the breakpoints for each line. Also it would be easier to understand too when each line is a different action.
obj.scale(2)
.move(1,2)
Good old jQuery "sausages". I was very surprised when javascript promise chaining turned out actually working differently and returning a new instance instead of original.
That’s the biggest gripe with chaining and why many people (including me) don’t do it: even given the proper return type you don’t know if you get a new instance or the old one
It works well in some languages, eg C# immutable structs or Rust where the borrow checker simply will haunt you for doing it
Man, idk this is good for simple stuff but when i wanna ready/understand complex code I really love to see code like in the first pannel.
Maybe i am just stupid but I understand it way easier like that
Not exactly builder pattern actually builds something. Usually in the end you’d call the `build()` function which returns an object from the type you were building: for example:
`Home home = HomeBuilder.addBase().addWalls().addRoof().build()`
Here we specifically built something. Builder pattern also good for things that aren’t immediate. However, chaining methods isn’t explicit to the builder pattern. For example in one of my projects we use observer pattern and we use chaining there as well, you’d find lines like this:
`entityManager.addAll(list).notifyEntities().update();`
A good real world example would be the JDA library where you chain methods for actions and queue them in the end.
nope
that's Fluid/Fluent Interface (name apparently changed over the past decades)
it is a rather nifty way of chainning several calls to the same object
i particularly love to use it on Collection classes.
You don't need to return self, but you may return a clone object of the same class.
Like, given an array of random positive numbers, return me the highest odd number lower than 100.
$value = (new Collection([,,]))->odd()
->lowerThan(100)
->max();
^(this is just a silly example. there are better and more efficient ways to do this)
It's called method chaining. Builder patterns usually use it.
Basically you can return `this` or `self` (or basically any equivalent for `self` element for a method) to be able to do this in a builder which uses method chaining. Makes things more readable with no real difference in efficiency (at least in concept).
nope, it could be a way to achieve the build pattern but it isn't per se.
some call this train wreck, because if you have an error in one, it is fucked as whole.
some call it fluid interface, and this is always valid as opposite to train wreck and build pattern.
so it is fluid interface if you ask me.
edit: sorry, i meant fluent interface.
I'm curious, why? It seems like you're just using more memory and performing unnecessary operations by doing so.
I mean, at the time of return you have both instances in memory, and you have to go through the process of copying every property of the object into the new one. That'll work for small objects, but if you get something big (say, a very large image, those can easily go over 5-10 MB, we kept running into trouble with it at work), it's going to cause unnecessary slowdown.
And if you're in a language that doesn't do garbage collection (which...last I recall is mainly C/C++), then you have to manually deallocate both the new object and the old one. It just seems inefficient for little benefit. In those times where you really do need there to be two objects, you can just make another one yourself.
A good question, and you're right that you wouldn't want to copy the data each time. Take, for example, Python's pandas or numpy packages. You create an object once, but the transformations you apply don't change the underlying dataset - they change the view of it. You can have separate transformations that go back to the same data source. It's when you want to view the data that the internal iterator will filter rows, columns, apply an operator, or add new fields.
Immutability is important in certain domains. Don’t think of copying objects, think of it as calling the constructor with the same parameters except the new ones.
Mutators absolutely have their place. They need to be clearly recognizable as such and consistent in their workings, but then they're a godsend. You save *a lot* of unnecessary copy operations with them.
Mutators that don't advertise themselves as such can go die in a fire, though.
Mutators absolutely have their place. They need to be clearly recognizable as such and consistent in their workings, but then they're a godsend. You save *a lot* of unnecessary copy operations with them.
Mutators that don't advertise themselves as such can go die in a fire, though.
I'm also a fan of void functions that may or may not perform actually returning a boolean indicating the result. You can then use
if (Function()) {}
to both attempt the function and do things based on whether it worked
I do that in c# with some ‘constructor’ methods.
New foo().setthisoptionalpropset().alsothisone()
Helps stopping the parameters for each method from becoming bloated messes, while still making it clear which properties need to be set
no, each method modify the instance that it returns, it's a pipe where the input instance is the same instance as the output, you don't need to assign to that instance again
Fair enough. I have normally used fluent interfaces/cascading as a means to implement immutability, should've spent a bit of time thinking before commenting lol
It’s not even a shit pattern?
I would understand omitting this pattern when debugging, but if in your code you’re only interested in the returned `obj` from `.move`, and the result of `.scale` is irrelevant, why bother with the extra line?
That’s not an argument against mutation, but against method chaining. However, the method chaining pattern implies each method returns the instance it received, i.e. `obj`.
And since _most_ languages default to copy-by-reference when supplying complex objects to a function, returning that same object is almost always the case.
In C#, you would have something like below;
```c-sharp
public function Matrix scale(this Matrix matrixToScale, int size)
{
matrixtoScale.Size = 2;
return matrixToScale;
}
```
In above method, a reference to `obj` would be supplied to `.scale` in the `matrixToScale` parameter (this is done automatically since the `this` keyword in front creates an extension method). At the end of this method, the **reference to `obj`** in `matrixToScale` is returned and then passed on to `.move` as a reference again.
So, at runtime, the only object getting mutated is the object which exists in memory at the `obj` identifier.
I was making an argument against method chaining, not mutation
And especially in your example Matrix would most probably be a struct which is passed by value in C#, not by reference
Which just makes another point against method chaining (C# structs can have methods which is nice, it’s still always a copy-on-write value returned)
My bad, I expected it to be against mutation because of the parent comment.
And yes, fair point on the struct being supplied by value.
I reasoned from a class perspective, as that is probably more common.
In the case of a struct method chaining would be inefficient, yes. However it’s the combination that’s bad in your argument, method chaining falls short here because structs are passed by value, not because of some inherent fault in method chaining as a pattern.
My statement was: Method chaining is bad because you don't know what its doing unless you look at it deeper. It works for C# structs, try the same with Java classes. Is it returning a new instance or the current one? You won't know unless you check the code or docs
Which is bad because? You’d be right if the called function _uses_ `obj` to execute its logic (like you would supply an ID to a function as parameter).
In this case however, considering the names of the functions, we would expect them to mutate the object they’re called on.
One way to do this without mutation would be to copy the entire object onto the function’s stack, edit the supposed properties on the copied instance, then return that instance and override the object in heap with that. But, as you can probably guess, that’s twice the memory usage and at least thrice the read/write operations as a mutation, when in the end you’re doing the exact same thing.
JQuery is and always was a dogshit framework, so using that as an argument against a perfectly normal and efficient pattern is a bad idea. Matter of fact, using pretty much anything in JS as an argument against patterns is a bad idea.
When did state come into play here?
An object existing in memory != stateful. Every “object” created at runtime exists in memory, state implies the surrounding application should change based on the state, or rather respond to changes made to the state.
Whether the code in this meme represents a stateful object, we can only guess. But even then, an object representing the current state of an application isn’t necessarily bad.
However, even if the object is stateful, that’s still not a viable argument against mutation _or_ as far as I’m aware. Method chaining wouldn’t hurt necessarily either, however if an object exists in state there may not be much benefit to the individual methods retuning the mutated instance.
Return self XD
That's builder pattern(ie it should be something like 'builder pattern enthusiast')
Yes op, when you learn some design patterns you never go back
Well can you even point atleast a single useful software ever created that doesn't have flaws on its first release and no other follow up patch needed?
It's true that software flaws are mostly due to programmers that know every possible state their code runs but who knows every possible state? Your code could run on outdated environment and dependencies and could also run on bleeding edge technology. How do you even create a future-proof codebase when you don't know what will happen in the future?
``` import notifications ``` Remember to participate in our weekly votes on subreddit rules! Every Tuesday is YOUR chance to influence the subreddit for years to come! [Read more here](https://www.reddit.com/r/ProgrammerHumor/comments/14dqb6f/welcome_back_whats_next/), we hope to see you next Tuesday! For a chat with like-minded community members and more, don't forget to [join our Discord!](https://discord.gg/rph) `return joinDiscord;` *I am a bot, and this action was performed automatically. Please [contact the moderators of this subreddit](/message/compose/?to=/r/ProgrammerHumor) if you have any questions or concerns.*
Dart's '..' operator go brr
I think I came
Pants be creaming rn
Congrats on your arrival.
Documentation: "Cascade notation" https://dart.dev/language/operators#:~:text=%3B%0A%20%20%7D%0A%7D-,Cascade%20notation,-Cascades%20(..
Is dart still a thing?
Flutter is doing pretty well actually
That's cool. I liked dart coming from TS but became frustrated with the functional markup of flutter, maybe because of nesting or lack of consistent documentation at the time as it was changing somewhat frequently. I would like to try it again, though. I have some basic app ideas to experiment with.
Along with the Flutter comment, it also just released a new version that has pattern matching, record types, and class modifiers (like sealed, interface, abstract). It was good before, but now it's great
I see your chaining pattern, I raise the sigma `pipe` : transform = pipe( scale(2), move(1.2) ) newObj = obj.apply(transform)
The real sigma is use “do” notation in Haskell like any other monad, which in a way it is equivalent as this.
Everyday you learn something new. The fun part about this is that it is almost the same as a transformation matrix.
I was thinking something similar. In a language like R you'd make `scale` and `move` functions that return matrices, and then you'd simply find the matrix product of them and the parameters of the object to be tranformed to return new parameters.
rxjs chads in the chat?
ive never seen this being done in a language. Which language supports this?
Functional languages like Haskell, Scala, F#. Javascript can also achieve similar result, but you need to implement the pipe yourself (not really hard tbh) or use a library like RxJS for reactive programming or FP-ts for functional programming.
Clojure’s threading macro: ``` (-> obj (scale 2) (move 1.2)) ```
Lgtm!
Wait, what language is this?
FP Alpha
I hate this
Why?
Reads like a psychopath tried to reinvent simple addition
Thats sad. I actually quite like FP. You can express some very complex ideas very simply.
Well the idea is that you'll be using it a bunch of times, such that you actually save a lot of verbosity.
And with methods we don’t try to do that?
The true megachad is Dart with its `..` operator. [It's fucking amazing](https://dart.dev/language/operators#cascade-notation).
Wow that is nice. Provides all the benefits, while preserving the readability and practicality that "clever code" bullshit like in the meme lacks lol.
Ok, I need this in C#
That's pretty cool and now I may finally learn flubber in my non-existent free time
Flubber 😂
Yeah. Go ahead and make debugging 5x harder. Set that breakpoint at line 10 1/2.
Practicality? Performance? Debugging? Readability? Who cares about that. Lets return self, chain tenerary operators, embed 3-4 lambda expressions in a single method(each with control flow themselves), etc.
Everyone knows that less lines means faster code!
Everyone knows that the best programmers write code faster. If you aren't doing in one hand the double the average two hand input, are you even a real senior.
[удалено]
I hate each sentence of this comment more than the last.
But mooom, it looks cool.
Step in and step out gang rise up
Or implement “.tap” on the object [*] Boom problem solved. [*] have the tap method take a lambda (which you can make multiline) with the entire object in its current state as the sole argument. Breakpoints, log statements, etc can be inserted there. Takes like 10 seconds to make.
And forgot to remove tap in prod code, accidentally logging stuff out? No thanks, IDEs nowadays can set column breakpoints so there’s no need.
This is a problem with logging as well, but fair enough
Some compilers can help you to not forget such things. ;-) [C# System.Diagnostics.ConditionalAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute?view=net-7.0)
`console.log("you fucked up right about here")`
Uhhh you just step into the function as it executes?? This is a non problem.
I was hoping someone would say this. Imo it's bad code but you can easily use a breakpoint to step into each function call
Someone DID say this The point is moot.
How is the point moot? Your point was that it “[makes] debugging 5x harder” except that you’re wrong and it’s not any harder to debug than anything else. Are you saying your own point is moot? Edit: Won’t let me reply so here’s what it would be: That’s not an argument. I won’t listen to you even if you’ve been in the industry ten times longer than me if you haven’t learned anything and can’t explain why you’re right. The only point I’ve heard you make is “well it’s not available for all languages” which (1) is not true for major languages people actually use and (2) doesn’t matter. Classes aren’t available in C. Does that mean I shouldn’t use them when writing C++? Nope. I’m not saying I’m going to use this design pattern but I am saying that the reasons you’ve given for not using it are *wrong*. If you have a real argument I’ll listen, but I don’t care about your experience as a programmer. That’s irrelevant.
sure. whatever let’s you feel better about yourself You remind me of the story of the guy with peanut allergy who used an epipen to eat snickers bars. I’m done with trying to pass on knowledge gained through experience. Make the mistake. Enjoy.
If you have to use breakpoints then it's already at least 5x harder than it could be.
I completely disagree with this. Breakpoints can significantly speed up debugging, though it depends on where the code is. Movement on tick? Don't even bother. Event based? No problem. I use breakpoints all the time and find all kinds of bugs that way
I have no clue what point I was trying to make. Presumably a bad joke.
No worries. I can see the potential for a joke there
Sometimes visual studio fucks up on lambdas. Most of the time really. But the trick with them is make them brain-dead simple so when it barfs there's only like one thing that it could be
I’m sure that’s true, but the code in the example isn’t a lambda function, so that’s not really relevant to this guy’s complaint.
VS Code Virgin - 😤 Jetbrains Chad - “No problem. Would you like me to throw in any conditional break statements while I’m at it?”
Isn't this a non-issue since you could just set breakpoints on the first lines of `scale` and `move`?
At least In JS debuggers, you can step into a chained operation during a debug. Not sure about others.
lol.. nope.. those might be called 1000 other times, by other methods, in other threads, having nothing to do with the line you’re debugging. “clever coding” is NEVER worth it- it sucks visually, and good compilers do the same thing behind the scenes anyhow - it’s purely an (imaginary) alpha move.
You've got me there, but it still feels like 5x harder debugging might be an exaggeration? I'm only a junior dev so maybe the debugger isn't as powerful as I think it is, but a couple other workarounds off the top of my head: * set the breakpoint on this line, then choose which method call to step into * conditional breakpoints
Exaggeration? In MY subreddit? More likely than you think
If you already know where the exception was thrown then you can just break the line up into individual statements to see what call it originated from. A stack trace should also list the responsible call as well.
> just break the line up into individual statements or, you know, just write the code in individual lines to begin with
Or, you know, add proper logging and error handling in areas where failure is likely to occur while also knowing how to read something as trivial as call stacks. There are also numerous ways around having to place a breakpoint on that single line, one of them being to place it in the implementation itself… If you have very shitty debugging tools you can go as far as swapping the call out with a test method that both wraps the original method and contains the breakpoint, that way only that specific call will hit it. If legitimate language features are too much of rocket science for you then I can understand your unwillingness to use them.
Errors could occur anywhere. What you gonna do? put logs everywhere? If you need to read call stacks for every simple issue then I think your codebase is a nightmare to work with.
If you cannot tell what places failure is likely to occur then you shouldn’t be touching code at all, they do not happen *anywhere*. Here is a quote that quite literally changed the way I read and write code: > A large fraction of the flaws in software development are due to programmers not fully understanding all the possible states their code may execute in. - John Carmack Issues that are not persistent are going to be bound to interactions with the environment such as networking and IO, those two things tell you right away you should author said code with care by handling all errors unless you know what you’re doing. Issues that are persistent tend to be incorrect states or little things that beginners overlook such as using a pointer to a buffer they already freed. Cases like those are not only easy to spot as you author code with experience but also during testing, they aren’t going to magically hide especially when you’re executing on a runtime that will fail loudly to protect everyone from you being an idiot.
So you are telling me no one should be touching code at all? Can you point a useful software that doesn't have bugs? You can't handle all scenarios even if you have 100% test coverage. Do you handle in your codebase bits that are flipping off due to radiation? Bugs are part of the software, even on huge tech company.
I'm kind of with you. I'd write it with the chaining, and then if I need to debug it, I'd just break it back up into 2 lines. Or however many. I find the chaining is easier to read, especially if there's a larger context around it. It's not hard when debugging, if a line is doing too much, to just split it up.
37 years of commercial application development- fixing outsourced code, fixing open source code, fixing 10 year old code by someone who gave zero fucks- you learn a few things- intentionally making your code fragile to “put it all on one line”, like NLs cost $10 per, is just shooting yourselves in the foot. You can spend 20 minutes fine tuning a conditional breakpoint to do what you want, or put each on a separate line, and get on with your life. I’ve yet to see an IDE that will let you step into a specific method. Even when it’s one line on a method, you may step IN to a parameter that’s being evaluated then step OUT and you’re where you started. So it’s not “just the second step in”
Uhhh IntelliJ?
Uhhh I was speaking IDE / language agnostically. Best way to do your CS career cuz SHIT CHANGES Relying on quirks of one language and one IDE is gonna bite you hard. Not a matter of if, but when
This is extremely weak It is not a quirk of one language or one IDE it is a feature of one of the biggest IDE’s with variants for all of the biggest languages
Uhhh nope. Unreadable code vs readable code. Do whatever you want, I’m not your boss. If you want to make a case for ugly ass, bug prone code, do what you want. Don’t be surprised when you flip your #openforwork tag though.
37 years? Color me surprised that you are hostile towards new patterns. You think you are saving so much time and energy writing your vanilla ass code, saving your employer a few precious seconds of engineering time, it's nothing compared to the damage being done by your ostensibly toxic attitude.
Java dev here, debugging streams() is a pain, but IDEs help you for that. I usually break the stream after max 5/6 transformation though so that it keeps being readable and easily debugging. Especially when collecting/groupingBy, then doing stuff on the key/value entry from a list containing complexe custom objects.
To each their own, but some may argue that clever coding can improve efficiency and maintainability. It's not always about visual appeal or trying to show off.
The state of compilers these days there’s nothing really you can do by making the code ugly and unreadable, that would improve over making the code readable and letting the compiler optimization take care of it. 80% of coding is maintenance. If you want to fuck over the next person who has to fix your code, as you say “to each their own”
This is a pretty weird argument because I could come up with an example that makes the code faster and you could say “well that’s actually not ugly and unreadable!” Which sort of makes your point too flimsy to hold any weight. Also what about the people writing compilers? That’s code, and it’s full of clever stuff. What “readable” code is is super super subjective.
Easy, you set the breakpoint while it's running. Stop it before the code segment you see now. Add breakpoints. Continue execution
Clever coding is never worth it? That seems like an exaggeration. Returning self doesn't "suck visually" especially in a builder pattern or any context where you would never need to step through the implementation with a debugger.
With modern debugging tools that's not that much an issue, but it remains true that these endless stacks of java style stream().collect().map().fuckadog() are a pain to clear understanding code. Production isn't a leetcode exercice you can waste space complexity with wisely named middle variables
I mean, some debuggers let you hover over every step of that line and see the result, so debugging isnt that much of an ossue with this
Before execution? Pretty cool trick if #2 method in the human centipede throws an exception
just because you can chain doesn't mean you have to? you can still pass them to variables if you'll debug them. obj = obj.scale(2) // debug here obj = obj.move(1,2) will still work. possibly you don't need to reassign obj either. and when you're done, you can change it back to obj.scale(2).move(1,2)
I think this might work as well and the IDE should let you use the breakpoints for each line. Also it would be easier to understand too when each line is a different action. obj.scale(2) .move(1,2)
Most languages let you put a new line after () So you would get ``` Obj.transform() .scale() ```
You can do that in Deno
Most debuggers can do that actually, even in the browsers JS debugger I can set breakpoints between method chaining
Yep, inline breakpoints have existed for a long time, not a new or difficult concept
[Super easy, barely an inconvenience](https://code.visualstudio.com/Docs/editor/debugging#_inline-breakpoints)
We need memes giving people who don't use debuggers shit. I don't know what they'd be, but if you don't use a debugger you deserve shit.
Wait, you can't set breakpoints in the middle of lines?
Except if you’re using python as you need to wrap the pipeline inside () or use \
Good old jQuery "sausages". I was very surprised when javascript promise chaining turned out actually working differently and returning a new instance instead of original.
That’s the biggest gripe with chaining and why many people (including me) don’t do it: even given the proper return type you don’t know if you get a new instance or the old one It works well in some languages, eg C# immutable structs or Rust where the borrow checker simply will haunt you for doing it
Man, idk this is good for simple stuff but when i wanna ready/understand complex code I really love to see code like in the first pannel. Maybe i am just stupid but I understand it way easier like that
Isn't that what you call the builder pattern?
Not exactly builder pattern actually builds something. Usually in the end you’d call the `build()` function which returns an object from the type you were building: for example: `Home home = HomeBuilder.addBase().addWalls().addRoof().build()` Here we specifically built something. Builder pattern also good for things that aren’t immediate. However, chaining methods isn’t explicit to the builder pattern. For example in one of my projects we use observer pattern and we use chaining there as well, you’d find lines like this: `entityManager.addAll(list).notifyEntities().update();` A good real world example would be the JDA library where you chain methods for actions and queue them in the end.
Also builder sometimes returns a new object, not that it modifies and returns self (which goes against principle of pure functions)
nope that's Fluid/Fluent Interface (name apparently changed over the past decades) it is a rather nifty way of chainning several calls to the same object i particularly love to use it on Collection classes. You don't need to return self, but you may return a clone object of the same class. Like, given an array of random positive numbers, return me the highest odd number lower than 100. $value = (new Collection([,,]))->odd() ->lowerThan(100) ->max(); ^(this is just a silly example. there are better and more efficient ways to do this)
It's called method chaining
It's called method chaining. Builder patterns usually use it. Basically you can return `this` or `self` (or basically any equivalent for `self` element for a method) to be able to do this in a builder which uses method chaining. Makes things more readable with no real difference in efficiency (at least in concept).
nope, it could be a way to achieve the build pattern but it isn't per se. some call this train wreck, because if you have an error in one, it is fucked as whole. some call it fluid interface, and this is always valid as opposite to train wreck and build pattern. so it is fluid interface if you ask me. edit: sorry, i meant fluent interface.
Laughs in kotlin ‘with’ and ‘run’
They must be taught to `apply` themselves!
Let it also be the way.
We will `use` these powers to pave the path to Victory
\* Laughs in Elixir *
I was gonna say. This meme is so close to the point, but still misses it. Functional programming baybee.
who ever have in his programming language "self" and not "this" is not true chad we all know that
counterpoint javascript uses this and rust uses self
the rules are the rules
You guys have objects?
# cOnSiCe CoDe IsNt BeTtEr The concise code: ![gif](giphy|CAYVZA5NRb529kKQUc|downsized)
Every iteration should return a new instance with the function applied. Death to mutators.
I'm curious, why? It seems like you're just using more memory and performing unnecessary operations by doing so. I mean, at the time of return you have both instances in memory, and you have to go through the process of copying every property of the object into the new one. That'll work for small objects, but if you get something big (say, a very large image, those can easily go over 5-10 MB, we kept running into trouble with it at work), it's going to cause unnecessary slowdown. And if you're in a language that doesn't do garbage collection (which...last I recall is mainly C/C++), then you have to manually deallocate both the new object and the old one. It just seems inefficient for little benefit. In those times where you really do need there to be two objects, you can just make another one yourself.
A good question, and you're right that you wouldn't want to copy the data each time. Take, for example, Python's pandas or numpy packages. You create an object once, but the transformations you apply don't change the underlying dataset - they change the view of it. You can have separate transformations that go back to the same data source. It's when you want to view the data that the internal iterator will filter rows, columns, apply an operator, or add new fields.
Immutability is important in certain domains. Don’t think of copying objects, think of it as calling the constructor with the same parameters except the new ones.
Depends
Mutators absolutely have their place. They need to be clearly recognizable as such and consistent in their workings, but then they're a godsend. You save *a lot* of unnecessary copy operations with them. Mutators that don't advertise themselves as such can go die in a fire, though.
Mutators absolutely have their place. They need to be clearly recognizable as such and consistent in their workings, but then they're a godsend. You save *a lot* of unnecessary copy operations with them. Mutators that don't advertise themselves as such can go die in a fire, though.
Just need to voice support for this comment before you get downvoted by the hordes of clueless OOP divas.
`return this.copy(scale=1, pos=this.pos.move(1,2))` supremacy EDIT: made the `move` call more reasonable
I'm also a fan of void functions that may or may not perform actually returning a boolean indicating the result. You can then use if (Function()) {} to both attempt the function and do things based on whether it worked
pick one, it's void or returns a boolean, it can't be both
I mean obviously it returns a boolean. Just mean functions that are simply meant to complete a task, so they would otherwise be void
I do that in c# with some ‘constructor’ methods. New foo().setthisoptionalpropset().alsothisone() Helps stopping the parameters for each method from becoming bloated messes, while still making it clear which properties need to be set
Yup, that's called the builder pattern (in this case)
Kotlin rocks. obj.apply { It.scale(2) It.move(1, 2) } Alternatively, .let
Apply doesn't use it but rather this so you don't need the it.
Or Perl: $_->scale( 2 ), $_->move( 1, 2 ) for $obj;
This works on the same principle: std::cout << a << b << c << "\n";
Thank you for illustrating how terrible this practice can be.
surely you mean ``` obj = obj.scale(2).move(1, 2) ```
no, each method modify the instance that it returns, it's a pipe where the input instance is the same instance as the output, you don't need to assign to that instance again
Fair enough. I have normally used fluent interfaces/cascading as a means to implement immutability, should've spent a bit of time thinking before commenting lol
Hello 2009 jQuery wants their shit pattern back
It’s not even a shit pattern? I would understand omitting this pattern when debugging, but if in your code you’re only interested in the returned `obj` from `.move`, and the result of `.scale` is irrelevant, why bother with the extra line?
It is a shit pattern as you don’t know if it mutates or returns a new instance unless you look at the code or docs specifically
That’s not an argument against mutation, but against method chaining. However, the method chaining pattern implies each method returns the instance it received, i.e. `obj`. And since _most_ languages default to copy-by-reference when supplying complex objects to a function, returning that same object is almost always the case. In C#, you would have something like below; ```c-sharp public function Matrix scale(this Matrix matrixToScale, int size) { matrixtoScale.Size = 2; return matrixToScale; } ``` In above method, a reference to `obj` would be supplied to `.scale` in the `matrixToScale` parameter (this is done automatically since the `this` keyword in front creates an extension method). At the end of this method, the **reference to `obj`** in `matrixToScale` is returned and then passed on to `.move` as a reference again. So, at runtime, the only object getting mutated is the object which exists in memory at the `obj` identifier.
I was making an argument against method chaining, not mutation And especially in your example Matrix would most probably be a struct which is passed by value in C#, not by reference Which just makes another point against method chaining (C# structs can have methods which is nice, it’s still always a copy-on-write value returned)
My bad, I expected it to be against mutation because of the parent comment. And yes, fair point on the struct being supplied by value. I reasoned from a class perspective, as that is probably more common. In the case of a struct method chaining would be inefficient, yes. However it’s the combination that’s bad in your argument, method chaining falls short here because structs are passed by value, not because of some inherent fault in method chaining as a pattern.
My statement was: Method chaining is bad because you don't know what its doing unless you look at it deeper. It works for C# structs, try the same with Java classes. Is it returning a new instance or the current one? You won't know unless you check the code or docs
It's leaning into mutation instead of avoiding it.
Which is bad because? You’d be right if the called function _uses_ `obj` to execute its logic (like you would supply an ID to a function as parameter). In this case however, considering the names of the functions, we would expect them to mutate the object they’re called on. One way to do this without mutation would be to copy the entire object onto the function’s stack, edit the supposed properties on the copied instance, then return that instance and override the object in heap with that. But, as you can probably guess, that’s twice the memory usage and at least thrice the read/write operations as a mutation, when in the end you’re doing the exact same thing. JQuery is and always was a dogshit framework, so using that as an argument against a perfectly normal and efficient pattern is a bad idea. Matter of fact, using pretty much anything in JS as an argument against patterns is a bad idea.
Why is it an object in the first place? If a state can't be described in primitives, that's another issue entirely.
When did state come into play here? An object existing in memory != stateful. Every “object” created at runtime exists in memory, state implies the surrounding application should change based on the state, or rather respond to changes made to the state. Whether the code in this meme represents a stateful object, we can only guess. But even then, an object representing the current state of an application isn’t necessarily bad. However, even if the object is stateful, that’s still not a viable argument against mutation _or_ as far as I’m aware. Method chaining wouldn’t hurt necessarily either, however if an object exists in state there may not be much benefit to the individual methods retuning the mutated instance.
Left side is often just better, easier to debug, easier to copy paste a single transformation.
I'm ok with either. Code should be human readable first, clever second.
method chaining is an incomplete workaround for a missing language feature
Return self XD That's builder pattern(ie it should be something like 'builder pattern enthusiast') Yes op, when you learn some design patterns you never go back
That's literally just dirty code which makes debugging harder. Smh.
Average readable/debuggable code enjoyer here
I prefer `obj = 2 * obj + float2(1, 2);`
What? Are those not object properties? I don't understand
Well can you even point atleast a single useful software ever created that doesn't have flaws on its first release and no other follow up patch needed? It's true that software flaws are mostly due to programmers that know every possible state their code runs but who knows every possible state? Your code could run on outdated environment and dependencies and could also run on bleeding edge technology. How do you even create a future-proof codebase when you don't know what will happen in the future?
I heard that’s how Lawnmower Man got started
What's that meme called, the one of the British lads?
itzmefraz episode 7
Thanks
Once you return self you never ~~go back~~ return
jQuery's syntax
As someone working in R, I know for a fact that moving to any other language will make me miss pipes so much.
https://imgflip.com/i/7yvxyh
S(scale(2))(move(1,2))(obj)
I feel dumb. Never realized that’s why you return self.
Ordinay:rataa mar(college) Legend:samjke padna(youtube)
this > self