Is Clean Code Really That Bad For Performance?

  Рет қаралды 90,493

Nick Chapsas

Nick Chapsas

3 жыл бұрын

Become a Patreon and get source code access: / nickchapsas
Check out my courses: dometrain.com
Hello everybody I'm Nick and in this video I will address some of the comments that I get all the time around the refactoring that I apply to my code. Creating classes, instantiating obejcts and extracting methods are common practices when you're refactoring code but I got many questions regarding the performance implications of such operations. In this video I will address the 2 major ones.
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasGitHub
Follow me on Twitter: bit.ly/ChapsasTwitter
Connect on LinkedIn: bit.ly/ChapsasLinkedIn
Keep coding merch: keepcoding.shop
#code #performance #cleancode

Пікірлер: 289
@nickchapsas
@nickchapsas 3 жыл бұрын
Hey everybody! Looking at the initial example (with the nested loops) again, I can see how it might not look "cleaner" to everyone, especially since I did a mistake during extracting and I over-extracted the second method which in hindsight wasn't needed. This was only done so we have at least 2 methods extracted for demo purposes. The point of extracting methods to smaller logical pieces still stands in spite of that but the example that I picked was not a great one. Sorry for that.
@CRBarchager
@CRBarchager 3 жыл бұрын
@Templar Royston Of Vasey Besides Nick here, I'd recommend Tim Corey (Iamtimcorey) if you want real life application development. If you want to go to look more hardcore of what happens in the memory when you call different methods I'd recommend JamieKing
@alansinoracki8508
@alansinoracki8508 3 жыл бұрын
@@CRBarchager Raw Coding is also a quality one for c#
@rafaelgil6895
@rafaelgil6895 3 жыл бұрын
Nice video! Just need to keep in mind that Spaguetti code is bad, but too many abstractions can be a pain to maintain as well. Sometimes a nested loop can be a lot easier to understand than a code so abstract that you need a debugger just to understand what's going on. I think Simpler comes before Cleaner. (Usually clean code is simpler, so I'm not saying you should stop doing clean code).
@jakedewey3686
@jakedewey3686 Жыл бұрын
Too many layers of abstraction causes is its own kind of spaghetti; in both cases you have to spend forever figuring out where you even need to look to figure out what your code is doing.
@VasiliSyrakis
@VasiliSyrakis 3 жыл бұрын
You know what's really slow? Troubleshooting a customer-impacting bug, in spaghetti code, in prod.
@nilstrieb
@nilstrieb 3 жыл бұрын
That's the most important thing!
@JackMott
@JackMott 3 жыл бұрын
Where I work, we have had a great deal of success, which means a huge amount of traffic. Endpoints that are too slow are an existential threat to our business, as it can bring us down. There are times when performance is not an important issue, but please don't pollute discussion about it with comments like these as if performance is never important.
@WashingtonFernandes
@WashingtonFernandes 3 жыл бұрын
lol, true
@dtkedtyjrtyj
@dtkedtyjrtyj 3 жыл бұрын
@@JackMott Please don't pollute discussion about clean code with comment like these as if performace is always supremely important. The clean code way to do perfomance is to do performance testing and making the fixes where it is important; asking "Does clean code make my code slower?" shows a lack of understanding of what clean code means. Your fast endpoints can be the worst spaghetti code ever and if your testing reveals that it is the fastest way to do it _and_ that the speed is necessary; it _is_ clean code. If it is spagetti code and you've done it that way "because faaaaaast!"; then not only is your code dirty, it is slower than the clean code version would be.
@abeplus7352
@abeplus7352 3 жыл бұрын
@@JackMott use lambda . Problem solved
@robertkomarek8615
@robertkomarek8615 3 жыл бұрын
Hey Nick, great Videos! Sometimes I watch ur Videos just for motivation. U really seem to love coding. That's very encouraging! All the best! Rob
@kblyr
@kblyr 3 жыл бұрын
I'm always wondering if refactoring makes my apps slower, and you answered it. You've got my like and subscribe, this is really helpful, thanks!
@chefbennyj
@chefbennyj 3 жыл бұрын
Videos showing the implementation of principals while refactoring are definitely worth watching.
@ajcroteau0928
@ajcroteau0928 3 жыл бұрын
Clean code to me has always been about maintainability and readability especially when I know other developers may be having to support my projects or looking at my code for inspiration on solving a problem they might be having... good to know it’s not affecting performance all that much.
@namesome4980
@namesome4980 Жыл бұрын
except it does its just that nick's video is badly made and doesnt show a proper exmaple: kzbin.info/www/bejne/qnWYf6Wbq6unmLc
@jordixboy
@jordixboy Жыл бұрын
@@namesome4980 was about to send the same vid lol
@shapermechanist
@shapermechanist Жыл бұрын
i remember when my teacher told me to not use "go to" just because it didn't made my code "readable", she ignored all my objections about the performance, she didn't care. Thats why we are observing so deep drop in the performance of the software.
@deus_nsf
@deus_nsf Жыл бұрын
@@namesome4980 I don't mean to disrespect you by any stretch of the imagination, but this passionating video you linked talks about C++, I bet .NET optimizes written code when compiling much more aggressively since you don't handle memory management yourself, and the framework does a lot in the background. It's a shame the guy from the video disabled comments...
@gillbates2685
@gillbates2685 Жыл бұрын
​@@namesome4980 @Deus_nsf Actually that Casey guy's video showed an example to sell his course, it doesn't generalize. you can even try the same example in Rust, the difference was barely anything. All he did was making the code less testable and maintainable. How to generalize to real world projects? By optimizing from CPU and memory levels *after* your code is written to be testable and maintainable, yes. By making a list of Clean Code principles then do the opposite of them like what this Casey guy is doing, no. In the former case the questions are "What does the CPU do? how do I make my code utilize these features?" - this is generalizable In the latter case the questions are "what do the Clean Code people do? how do I contradict them?" - this is just unhinged. Also it's kinda crazy how many people believe this guy (or anyone else) can take a software, make them 10-15 times faster by simply making their code contradict some "clean code" guideline. This Casey guy has been advocating this position for decades now, if he were capable of doing that to an arbitrary software and not just two, three specific toy examples he could come up with in the past 10 years, he wouldn't be peddling his game programming courses on youtube. Now I think his work definitely has value and his technical skills are great, he just doesn't seem rational enough to ever see that the results he has don't actually support the strong universal statement he wants to claim but something much weaker.
@trocomerlo
@trocomerlo 3 жыл бұрын
Your content is awesome. So well synthesized, structured and communicated. Thanks!
@Pedro5antos_
@Pedro5antos_ 3 жыл бұрын
I was impressed by the results! Thanks Nick
@bodek321
@bodek321 3 жыл бұрын
Thanks Nick for the next epic coding episode. Amazing as usual. I would like to add something from my experience. When we optimised the code manually, we managed to save milliseconds, but thanks to the team's openness to refactoring, we were able to improve the algorithms and save minutes. Rename something and extract method are the first two that are essential to encourage developers to touch the code "around" my task, which maybe "I should not touch".
@nickchapsas
@nickchapsas 3 жыл бұрын
Hey Bogdan. Yeah, using better algorithms is where the big time saves are. Changing something from an O(n) to an O(1) time complexity not only ensures it's faster now but it will be faster in the future. I feel like the "curse" of the high level managed programming laguages is that people don't have an incentive to care.
@gvanvoor
@gvanvoor 2 жыл бұрын
Always strive to write clean (i.e. easy to maintain) code. If it turns out to be slow when testing, use a profiler to find the bottle neck(s) and optimise those. Unless you’ve been doing this for decades your intuition about what the bottle neck is will probably be different from what the profiler finds. In that case the profiler will be right. This is the case for compiled languages like C, C++, ... but I assume the same holds for code going through a just-in-time compiler.
@jmm00702
@jmm00702 Жыл бұрын
Noob
@RiversJ
@RiversJ Жыл бұрын
In my experience (optimizing hot paths in video games) a few method extractions are usually very tiny, what really kills your performance is cache missed that result from some patterns of clean code where the compiler either A cannot predict which area of memory will next be required B crisscrossing pointers (read: references) especially if the calling function doesn't know what area of memory will be needed for the called function C unnecessary heap allocations, keep anything that is small and only needed temporarily on the stack at all times.
@stephenyork7318
@stephenyork7318 3 жыл бұрын
It’s very subjective about something being slower just because there are methods used. In c /c++ there can be a performance hit but ultimately it comes down to whether it matters or not. For average business apps doing a single call that has a few methods is not going to cause issue s. It if you use that that algorithm in a method looping over 1m records then yeah you may face issues. But then it still depends. I love your demo out the process of benchmarking, so you can really determine for sure if you’re affecting performance. It’s a really clean way to check. Thanks for the video.
@iuryfranklin6765
@iuryfranklin6765 3 жыл бұрын
I'm from Brazil and I follow all the videos, very good!
@Pedro5antos_
@Pedro5antos_ 3 жыл бұрын
Brasillllll
@timlong7289
@timlong7289 6 ай бұрын
@Nick I'm glad you made this video, as you do come across as being somewhat performance-obsessed, and while that definitely is needed sometimes, I think in the vast majority of situations it is more important to write clean code. As you have very clearly demonstrated here, the two are not at odds. Inexperienced developers commonly fall into this trap of premature optimization at the expense of clean code, but what a lot of inexperienced developers fail to grasp is this: when it comes to optimization, the compiler is usually better than you! Having spent the last few months working on some decidedly "unclean" code, let me say that it is not a nice edxperience to have to clean up some else's mess. I have had to deal with "arrow code" that goes on for hundreds of lines, and violations of all of the SOLID principles. It is rather depressing to have to deal with that.
@irelandfpv
@irelandfpv 3 жыл бұрын
Great as usual! Also It was nice to see my nickname in the list of people who supports the channel :)
@overclucker
@overclucker 3 жыл бұрын
Excellent points, and even more excellent demonstration!
@AlanDarkworld
@AlanDarkworld 3 жыл бұрын
A good demonstration, and I fully agree with the points made in the video. In real-world scenarios, don't think about whether or not you should extract the method (spoiler: you should!). Instead, if you have to optimize something, think about the runtime complexity of your code (O-Notation) and about smart caching strategies when working with any type of I/O (disk/network/...). Use the right data structure for the right job and have some understanding of their key characteristics. Avoid doing useless work, in particular doing it multiple times. Apply data filters as early as possible. And always always always MEASURE with a profiler, don't guess.
@iwikal
@iwikal 3 жыл бұрын
I was optimizing an image decoding library in Rust the other day, and managed to cut a benchmark in half (from 21ms to 10ms for a 2k hdr image) by reducing the amount of dynamic allocation, without changing the big-O complexity at all. Then, by adding a new API that iterates over the image scanlines instead of returning the whole image at once in one big buffer, I got it down to 7ms. One third of the original time. So when you're memory/cpu bound, things like this can matter.
@johnbarleycorn_
@johnbarleycorn_ 3 жыл бұрын
I work with IBM mainframes and was taught principles specific to the discipline of Data Processing back in the mid-80s (note that this is something that UK universities do not seem to teach as demonstrated by the fact that I have heard many tales of graduates having to be taught the right way of doing things). These are rules which were created in the days when the system you were working on might have kilobytes of memory to work with. One of the more basic rules is that you don't try to second-guess the operating system/compiler, another that you keep as little data in play as possible. Writing a load of code to buffer I/O, for instance, is something that you would not do unless absolutely necessary for the function of the program. Aside from the fact that it adds complexity to the code, even on a PC-based system, a read from a filesystem is going to return a minimum number of bytes (in the form of a block or sector) and therefore forms an automatic buffer that the operating system will maintain for you. Coding to do buffering is therefore an unnecessary overhead that duplicates what the OS is already doing. Working in COBOL, I have come across the argument many times over the years that using the GOTO statement and coding in a more monolithic fashion rather than using a structured procedural approach improves program efficiency. The reality is that the compiler's optimisation blows this argument out of the water. I am one of those people who are perverse enough to have used the IBM compiler's "LIST" option to output the generated assembly language code and be able to understand what it has written. I have seen instances of the compiler moving blocks of code around in order to generate more efficient object code. For example, if there is a procedure called from one place in the program, the compiler can inline the procedure at the calling point in order to remove the call. Attempting to interfere with what the compiler is doing by de-structuring the code in a manner which appears logical to the programmer risks altering the optimiser's decision making process in a negative way with the added expense that the code is less maintainable/understandable. What you have proven here is that these decades old rules still work. The correct way of doing things is to write for structure, readability and maintainability, particularly in a commercial environment where the code will potentially be operated and maintained for many years by people other than yourself. As long as you are writing as clearly and efficiently in the language you are using as you can, it is best just to trust the compiler and operating system to do their jobs as efficiently as they can.
@clickrick
@clickrick 3 жыл бұрын
Summarised as "don't solve a performance problem you haven't got".
@davidmartensson273
@davidmartensson273 Жыл бұрын
In other words, if you KNOW that you can beat the compiler because you understand why the compiler makes the wrong decision, rewrite the compiler :P
@mariosk2139
@mariosk2139 3 жыл бұрын
Very enlightening! we have one less thing to worry about when writing code! I am wondering about boxing/unboxing though, which will come along with more complex 'clean-code scenarios'.
@RichardONeil
@RichardONeil 3 жыл бұрын
Fantastic, as always! Thanks Nick!
@peterfranzmayr3962
@peterfranzmayr3962 Жыл бұрын
Hi Nick. Very nice video. Clean code is not about program running performance, it adresses developer performance.
@stefangranath3841
@stefangranath3841 3 жыл бұрын
This is golden, thank you so much!
@costalino1970
@costalino1970 2 жыл бұрын
Thank Nick for your this video, I would like to ask you, you never check when you extract method if the entry is null before the foreach for instance Regards
@adriankujawski
@adriankujawski 3 жыл бұрын
so we can call it: microseconds wise, weeks in maintenance stupid
@lupf5689
@lupf5689 Жыл бұрын
Writing what's considered "clean code" almost never introduces performance problems. The problem here is the word "almost". If you are handling a few thousand messages/events/entities/whatever per second on a somewhat higher abstraction level, you are most probably fine. Do whatever makes your code easier to understand and maintain. That said, if each of your messages contains a data structure storing a few thousand 3d-points or measurement data of some kind, that have to be processed in a non-trivial way, you are suddenly talking about handling a couple million "things" per second. That's where you probably should start to think a bit about the layout of your data in memory and what processing it actually means. Do you really need to access things via dynamic method calls, reflection or instance methods? Maybe you might want to avoid inheritance, some composition patterns or even start to unroll some loops? Do I really have to throw an expression on 50 million strings or can I maybe rely on bytes 17 and 18 having the values I look for? Given the stuff I work on, these cases are rare but exist. So it's worth knowing that there is at least some overhead involved with some of the practices and patterns.
@NathanFranckGameDev
@NathanFranckGameDev 3 жыл бұрын
If you're using the Unity game engine, you didn't used to get this performance from refactoring. It was significantly faster to not have method calls in loops with lots of iterations. Not sure if that's still the case, since this was in like 2016. Before just accepting performance from someone else make sure you test using your own framework!
@AniProGuy
@AniProGuy 3 жыл бұрын
Love your work! Amazing! :)
@markmanning2921
@markmanning2921 3 жыл бұрын
i have often found that refactoring code reveals ways you can improve the logic of that code and thus make more significant performance boosts. I am a forth programmer and forth teaches you to factor right down to the smallest level so that if you see things like 1 + scattered throughout your code you are encouraged to define : 1+ 1 + ; While that might not be advisable with languages like C i find that factoring code the way you have shown here ALSO makes that code significantly easier to read because instead of having a non descriptive for loop buried in your function you have a calculate_fudge_factor() call describing its purpose. It is also MUCH easier for the optimizer to optimize well factored code than it is for it to optimize cluster bleep code with if/and/but loops nested to the umpteenth level :)
@samysammour9983
@samysammour9983 3 жыл бұрын
It is really unfortunate that you have only 40k followers. Really great video
@arphenti2502
@arphenti2502 Жыл бұрын
Wow, this pop up after Casey’s “clean code, terrible performance”
@cdtje3
@cdtje3 3 жыл бұрын
Great video once again!
3 жыл бұрын
Great video, thank you! I like the pragmatism you showed in this video. :)
@yuehuang3419
@yuehuang3419 3 жыл бұрын
Thanks for the video. I am curious how much the inline vs optimization plays a factor. And how the perf changes with public instead private extracted methods.
@nickchapsas
@nickchapsas 3 жыл бұрын
It wouldn't change since inlining can be performed even if the method is used by multiple sources. The JIT will basically optimize this as much as possible to get the absolute optimal performance.
@davew2040x
@davew2040x Жыл бұрын
I do enjoy that Nick is responding in a thoughtful and data-driven way to a proposition that is, frankly, silly. For most codebases, a clean codebase is the ONLY WAY to get to a performant place, because it quickly becomes impossible to optimize a codebase that nobody understands due to its unnecessary complexity.
@defeqel6537
@defeqel6537 Жыл бұрын
It really depends on whether the "clean code" is really clean and not overly complex
@OneAndOnlyMe
@OneAndOnlyMe Жыл бұрын
Thank you for this. If performance *really* matters then solutions should be developed in C (or machine code). In most business environments, code maintainability is far more important as there can be a far higher cost to business when code is not easy to understand. In business applications, improving from 100ms to 50ms is just not worth the productivity loss.
@yakovkarnygin6625
@yakovkarnygin6625 Жыл бұрын
two times better performance on a hot path is not worth what?!
@OneAndOnlyMe
@OneAndOnlyMe Жыл бұрын
@@yakovkarnygin6625 Not every business is a investment bank or stock exchange.
@yakovkarnygin6625
@yakovkarnygin6625 11 ай бұрын
@@OneAndOnlyMe if your code satisfied its customer's needs why would you bother talking about performance? that's because it never does.
@Jedimaster36091
@Jedimaster36091 8 ай бұрын
@@yakovkarnygin6625 It depends. If the workflow takes hours to complete, due to its business nature (e.g. huge files being moved around), does it really matter whether a particular step in the workflow runs 50ms faster?
@yakovkarnygin6625
@yakovkarnygin6625 8 ай бұрын
@@Jedimaster36091 50ms faster per 1Kb makes it 14.6 hours faster per 1Gb. long workflows always consist of repeated operations.
@justmicha_6762
@justmicha_6762 Жыл бұрын
Is my code slower, equal or faster when I abstract and inject services and only use contract fields in my classes?
3 жыл бұрын
Nick, is the result same when you apply strategy pattern with reflection what you showed in one of your previous videos? I know you had a video about speed of reflection, but would be awesome to see something more complex if it makes sense.
@nickchapsas
@nickchapsas 3 жыл бұрын
It absolutely does. Reflection is only used to initialize a dictionary once, which is exactly what MediatR is doing. As long as the Provider/IMediator is registered as a singleton (which it is) then the results are the same.
@MrSamisack
@MrSamisack 3 жыл бұрын
Love this kind of content
@galbertdjaja
@galbertdjaja 3 жыл бұрын
Hey, may I know what's the extension that shows your name on a certain piece of snippets like in 1:11? Thanks :D
@nickchapsas
@nickchapsas 3 жыл бұрын
This isn't an extension. It's a feature of my IDE called CodeLens
@galbertdjaja
@galbertdjaja 3 жыл бұрын
@@nickchapsas Ah thanks, seems that it's for rider only then, not available on other intellij based IDE :D
@plachetek
@plachetek 3 жыл бұрын
Great video!
@_iPilot
@_iPilot Жыл бұрын
At 8:35 it is not just 4.5 microseconds; it is almost 15% slower!
@LukeAvedon
@LukeAvedon 3 жыл бұрын
Wow. I had no clue about NoOptimization and NoInlining.
@martinrodriguez1329
@martinrodriguez1329 Жыл бұрын
I always go back to a certain situation I had to deal with. Needed to execute a memory rewrite within 150 microseconds with a 120Mhz cpu. And the amount of information to rewrite was decently large regarding the circumstances. I tried the simple solution of a loop to execute it. Took more than 150 microseconds to execute. I took the time to write one by one the iterations on code without a loop. It took 60 microseconds and gave me quite a large gap in between. Was a mess to read? Maybe, but it managed to save resources, so I think is worth the programmer's time to make hardware's life easier.
@lindsaycole8409
@lindsaycole8409 Жыл бұрын
That is a good example of when to document the F**k out of your reasons. Essentially a big chunky comment, why you needed to meet sub 150 microseconds, with example code with the loop that didn't achieve it, and that the time the implementation did achieve it. We seem to be talking about 1 function so it's contained.
@keit99
@keit99 Жыл бұрын
Also can't you compile your Code with loop-unrolling. No need to write it out of your compiler does it for you.
@afnman83
@afnman83 Жыл бұрын
Nowdays software engineers like to have hundred of file classes, abstractions to everything and heavily use of design patterns, because it looks "cleaner". They don't know what they are doing, until their client notice it. Modern hardware abusers
@BastetFurry
@BastetFurry Жыл бұрын
This is all true for server and user application on a modern system, now do the same on some low power 8 bit microcontroller. Like your run of the mill ATMega328 used on most Arduino boards as that is something everyone can get hold of and play along for cheap.
@LuigiTrapanese
@LuigiTrapanese Жыл бұрын
I believe is possible to write code cleaner AND more efficient. You keep both in mind while you are writing and building
@tristangrobler4950
@tristangrobler4950 3 жыл бұрын
That's for the cool explication!! Excuse my ignorance, but would these same principles apply for Java in Android studio? Thanks
@nickchapsas
@nickchapsas 3 жыл бұрын
Java also uses a JIT compiler during runtime so yes it would still optimize but I don't know the ins and out of JVM's JIT so your mileage may vary
@tristangrobler4950
@tristangrobler4950 3 жыл бұрын
@@nickchapsas Awesome, thanks so much for taking the time to reply!
@swedishancap3672
@swedishancap3672 Жыл бұрын
what is the IDE your using?
@simonbaxter8001
@simonbaxter8001 3 жыл бұрын
Nice video Nick. Good explanation and answers the performance question nicely, although on your PC''s spec, the benchmark delta isn't going to be as big as a lower end or an average users client machine. I'd agree that these figures are good for a good server farm. On performance and optimisation, maybe a follow on topic would be on thread pools, object caching and static variables vs. constantly creating and disposing of objects.
@nickchapsas
@nickchapsas 3 жыл бұрын
Performance is always relative. This means that the diviation will be proportionate to the results that you are seeing here. This means that for this particular example a beefed up server farm and a raspberry pi will have the same performance diviation which is 0 for the first example and constant for the second. That being said BenchmarkDotNet will run as many iterations as necessary, based on how the code performs on your machine in order to identify the true delta. To give you an idea, my baby laptop from 3 years ago on battery run the first example with 30.1us for the one method approach and 30.2us for the extracted one, which is the exact same one as my desktop and I'm sure that my raspberry pi will run it with the same results. That's how good BenchmarkDotnet is. You can give it a go yourself.
@simonbaxter8001
@simonbaxter8001 3 жыл бұрын
@@nickchapsas "That's how good BenchmarkDotnet is." ... definitely going to try it out.
@wknight8111
@wknight8111 Жыл бұрын
I used to get a lot of this, when I started switched from C to C#. People said "C is faster", which it absolutely can be. But you can't discount the efforts of the developer. A developer writing performance-minded C# can make a faster application than a developer writing dumb C, and vice-versa. People also seem to think that you can write code for readability OR performance, but can't consider both at the same time. This is equally wrong. You can write clean, readable, performance-minded code. If code is clean enough to read and understand quickly, you may have more time to do optimization per sprint than you would have with a big jumble of poorly-designed code. Getting your abstraction boundaries in the correct places may even open optimization opportunities you didn't even know you had.
@iGexogen
@iGexogen 3 жыл бұрын
When you refactor big methods with monstrous nested if/else branches you can get another optimization bonus, it is from cpu branch predictor. When you extract all this mess to methods following simple if/return pattern your code will become very predictable. And I think that all this microoptimizations can be vital on "hot paths" of API code, no matter if slow external things like IO involved or not, your average request time will remain same, but number of parallel request you can serve increases.
@nickchapsas
@nickchapsas 3 жыл бұрын
This is only true if the io latency and the microptimizations are proportional. If they are not then you're wasting your time since you can gain orders of mangitute of performance by just scaling the app out by adding an extra instance.
@iGexogen
@iGexogen 3 жыл бұрын
@@nickchapsas In real life we have such systems like in my ogranization, which do both things very bad. It uses insane amount of app servers to serve about 50K users, and all because of bad code. It is bad in both terms of speed and memory consumption and needs all and micro and macro optimizations, but I think it needs to be burned. If database side of system wasn't even worse we could think about optimizing code side, but instead of it I promote idea to rewrite it all).
@nickchapsas
@nickchapsas 3 жыл бұрын
@@iGexogen Damn, I'm assuming legacy ones?
@iGexogen
@iGexogen 3 жыл бұрын
@@nickchapsas It is our current document flow system started working in 2015 and written in java, and it was bad even in idea) so many architectural mistakes was maken)
@bodek321
@bodek321 3 жыл бұрын
@@nickchapsas When is the system getting the legacy one? Obviously this is a rhetorical question. For some green field projects it is enough to reach sprint no. 10 :-)
@igorthelight
@igorthelight 3 жыл бұрын
Did you tried NGEN? It works pretty good ;-)
@Funkbassfushion
@Funkbassfushion 3 жыл бұрын
Not sure how MediatR solves the open-closed-principle but it definitely decouples classes from one another.
@nickchapsas
@nickchapsas 3 жыл бұрын
It solves it by not having to update a class to add functionality and just extending by creating new classes.
@jwbonnett
@jwbonnett 3 жыл бұрын
Is that the same with abstractions that are not inline?
@nickchapsas
@nickchapsas 3 жыл бұрын
Sorry what do you mean?
@jwbonnett
@jwbonnett 3 жыл бұрын
@@nickchapsas So you are cleaning the code in the same class here, what if it were base of code that is wrapped in other classes? Does that still compile to the same level with JIT?
@ayoodawg1104
@ayoodawg1104 Жыл бұрын
The problem is not “clean coding” since it includes some good principles like KISS, DRY and YAGNI. The problem, in my opinion, is that a lot of devs nowadays apply OOP the wrong way. Instead of thinking in terms of steps the CPU has to do in order to solve the problem, they just throw classes around without really knowing why (“because it’s a noun” is the typical answer). Structs, classes and interfaces are just tools we have as developers to solve a problem. And we have to keep that in mind when we write code.
@alxjones
@alxjones Жыл бұрын
The whole point of high level programming -- the literal definition of abstraction -- is to separate the code from the hardware. The abstraction is where the people work and the compiler's job is to turn that into CPU instructions. This is doing OOP *right*, down to its very core principles. There are plenty of ways that OOP is done badly or overdone, but I will push back on the idea that it has anything to do with thinking at the hardware level.
@ayoodawg1104
@ayoodawg1104 Жыл бұрын
@@alxjones So the point of the video is to discuss about Clean Code and if it is bad for performance and to what extent. I said that OOP is just a tool and not a problem per se but if used the wrong way can cause performance issues. That can happen especially when one doesn't know how the CPU works and the step it has to do in order to execute the code he just wrote. You replied that abstracting - separating code from the hardware - means doing OOP the *right* way. You also said - if I understood it correctly - that OOP has nothing to do with thinking at the hardware level. Well, I partially disagree with the second statement "OOP has nothing to do with thinking at the hardware level". In my opinion, it has *something* to do with thinking at the hardware level. For example, let's say you want to iterate over a huge number of elements and you care about performance. One good way to go is to use an array instead of a linked list in order to avoid cache misses as much as possible. Instead if the number of elements is not that big, and you care more about flexibility (adding, removing elements) than performance, then a linked list may be the best way to go. Of course abstractions of arrays and linked lists are useful so you can simply call list.Add() or list.Remove() and not care about the implementation details (e.g. memory allocation/reallocation). But my point is that a dev must know when to use what. Even if one is writing high level code (e.g. using list.Add) he must know - at least at a general level - how the class he's using works if he cares about performance. Another example would be to write a new class just because "it is a noun" instead of thinking how the data will be stored in memory (avoiding cache misses is good if one cares about performance). So, in my opinion, even when programming in OOP paradigm, one must consider how everything will work and fit together at hardware level (if he cares about performance). My 2 cents
@misiekse
@misiekse 3 жыл бұрын
Off topic question: do you intentionally add async/await keywords to your asynchronous methods when the only thing they do is return another task? If you do, why? As far as I know, it can be omitted since code that is calling async methods will be awaiting for result anyway.
@nickchapsas
@nickchapsas 3 жыл бұрын
async await was added in the method extraction example because they were making an API call. In the second example with MediatR it was added because MediatR only supports and async handler model so to give the 2 approaches a fair chance I made the non-async one async as well.
@FlooferLand
@FlooferLand 3 жыл бұрын
As a C++ programmer function extracting in C# sounds like shooting yourself in the foot since C# doesn't allow you to use pointers and references (which means that if you call a function and give it a variable as an argument the whole variable will be copied over) but C# deals with this problem in a much interesting way.
@nickchapsas
@nickchapsas 3 жыл бұрын
Yeah you would assume that there would be jumping involved but it's not the case. What's really interesting to me is that if I try to write C++ the way I write C# i will probably write some really bad code, completely unintentionally.
@FlooferLand
@FlooferLand 3 жыл бұрын
​@@nickchapsas A good example would be how C++ uses the "new" keyword. In C# that's just how you construct a class but in C++ it's done by calling the class like you'd call a function. When using the new keyword in C++ you're actually making a variable not automatically delete itself when it falls outside a block and the only way to free their memory is by calling "delete" on them.
@CarrotCakeMake
@CarrotCakeMake Жыл бұрын
All objects (instances of classes) are behind fat pointers in C#. You can only pass primitives like int/float and structs by value. Which just introduces another level of problems. One of the many reasons I left C# for Rust.
@FlooferLand
@FlooferLand Жыл бұрын
@@CarrotCakeMake I actually ended up leaving C# for Rust as well like half a year after making this comment xD Feels like C++ with C#-like superpowers
@CarrotCakeMake
@CarrotCakeMake Жыл бұрын
@@FlooferLand To me the worst thing was how C# doesn't even have source level sharing. It's like every project has to be written from scratch or using "official" libraries, unless you want to go through the nightmare of trying to use someone else's code with yours.
@decorummortis5175
@decorummortis5175 3 жыл бұрын
Cleaner code isnt necessarily faster its maintainable and readable. If during the code cleanup you are changing some of the heavy hitting logical operations to something simpler (massive if-else if meaning 20+ clauses where a switch would be better usage will improve runtime.) or leveraging better coding practices yes you will improve runtime speeds, but in a micro level. Add that with the function breaking in logical spots helps with compilation. but it's all readability and maintain ability. A lot of times tree shaking and using reusable functions instead of duplicating blocks of code is the way to handle slower clumsier code. Cleaner code allows for higher quality, lower bug counts, faster output of product, increased productivity, ease of debugging this is all really the benefits of cleaner code. As you mentioned the just in time compiler works a lot of magic for you
@Thriron
@Thriron 3 жыл бұрын
All of the code I write for products is embedded, bare metal code. In that scenario, when you are looking at real time operation and stuff, yeah, maybe be a little mindful about what you extract to a method. But GCC will build for basically any micro controller and will inline half of your functions anyways. Worse case, small function call is just saving off a handful of registers to memory and jumping. That's NOTHING for modern processors. Most of them have hardware specifically for those operations and you're so far removed from the actual registers that it will be transparent as most of your instructions and data are constantly being pushed and pulled from RAM. The only applications that I know of where you actually need to optimize at the hardware level are giant distributed mathematical modeling and RTOS systems. Everything else the compiler is smarter than you.
@yoshi7481
@yoshi7481 8 ай бұрын
I think people having differing opinions on "clean code" is mainly just the differences in their industry. A web service is not the same as a video game. Services can potentially scale horizontally a lot, distributing the load, while games must scale vertically on a finite set of hardware, and are very latency-sensitive. People are comparing soft-real time systems and websites that respond after 500ms. The difference is 1ms in this context is probably irrelevant for it's use case, but in a video game that means you can't add more features. Performance, especially for console games is a prerequisite to even have *any* features, never-mind add any new features.
@TheJamesboink
@TheJamesboink Ай бұрын
I'm not sure if its actually testable in C#. It's already a "slower" language than C++ and in "Clean Code Horrible Performance" you can see how much of an ACTUAL impact clean code standards have on performance.
@CallousCoder
@CallousCoder Жыл бұрын
Yes clean code is slower because abstractions cause extra jsr and rts and setups of stack frames. So it is always a trade off. Us old skool assembly demo coders know that all too well.
@AK-vx4dy
@AK-vx4dy 8 ай бұрын
As i argumented on other video, methods extraction don't slow because on JIT-ed langugages have no effect and in most modern compilers also it is often true. JSR and RTS 😆 I see someone longs for 6502 assembly...there is no place for clean code, loop unrolling, zeropage as extra registers...dirty beyond imagination 😅
@ThePC007
@ThePC007 3 жыл бұрын
Lots of slowdown cones from developers not understanding the code they are working on, which leads to issues like performing expensive actions twice or transforming some data from A to B only to transform it back from B to A right afterwards. So clean code may often times actually be faster than dirty code.
@DanielWillen
@DanielWillen 2 жыл бұрын
Didn't John Carmack basically say readability over performance?
@edwinsulaiman6143
@edwinsulaiman6143 3 жыл бұрын
where can i find the source code?
@nickchapsas
@nickchapsas 3 жыл бұрын
Did you check the video description?
@edwinsulaiman6143
@edwinsulaiman6143 3 жыл бұрын
@@nickchapsas oops, i missed it, thank you
@cotin18
@cotin18 3 жыл бұрын
Yadi yadi yadda -remix coming soon :D
@skgenius5410
@skgenius5410 Жыл бұрын
If you don't use Uncle Bob's very OOP "Clean Code" because you are interested in high performance, than you will use DataOrientedProgramming (DOP) where you not hide the data. And this will nit mean you code is not clean, it just follow other rules. The first think in DOP is do not use a slow abstraction like DataTable, the second think is don't "index" a row by strings, the third think is use RoA instead of AoR. And with all of it you maybe get 20x performance.
@frankhaugen
@frankhaugen 2 жыл бұрын
A consultant I was babysitting/on-boarding told me that any developer that practice clean code is only trying to hide their incompetence... I didn't like the guy from that moment, and he hated working with us, so he left in a few weeks 🤣
@barmetler
@barmetler 3 жыл бұрын
One thing I've learned, is, that writing cool looking code that seems like it would be faster (branchless code, etc), more ofthen than not actually result in slower execution. The reason for that is that branched code will get optimized way better. This is because compilers are written by humans, which means they are especially good at optimizing normal patterns that are used everywhere. So, writing code that is more _normal_ actually increases the chance that (not only collaborators, but also) the compiler knows your intentions, so will know exactly how to translate that into byte-/machine code in the best way possible. Your mindset shouldn't be "How can I make this as efficient as possible?", but it should be "How do I make my intentions as clear as possible to the compiler/interpreter?" Now some efficiency principles are obviously still important, for example how complex the code is (O(n^2), O(n log n), etc) or which way you iterate over a multi-dimensional array (iterate over lines instead of columns, as to increase cache hit chance) but things like "should I use ifs or a switch block" really should be dictated by what is more readable.
@sasas845
@sasas845 3 жыл бұрын
I disagree. For modern CPUs, branching (especially indirect branching) is essentially torture. However, if you work in a language such as Java (probably also C#) that is built around "branch everything, virtual dispatch everything" there is realistically no way a programmer can avoid paying the penalty for branching, so I'd say trying to do branchless programming on these platforms is pretty pointless since the platform will gleefully undermine all your efforts. I recently needed quaternions in Kotlin. Implementing them was fairly straightforward. Efficiency-wise, it was a complete shitshow since despite all my efforts at telling the language "this is a fixed (even centuries-old) structure with fixed functionality that won't EVER change", it went "no, I'm going to assume that at some point you will replace this implementation with a completely different one, so all code has to be virtual and dynamic". Some digging revealed that a) java compilers are dumb morons roughly on the level of the C compilers of the 70's and 80's b) the JVM spec disallows a huge chunk of trivial compile-time simplifications because it guarantees that any and all code can be modified at runtime. Now, if you work with languages such as C,C++, Rust that are more receptive to programmer intent than the OO-junkies Java and C#, techniques such as branchless programming and various other methods for reducing resource consumption can (and do) provides tremendous benefits if you know what you are doing. In my experience, speedups of 10x and more are actually pretty common.
@barmetler
@barmetler 3 жыл бұрын
@@sasas845 I did not say that branching is not torture, as in you don't need to avoid branches. What I said, however, was that replacing a branching statement with something branchless (like for example "i = somebool * a + (1-somebool) * b") will be less efficient than an actual if/else, because the compiler will actually inline the if else way better than the purely arithmetic statement. And things like java or c# are inefficient anyways, I was more talking about actual compiling languages, so mainly c. So when you say, that techniques of branchless programming are important, I don't disagree, we're simply talking about completely different things, and I see that I could have been a little bit more clear about what I meant. In conclusion: replacing an if/else with something similar, but branchless (if it is a simple expression) is not necessarily faster, but of course extreme branching is bad and you should avoid it.
@sasas845
@sasas845 3 жыл бұрын
​@@barmetler Ok, then we are not as far apart as I originally thought: I took particular issue with your claim that "branched code will get optimized way better" as branching is (at least for the compilers I have used) something that tends to really make reasoning about the code more difficult for compilers (this also holds for humans and cpus). A rule of thumb I use for writing efficient code (apart from the basic "avoid unnecessary work") is something like "keep the exciting stuff (branching, exceptions, indirect stuff, exceedingly clever stuff, other schenigans) apart from the code parts where the bulk of the computational work gets done". Thus for the "hot" parts, a) the compiler gets to do its job on a chunk of "boring" code where it can just apply all its optimization power without worrying or needing to be particularly clever, b) the cpu does not trip too often over interesting parts and c) it helps making code more understandable (provided you actually do the minimal effort of giving a short explanation why the code is structured as it is). Regarding branchless programming: There are often situations where branches can be removed from hot zones without needing to do tradeoffs (e.g. structuring the data in such a way that the "else" branch never exists -> far too many branches are some kind of integrity or sanity checks. Also I love min/max intrinics since they are dirt cheap in silicon, avoid branches ("if a>b ? a : b") and can be used to keep arithmetics inside intended operating ranges). For situations that are much less clear such that textbook example "i = somebool * a + (1-somebool) * b" (AFAIK, this is only an illustrative example, not a real-wolrld example, so please forgive me if I'm attacking a strawman) are much trickier and at least I would be reluctant to trade a conditional move for two multiplications if there wasn't something pretty juicy at the other end of the tradeoff.
@el2746
@el2746 3 жыл бұрын
​@@sasas845 SO basically, in short, if you want to be efficient, just use low level programming languages like c. Didn't like Java anyways...
@sasas845
@sasas845 3 жыл бұрын
@@el2746 IMO, the JVM is a special case since it insists on taking every single penalty caused by naive dynamism, which makes it unreasonably inefficient in my book. Even if you don't go "pedal to the metal" (custom-built native code), there are reasonably efficient (meaning resource consumption is directly correlated to the amount of work you require from the program) alternatives to JVM. AFAIK, Golang e.g. performs static escape analysis on objects, which should make it's GC already orders of magnitude more efficent that JVM's. Swift is a good example for a highly dynamic language that manages to wiggle out of paying the price for dynamism pretty much all the time (I'm no friend of Apple's and most of their technogies but you've got to aknowledge that this a very non-trivial feat of engineering. This technology the core reason for iOS's performance advantage over Android.).
@michaelkhalsa
@michaelkhalsa 3 жыл бұрын
If you really want to optimize a return from a DB op, then populate your results with ordinal indexing in your repo into strongly typed records, and scrap datatables or sets. somefield = dr.getstring (23); With lots of fields and larger collections this can be very sagnificant. I measured this some years ago, so have not checked for any recent optimizations.
@nickchapsas
@nickchapsas 3 жыл бұрын
This isn’t a database call. It is just using a datatable for demo purposes. I don’t think I’ve ever used a datatable in real code
@kiryonnakira7566
@kiryonnakira7566 Жыл бұрын
it is not more readable to me cause you don't have the rainbow colored theme i have
@JonathanSwiftUK
@JonathanSwiftUK 3 жыл бұрын
Code which does stuff is great, but you need to add in a certain amount of error checking when writing real-world code. I see too many modules crash out with data which is out if range/not in the correct format. Like when servers get rebooted for patching, many apps have to be started in a certain order, rather than having code which re-connects to a resource isn't immediately available.
@nickchapsas
@nickchapsas 3 жыл бұрын
You absolutely should but this isn't the subject matter of the video. When I'm talking about a specific topic, I trim the code to it's very basics so the topic is easier to grasp. If I hard retry policies, jitters, backoffs and circuit breakers then the main poiny might be lost in the noise.
@JonathanSwiftUK
@JonathanSwiftUK 3 жыл бұрын
@@nickchapsas True, but I wouldn't want people to think if their code doesn't look like a work of art they've done it wrong. Good video, I'm liking the technique and style.
@nickchapsas
@nickchapsas 3 жыл бұрын
@@JonathanSwiftUK The code can still implement all the production-ready qualities and look like a work of art. It's a matter of using them correctly. Don't worry, I have a video coming just for that.
@iGexogen
@iGexogen 3 жыл бұрын
@@nickchapsas Maybe you sometimes will make video about "defensive programming"?)
@RawBert
@RawBert 3 жыл бұрын
I wouldn’t modularize every for loop I see to be honest
@yakovkarnygin6625
@yakovkarnygin6625 Жыл бұрын
it's like when you compare different flavours of crap and surprisingly discover they all are equally disgusting for you
@aleksanderklepov8881
@aleksanderklepov8881 3 жыл бұрын
You are saying, that it's just 4 milliseconds, but it's just because the overall time is 31 ms. From another point of view it's 15% or so, and for me it's huge.
@nickchapsas
@nickchapsas 3 жыл бұрын
It's not 4 milliseconds. It's 4 MICROseconds which is 0.004 of a millisecond. There is no logical point of view, when writting c# code, that this is huge simply because it doesn't scale. It a real program it will get drowned and load leveled by slower things.
@aleksanderklepov8881
@aleksanderklepov8881 3 жыл бұрын
@@nickchapsas Yeah, I've made a mistake, thanks. Forgot to point out, that the video is great. I was to lazy to do something similar. I think, it wouldn't scale, only if you increase the time in the innermost loop. And it will scale, if you'll increase the outermost loop count. Am I wrong?
@nickchapsas
@nickchapsas 3 жыл бұрын
@@aleksanderklepov8881 In both cases performance is the same since JIT will optimize it. The perofmance difference is only present when JIT optimizations are explicitly turned off on the method level, which never happens.
@aleksanderklepov8881
@aleksanderklepov8881 3 жыл бұрын
@@nickchapsas I'm talking about cases, when JIT optimization is turned off, or when the language has no such feature, because I'm mostly interested in c++, that has no JIT.
@nickchapsas
@nickchapsas 3 жыл бұрын
@@aleksanderklepov8881 JIT optimization are never off in .NET nor any other language that supports them. This video does not apply to languages that don't use a JIT.
@jamieoglethorpe
@jamieoglethorpe Жыл бұрын
Dijkstra's rules for optimization: 1. Don't optimize 2. Don't optimize yet
@TheArakan94
@TheArakan94 Ай бұрын
Sure, method extracting in languages like C# or Java is not impacting performance while in others (such as C++), it likely will, especially if they are virtual methods. But the "Clean Code" is so much more than just this and it does have a significant performance impact. Especially if you use it as intended by the creator. See excellent presentation here: kzbin.info/www/bejne/qnWYf6Wbq6unmLc And response to many reactions here: kzbin.info/www/bejne/rmOogIKAnJ15oaM
@yavvivvay
@yavvivvay Жыл бұрын
I'd bet you if it was rewritten in architecture-specific assembly language it would run faster :D
@MrEdot
@MrEdot Жыл бұрын
my take is, whenever someone said "refactoring" or "optimization" in terms of performance/speed. I will take a look at the time complexity, let's say if the current implementation is n square, and the proposed solution is not less than n square (but with different coding styles and approach). I personally will disagree/reject it. or maybe put it as low priority (depends on the situation) Because it is not worth it, if you want to make it faster you have to understand time complexity and proposed smaller time complexity solution. Although constant factor might makes a huge difference, it is extremely rare. basically save it for later. as long as the time complexity is good, move on. don't care too much
@afnman83
@afnman83 Жыл бұрын
To measure a solution only by the time complexity is a huge mistake. Its more than that. You have to use profilers and measure the real time in different hardware and configurations to be precise. There are many cases that a faster algorithm (in theoretical sense ) can be slower in practice.
@alxjones
@alxjones Жыл бұрын
Not to pile on, but I don't think this is a good approach. Performance should be judged in terms of the expected and peak load, not on a theoretical growth class. You say the constant factor making a difference is rare, but that's not truly the case in my experience. A lot of the tools used to improve performance have an overhead cost, which is worth it only when amortized over large inputs. The best measure of performance of your software is the performance of your software -- that is, use metrics and profiling, instead of theoretical calculations, to determine bottlenecks.
@MrEdot
@MrEdot Жыл бұрын
@@afnman83 A faster algorithm will eventually become faster when you add more data. For instance, there are cases where n^2 beats n log n, but if you add more data, n log n will eventually beat n^2. That's how it works.
@MrEdot
@MrEdot Жыл бұрын
​@@alxjones I agree, but in practice, how many operating systems do we have these days? How many different types of hardware do we have? How much would it cost to add metrics to all of them? For simplicity, using time complexity will definitely save you from this burden.
@Xbox360SlimFan
@Xbox360SlimFan Жыл бұрын
Be careful people: C# is not a low level languange. Abstaction and "clean" code is probably a good idea here, like in shython. C/C++ gets compiled and modern compilers are very good at finding optimizations for the machine code. Abstractions make it harder for the compilers to find (very important) optimizations. We are not just talking about polymorphism, i.e. virtual function tables and so on, but: Modern C++ Tensor libraries that rely on function templates are SLOWER than ordinary C-TRAN and at best equally fast. Which means, stick to C-Tran style coding when it comes to number crunching. However, compilers get better every year too, we may not forget! Things might look different in 10 years from now.
@yakovkarnygin6625
@yakovkarnygin6625 Жыл бұрын
there is literally nothing in function templates that could make them slower than normal functions assuming that the rest of the code is the same. computation done at compile time can never be slower at runtime than the one which completion is shifted to runtime. all these talks about templates come from the fact that people have a very little idea about them.
@Xbox360SlimFan
@Xbox360SlimFan Жыл бұрын
@@yakovkarnygin6625 Yes there is: Compilers have a hard time finding crucial optimizations when compiling code that relies on high level abstractions. Edit: Assuming the generated machine code is similar, then there is barely any difference in run time obviously.
@yakovkarnygin6625
@yakovkarnygin6625 Жыл бұрын
@@Xbox360SlimFan by explicitly saying which part of the code has to be evaluated at compile time you make the compiler's life a lot easier. any assumptions that it will struggle with optimising templates over normal functions are just fundamentally wrong. most probably we are talking about a bad piece of generic OO code compared to a good procedural one. I agree that statistically procedural developers are better, just because there are too many bad OO developers. but it doesn't make C better performance-wise than C++ in general, and than templates in particular.
@Xbox360SlimFan
@Xbox360SlimFan Жыл бұрын
​@@yakovkarnygin6625 1. Compile time increases with extensive use of the STL and other templated libs. 2. Compilers struggle optimizing higher level abstractions, that is well known. 3. If You want speed, cut higher level abstractions as much as possible, i.e. code in c-tran, and build O3. I have not looked at the research or tested the speed myself, but using STL containers were always fine from my experience. Nesting iterators, overloading operators of the templated types, and introducing some virtual functions to the party, and You may have bad luck when it comes to the compilers smartnes.
@robrick9361
@robrick9361 9 ай бұрын
@@Xbox360SlimFan You should be clear about what you're saying. TEMPLATES ALONE could never cause runtime slowdown. If anything they ensure more speed as the template definition must be known to the compiler. If you combine templates with other features like many things in the STL do then yes sure. But in your original post you implied that templates ALONE could make slower runtime code, which is completely wrong.
@andreandpaula
@andreandpaula 3 жыл бұрын
What ide is that?
@nickchapsas
@nickchapsas 3 жыл бұрын
JetBrains Rider
@ifstatementifstatement2704
@ifstatementifstatement2704 5 ай бұрын
When you have something that calls something that calls something that calls something… that can’t be good lol
@karapuzo1
@karapuzo1 3 жыл бұрын
You can't lose performance when your runtime is slow already. Go to C/assembly and time function calls and lookups. For tight loops there might a significant difference as loop unrolling would be impossible and inlining requires manual definitions.
@pjeet4411
@pjeet4411 Жыл бұрын
Your videos are my everyday schedule. I learn a lot from your videos. Planning to buy a project and watch your videos like a short movie
@syth-1
@syth-1 3 жыл бұрын
People always tell me I shouldn't use linq when possible due to performance - I understand there's some overhead, but seeing this, does linq have a more drastic performance penalty?
@nickchapsas
@nickchapsas 3 жыл бұрын
It really comes down to what you're doing. LINQ does have a fair overhead but it also simplifies your code (depending on how you use it) so it really depends. Do you need to make the most of each clock cycle? Then don't use it if possible. Is it easier to just scale your app out? Then use it. It's a case by case thing. There are some Linq packages that actually optimize Linq quite significantly like LinqFaster
@iGexogen
@iGexogen 3 жыл бұрын
@@nickchapsas Sometimes LINQ can result in very noticeable performance hit, it is when you are capturing many things in your lamdas. But for most places in code except hot ones LINQ is pretty good.
@briankarcher8338
@briankarcher8338 3 жыл бұрын
LINQ is ok really. You just need to know what it is doing. Most LINQ calls, for example, use some memory per call - a few bytes, maybe 80? So if you have a hundred LINQ calls inside a loop that runs a million times you will hit the garbage collector as your memory gets eaten. However, if you have an API that calls a LINQ call once per API hit you will not notice the difference. In the end in 99% of cases you will not notice the difference. The only case I would absolutely say "Stay Away!" is in Unity game development. Your code is running 60, maybe even 200 or 300 frames per second in one process. Any kind of memory leak shows up real quick. You do not want to ever hit the garbage collector in your game. Unity has a pretty good profiler to catch memory leaks though. And beware if huge loops. Other than that you're probably fine and the cleanliness far makes up for the limited excess memory usage.
@igorthelight
@igorthelight 3 жыл бұрын
Write two methods: with and without LINQ and compare them. The easiest way to learn ;-) I even use Timer to measure the execution speed when I'm lazy.
@vanivari359
@vanivari359 Жыл бұрын
maeh, that "slowest operation" argument is pretty thin - if you have to respond in 50 ms and your slowest operation needs 40 ms, then you don't have any time to waste in the rest of your application. In most applications, it doesn't matter and i prefer maintainability of clean code, but if you are fighting for every millisecond, it is worth looking into optimized code which is not "clean code", especially if there are loops involved and 100 nanoseconds shaved of adds up if that code is executed thousands of times.
@alxjones
@alxjones Жыл бұрын
The point is that there are orders of magnitude separating the time it takes to run the average line of code vs. the slowest operation. Using your example, if the slowest operation is 40 ms and the average line of code is 100 nanoseconds, there's a factor of about 10^5 between these two. That means you need 100,000 of those average lines to make a noticeable change to overall performance next to the slowest operation. It's not impossible that you hit something like this; maybe you're doing an n^2 operation on lists of around 300+ elements for each service call, for example. However, the situation where the difference between hitting and not hitting a performance threshold is so fragile that you can't afford to extract a function is both extremely rare and indicative of a larger issue somewhere else in the design. For example, using C# was probably a mistake if you cared about nanoseconds. Making a service call in the first place is something you may want to reconsider, or at least having a cache in place to amortize the long service calls if you get a lot of duplicate requests. You might be able to find a more efficient algorithm for your list. Hell, you could even push back on the performance requirement, since 50 ms response time with a 40 ms slowest op is a lot to ask for something that isn't business/mission critical. In short, it's a rule of thumb. Optimizing code is a last resort, especially is situations where there are other bottlenecks external to your code. There is a cost to code which is optimized for performance rather than maintainability, and you want to be absolutely sure that's a cost you have to take on before deciding to do so. In almost every case that doesn't require writing low-level code for specialized hardware, it's not worth it.
@madpuppet666
@madpuppet666 Жыл бұрын
if the code fits on a page, you don't need to go splitting it up into child functions that mean you now have to hold multiple levels of abstraction in your head just to understand it. If you're going to abstract its usually better to think in layers where one layer is just calling abstractions, and those abstractions are just 1-2 pages of code each. Abstracting every level of indention is going too far IMO.
@ctrlaltdebug
@ctrlaltdebug 3 жыл бұрын
I fix indentation by making tabs 2 spaces lol.
@holleey
@holleey 3 жыл бұрын
wdym "actually"? clean code is code that doesn't do any unnecessary things, which of course generally makes it faster.
@nickchapsas
@nickchapsas 3 жыл бұрын
Clean code does not mean simple code and in most cases it actually does more than “regular” code in order to get around some potential violations. Open closed is a great example of that. Being more elaborate and usually lengthier, people assume it is also slower.
@holleey
@holleey 3 жыл бұрын
@@nickchapsas ok so people mean "short" when they say "clean"? weird. not an useful definition imho.
@abeplus7352
@abeplus7352 3 жыл бұрын
@@holleey clean code is interpreted differently in different languages . But clean code essential is unit testable , easy to swap out because you've modularized it , and easy to comprehend . I've written our api for pure performance at the time , when we ported over from spring boot to go , but it was an unmaintaible mess , but I knew I had to make that decision at the time because we're suffering from slow speed , and our last senior developer fucked us , he was working two jobs so he barley got anything donein that spring boot codebase . And I at the time a junior dev was give the task , do what he did that took him about a year in 2 weeks . So at the time I didn't care about unit testing or anything , I just cared about raw performance. After I showed my api response times in the benchmark I was given ownership of the codebase and later promoted that summer . It's still my proudest moment , but now I've refactored the codebase drastically use a repository pattern in place that's more familiar to devs . It's more code to write but it's unit testable easily .
@abeplus7352
@abeplus7352 3 жыл бұрын
@@holleey tldr sometimes in life you have to write performant code and other times you have to write clean code and sometimes it happens that you can write clean performant code .
@TheSwissGabber
@TheSwissGabber Жыл бұрын
Clean Code is just another word for programmer-narcissism. Yes code should be readable and maintanable but it should also be efficient and fast. If you insist on keeping code "clean" no matter the cost you're just focusing on yourself. If it's 10x slower and you like it because you think it's "cleaner" and you don't care: you are a narcissist.
@7th_CAV_Trooper
@7th_CAV_Trooper Жыл бұрын
Pro tip: for pennies a month you can upgrade your compute units and save hundreds of thousands of engineering dollars wasted on optimization and additional expense of unmanageable code. Clean is the correct way.
@massimo79mmm
@massimo79mmm Жыл бұрын
as usual, you have to be balanced. if you are an extremist of "clean code" (and i have the classic "clean code" book, i think the author is joking), you will produce extremely slow code and very BAD to maintain. example: in that book the author says that clean code needs to have 3-4 line functions (page 34) (and consider that he is making the example with an IF, so one line is "already used"). oh, yes. try to do a "real world" program in this way. you will use 95% of the time thinking about function names (because you have a "ReadFromDb", another with "ReadTableFromDb", another "ReadLineFromDb", "ReadColumnFromLine", "ReadValueFromColumn" and so on), and your code will be unreadeable because you can't go deep 30 functions deep every time you need to uinderstant "where i call that fuzzing JDBC query?". and your code will be extremely slow, because for every little thing the cpu will have to pass every time a list of parameters in the stack (that will be HUGE) and call hundreds of time a function just for... things you can do with a 20 lines-long function. and obviously you have to be a little "clean", nobody wants to return to spaghetti code. and i find VERY stupid the idea of "well, my code is slow? no problem, add another server". A good programmer can produce readable, maintanable and FAST code. a POOR programmer simply asks for a more powerful cpu and more ram, justifying with "hey, my code is very maintanable, so it doesn't care that is slow". i call it WASTING resources.
@TheIllerX
@TheIllerX 5 ай бұрын
That is very much my thoughts about the book(and also many youtubers advocating the advice) as well. Clean readable code is of course something to strive for, but "clean code" is not some kind of copyrighted term. One has to be pragmatic and not following some rigid rules like some religious dogma. I agree about the 3-4 line function advice being really bad. As you say, it is really confusing to go tons of layers of function calls deep for no reason. It makes the code harder to read. You loose track of the big picture. The ideal of a function doing one thing, doing it well and with no side effects is good advice though. But don't split it into smaller functions unless those functions are sensible as stand alone functions of their own. If a function goes on for several pages it might be a good idea to split it into smaller functions for readability, if possible, but the splitting should be natural and not just for the sake of it. Variable names are a bit of a trade off. You, of course, don't want variables with names like a, x, tmp, tmp2 and so on (except in mathematical expressions where you need short names for readability). On the other hand, having very long and verbose describing names actually makes your code less clean and hard to read too. So some medium length name that captures the essentials of the variable is preferrable.
@errrzarrr
@errrzarrr 2 жыл бұрын
Clean Code is not about code performance. Is about your performance, team performance, HUMAN performance.
@quigglebat
@quigglebat 3 жыл бұрын
Re-fuck-toring
@MrCmeNOT
@MrCmeNOT 3 жыл бұрын
Vanilla Python is not really JIT compiled, just sayin
@igorthelight
@igorthelight 3 жыл бұрын
+1 It's interpreted. For JIT use PyPy :-)
@simonfarre4907
@simonfarre4907 3 жыл бұрын
C# doesn't get compiled to assembly. So unless one knows exactly what IR the code gets compiled to, you can never know if your code gets worse or better, by simply looking at the source code. The same is even true for systems languages, although you can be more sure. JIT is also a great tool but it also adds non determinism to the code base. It's one of the major reasons games for instance will never be written in Java or C#. That and GC of course. But none the less, its powerful.
@AntonioNoack
@AntonioNoack 3 жыл бұрын
*cough* Minecraft *cough*
@baconhair1565
@baconhair1565 3 жыл бұрын
*cough* Unity, Godot *cough*
@ifireblade09
@ifireblade09 3 жыл бұрын
So dictionaries still violate open closed principle. yes they are better than switch's or if else statements but you have to "modify" an existing class file. remember SOLID is about OO principles. Use the power of your DI and object heirarchies to do the heavy lifting. For instance instead of a dictionary of recipes...just take a IEnumerable of Recipes and then if you have a new recipe it's a NEW type that automatically gets added to the DI, and also is automatically included in the IEnumerable that you might pass into a RecipeBook. This is something that a DI framework like Autofac gives you out of the box and is additive only without modification to existing code...that's the open/closed principle.
@bra5081
@bra5081 3 жыл бұрын
Well said.
@nickchapsas
@nickchapsas 3 жыл бұрын
They only do if they are not built dynamically which in this video they are. That being said, even if they were not, they are orders of magnitude better than having if else or switch. Not all open closed violations have the same weight
@ifireblade09
@ifireblade09 3 жыл бұрын
@@nickchapsas yes I agree with orders of magnitude. I think I was also cross referencing another video you had on it. yes a dictionary in one file that is additive in nature is still MUCH better than switch and heavy branching logic.
@iGexogen
@iGexogen 3 жыл бұрын
I think explicit registration in DI provider is much cleaner way to do things, it gives you ability to bootstrap various different configurations for different purposes, testing, production, maybe some isolated decomposition of project subsystem and so on. Automatic registrations with naming or other conventions are obvious only when your project is relatively small, in large solutions worked by large amount of developers managing this things becomes very huge problem. I've decided to stop using external DI in our net core projects, in my case it was SimpleInjector, because adapting them with stock DI makes things even more complicated.
@stupidnameever3648
@stupidnameever3648 3 жыл бұрын
why you saying "refactoring" sounds to me like "refuckoring"
@nickchapsas
@nickchapsas 3 жыл бұрын
You either have a very dirty mind or my accent is just weird
@stupidnameever3648
@stupidnameever3648 3 жыл бұрын
@@nickchapsas maybe both, i dunno, great vids btw
@drcl7429
@drcl7429 Жыл бұрын
Before I watch I think clean code is probably slower because it usually requires more execution jumps. The difference is likely minimal and nothing compared to the amount of time wasted trying to scale and expand unclean code.
Where are types allocated in .NET and why people get it so wrong
14:35
Do you have a friend like this? 🤣#shorts
00:12
dednahype
Рет қаралды 49 МЛН
1❤️
00:20
すしらーめん《りく》
Рет қаралды 33 МЛН
Sprinting with More and More Money
00:29
MrBeast
Рет қаралды 91 МЛН
What is Span in C# and why you should be using it
15:15
Nick Chapsas
Рет қаралды 247 М.
25 nooby Python habits you need to ditch
9:12
mCoding
Рет қаралды 1,7 МЛН
Stop Doing Code Reviews
18:21
ThePrimeTime
Рет қаралды 94 М.
My 10 “Clean” Code Principles (Start These Now)
15:12
Conner Ardman
Рет қаралды 105 М.
3 Types of Algorithms Every Programmer Needs to Know
13:12
ForrestKnight
Рет қаралды 436 М.
Clean Code Is Killing Your Projects
9:20
Web Dev Simplified
Рет қаралды 141 М.
The New Extensions EVERYTHING Feature of C# 13!
10:32
Nick Chapsas
Рет қаралды 64 М.
"Clean Architecture" and indirection. No thanks.
25:06
CodeOpinion
Рет қаралды 41 М.
Do you have a friend like this? 🤣#shorts
00:12
dednahype
Рет қаралды 49 МЛН