Why I don't use the "else" keyword in my code anymore

  Рет қаралды 334,174

Nick Chapsas

Nick Chapsas

Күн бұрын

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 tell you why I'm not using the else keyword anymore. I think this is an interesting topic and it dives into some other principals as well which ultimately help to create what I consider to be cleaner code.
Timestamps
Intro - 0:00
Main else refactoring - 2:51
Open-close refactoring - 11:35
Video about Object Calisthenics: • 9 "rules" for cleaner ...
Video on whether this will slow your code down: • Is Clean Code Really T...
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
#dotnet #csharp #cleancode

Пікірлер: 1 100
@nickchapsas
@nickchapsas 3 жыл бұрын
Addressing a few frequent asked questions below: Q: Why did I say that I don't recomment an single exit point approach. A: Single exit point approaches usually include nesting which is another thing I am addressing in this video. Sure you can do it without nesting but at that point your code is needlessly complicated and not as readable (subjective). Multiple exit points tell the story of the method's flow way better in my opinion and have the side effect of also exiting earlier. Even the StackOverflow question on the matter, has been closed and marked as “opinion-based”: stackoverflow.com/questions/4838828/why-should-a-function-have-only-one-exit-point Q: Why are I doing a positive if check in 10:10 A: Totally missed that. It should have been an "if(age < 18)" check instead. Thanks for bringing it up. Q: The Open-Close violation wasn’t completely fixed since it was now moved to the class level instead of the method level A: This is correct and I mentioned it in the video as well. I didn’t want to spend more time in the video for the second part since it was an afterthought to begin with. That being said, if I was to continue I would implement a strategy pattern and have the dictionary automatically created by some convention. That way we completely eliminated the OC violation
@fourlegsgoodtwolegsbad
@fourlegsgoodtwolegsbad 3 жыл бұрын
IMO using the return instead of else is only safe if the method is small (only a few lines) and can be seen in full with very little analysis. Your cases fit this and so it works but that would be my note. If you use the first rule you in essence solve that but for people not following that rule strictly they can get into trouble with forgetting all of the wild ways they exit lol.
@nickchapsas
@nickchapsas 3 жыл бұрын
@@fourlegsgoodtwolegsbad Methods should be kept small. My rule thumb is that if I need to scroll to see the whole method then the method is too long (normalized font sizes)
@fourlegsgoodtwolegsbad
@fourlegsgoodtwolegsbad 3 жыл бұрын
@@nickchapsas I of course agree. However, real life demonstrates that many do not do this lol.
@AyushkaPartohap
@AyushkaPartohap 3 жыл бұрын
If you have nesting problems, it's likely the culprit is mixing levels of abstraction. Not single exit.
@ruadeil_zabelin
@ruadeil_zabelin 3 жыл бұрын
@@fourlegsgoodtwolegsbad Just extract methods. Whenever I open a file for my work and it has functions that are too big I just start extracting them and cleaning up the code before I even start on my actual changes. Sometimes that also means I have to write additional tests. But it really helps learning that part of the code and it can even expose bugs. If a superior complains about me taking that time I tell them that I'm hired for improving and maintaining the code, and not just "data entry".
@ghollisjr
@ghollisjr 3 жыл бұрын
You have started down the path of enlightenment, at the end of which is the pristine beauty of the goto statement.
@doldol1
@doldol1 3 жыл бұрын
yikes
@Theunitedlowshater
@Theunitedlowshater 3 жыл бұрын
Sometimes i wish i had a goto statement in python, but i know many people hate it.
@moralesvazquezmiguelangel6546
@moralesvazquezmiguelangel6546 3 жыл бұрын
@@Theunitedlowshater goto is horrible for performance...
@0xCAFEF00D
@0xCAFEF00D 3 жыл бұрын
@@moralesvazquezmiguelangel6546 It's a jmp like any other. Can you elaborate?
@risingdeathx
@risingdeathx 3 жыл бұрын
Please no
@fahimmahbub9268
@fahimmahbub9268 3 жыл бұрын
Next video: Why I don't use my hands for typing
@c0smiq
@c0smiq 2 жыл бұрын
Actually I would love to see a video where he goes through all his most used shortcuts and plugins he uses.
@suraj351
@suraj351 Жыл бұрын
😂😂😂
@gaborpinter4523
@gaborpinter4523 2 жыл бұрын
The problem with this approach, that you will fragment even a really simple business logic into so small pieces, that it became harder to understand. Also the default case in a switch can be interpreted as an else :D
@jaumesinglavalls5486
@jaumesinglavalls5486 2 жыл бұрын
@@IIARROWS Agree to both comments , for me (maybe because I'm a little bit dislexic) the else is good visually to be there, is much more easy to understand is two different blocks of code, without the else if you don't read the return, you think it's the same flow. Some time ago we had a bug in the company because a return in the middle, and one line was only 3 lines lower, but visually it's much harder to see this line is in an incorrect block if you have the return (at least for my case) And for me, when you have a method with one line, something smells... usually this kind of code means that any newbie to the code requires 6 or 7 jumps between functions to really understand what is happening.
@Vol4ica
@Vol4ica 2 жыл бұрын
@@jaumesinglavalls5486 totally agree. for me the video looks like "hey, this is how you can write code without using keyword 'else'". But I dont see any explained profit that it brings. Nick is doing some refactoring - rewriting 'if' tree into switch case, also he extracts logical pieces of code into corresponding methods, which is totally ok. But when he started replacing 'if-else' by 'if return', I felt like he was trying to manipulate us, using "three yeses" trick.
@jaumesinglavalls5486
@jaumesinglavalls5486 2 жыл бұрын
@@Vol4ica Exactly, the if else or if return, is the same, only that some part of code is not idented (In my opinion, making it worst to read) don't forget that identations in most of the languages are here only to help us, to represent visually something the code is doing. In my opinion the rule (at least is what I've got when writting) try to avoid the if itself, as joke usually I say "I am alergic to conditions"
@pauoliveres9299
@pauoliveres9299 2 жыл бұрын
@@jaumesinglavalls5486 i am also dyslexic and also find hard to follow when there is a return, so maybe it is indeed related
@JustYesntMan
@JustYesntMan 2 жыл бұрын
Just write in binary
@jenselstner5527
@jenselstner5527 3 жыл бұрын
First rule of programming: Don't stick too hard to the rules! ;o)
@nickchapsas
@nickchapsas 3 жыл бұрын
Also known as critical thinking ;D
@igorthelight
@igorthelight 2 жыл бұрын
I would say: Understand rules - not just follow
@closetothee3785
@closetothee3785 2 жыл бұрын
Agree. The tricky part is to know when to use which rule.
@rickarmbruster8788
@rickarmbruster8788 2 жыл бұрын
@@nickchapsas WORD!
@forytube4998
@forytube4998 2 жыл бұрын
But the recipebook also violated open-closed, as every time you want to add new drink, you have to modify it
@rustamhajiyev
@rustamhajiyev 3 жыл бұрын
Hey, Nick! Thank you for another amazing video! As for the second part of the video, it is even better that it was not prepared in advance, because watching you think out loud, analyze the code and make decisions is also very valuable. 👍
@user-pw5do6tu7i
@user-pw5do6tu7i 3 жыл бұрын
i instantly subscribed when he did the outro in the middle of the video for the people who were just interested in the title. a content creator that cares about views time like that will always produce quality.
@0x19
@0x19 3 жыл бұрын
k
@RMDragon3
@RMDragon3 3 жыл бұрын
I don't use "else" that much either but I don't think that forcing yourself to never use it is a good idea. I know you can always add a return early but I only use it if something has gone wrong (like them being underage in the video) and the code between the if and the return is very short. Also, I think the "intended" code should end at the last line of the method because if you are reading the code backwards (which I do when I'm trying to figure out where a value comes from) it makes it easier than having to go to the middle of a method.
@Inertia888
@Inertia888 3 жыл бұрын
I am a beginner, learning C++ & Python, and from my perspective it does seem like a good exercise for learning to become more efficient, but not good as a rule that is written in stone. Sort of like when learning to play chess, a student may start a game with less than every piece, in order to more acutely learn how to take advantage of certain aspects of the game, but would never play a tournament game by starting out with missing pieces.
@stuartmcconnachie
@stuartmcconnachie 3 жыл бұрын
There’s a developer in our office who consistently puts else clauses back in while doing code reviews. Even when I write code.... if (condition) { throw new Exception(...); } He adds the else back in for the following code and does this down multiple levels of nesting. Same with return statements. Someone once taught him functions should only have a single exit point, and he’s carried that over to C# methods. When question he say “makes it more readable to me”. 😜
@manuellernst3700
@manuellernst3700 3 жыл бұрын
I agree with@@Inertia888, branchless programming, not using the else keyword and other techniques are just different ways to do the same thing. Sometimes they can be better than the traditional way, and sometimes they will not. As well, overusing any strategy can always make things messy, as you pointed out when reading the code backwards
@VanLouProductions
@VanLouProductions 3 жыл бұрын
@@stuartmcconnachie Does your office not have some kind of coding standards in place? Especially if you have code reviews, they should check by the ruleset in place, not personal opinion (apart from the fact that the reviewer shouldn't be the one doing changes, that's the author's responsibility; but that's just what I've learned from software quality courses at university, so I guess "the real world" looks different).
@cod3r1337
@cod3r1337 2 жыл бұрын
@@VanLouProductions That's one of the few principles they teach you that actually hold true, at least in well-funtioning teams. What they don't teach you is how to get into that place. Having a team with shared principles and values and a culture of mutual trust and respect and candid but constructive critcism is a rare thing. It took me most of my carreer to get somewhat close to that ideal, and it's still something we need to fight for every day.
@ades3967
@ades3967 3 жыл бұрын
Loved the refactoring section! So many dev videos on KZbin only show rehearsed videos, so it's nice to see the real thought processes as you went along.
@gustav1416
@gustav1416 3 жыл бұрын
Okay, some comments on this. Moving code which is never reused to a function is a nightmare to read. Not only do you obfuscate the code by moving it somewhere else, but you also make it appear as if it's going to be reused, which is not the case. It also leaves you with naming, and when code bases grow big, having a plethora of obscurely named functions is not very good from a tech debt perspective. You also create a longer call stack, which is making it harder to debug. And, not to forget, even if function calls are fast, they do have a cost! Returning early is great for when you have simple conditionals or if you have a set of conditions which are supposed to terminate the function early, but if you have a scenario where it's not a binary condition, i.e. you will have an if-elseif chain, then how would you solve that? The returning early scenario is usually used or thought of as a function having a fast path and a long path, meaning you can, just like you say, return early if a function performs its task or has to abort. But having something run after the conditionals may also get forgotten over time and you end up running that code just because you didn't return in one of your conditionals. Isn't it better to be more explicit about what code you run? With that said, I do agree that big scope chains are annoying to read, especially when closing them, but I still don't agree that returning early is good a universal solution conditionals. Talking about code bloat, is it really less bloated to create a function for a conditional? Look at how many lines of code you have in the end, I am fairly sure you started at 50 and ended with like 70 in the first file and something over 30 in the new, so you doubled the amount of text for basically the same functionality save for a slightly more useful way to add more drinks. I could be wrong but this whole RecipeBook class could be reduced to just using a static map with a String -> lambda mapping, which would allow you to move the drink initialization to the same place without having to introduce an extra class which is used only once, and it would incur less coupling in the code. I hear these mantras and these manifestos, but I hear very little explanation or defense of them. Why do you only want one indentation per method? What's the logic behind it? What's are the benefits? I'd like to break down why these rules are useful and actually get a good argument for why one would want to use them. What I usually see is very typical OOP, abstract everything until you have made everything reusable, and then in the end, never reuse anything.
@Masterrunescapeer
@Masterrunescapeer 2 жыл бұрын
First point with moving code, highly disagree since you should be able to name small functions well, then i can just debug that single function that's giving an issue and the name should be able to be descriptive enough that the name gives away what it does. If it does more than one thing, then you've failed, and that's where naming issues come in. Second point, you're just not writing else since you exit early, so you're bringing in an issue you'd have by not correctly formatting and exiting early. For multiple if else if you have a switch statement with a default case, which is your else. More or less code doesn't really matter that much within reason, it's more important that it's easy to read and maintain. Making every function do one task means it's easy to debug later down the line, I know, I'm currently working on a bunch of spaghetti code for nearly 2 years now, and we're finally at the point where it's okay to introduce juniors to the code base since they don't need an extreme background in the flow etc. to be able to understand what's going on, they can take each function at a time to understand what it does, step by step. And in regards to his examples, all the stuff is simple, imagine it was more complex stuff, decisions with routing, calculating financial interest based on a multitude of factors, etc., that would all be more complex things, these examples or to explain what, not a best-case use of it. I like SRP, if it isn't properly followed in a large code base, issues crop up pretty fast.
@hyperborejskivejsnorec151
@hyperborejskivejsnorec151 2 жыл бұрын
Thanks a lot, now I know about static maps.
@gustav1416
@gustav1416 2 жыл бұрын
@@Masterrunescapeer If you make tons of small functions you mismanage the purpose of a function. It’s meant to be used for reusable code, and making a bunch of small functions that just run in sequence is of no use when all that code could live in a single function. I’ve seen so much code where there are hundreds of functions being run in sequence and only in that sequence. That just adds a constant execution cost to your application (having to push arguments to stack and the return instruction pointer, as well as popping the return instruction pointer) and obfuscates the code for absolutely zero gain :).
@Masterrunescapeer
@Masterrunescapeer 2 жыл бұрын
@@gustav1416 in regards to issues with overhead, your compiler is smart enough that that should very rarely ever be an issue. It's easier to write multiple encapsulating functions that go step by step than one giant function, e.g. Flow of sending a message you'd have a controller that orchestrates accepting it, then process into usable, then send to task, then convert result to correct format, then return. In regards to too many small functions, doesn't matter if function name says exactly what it does, I'm not talking about taking a one liner and making a function out of it, I'm taking about a few lines that are repeated, e.g. Take header from a cookie and do comparison to check what user type and then check is valid for call or something, that's a recent five liner I split off and made generic. Or if it's a business rule, the function on its own is maybe mathematical, say function is area of a circle or something, you'd split that out so you do calcCircleArea, even though one liner so name is there for easy understanding. And no, would not do it with circle area calc, I'm saying rather business rule or other more complex formula. Then removes need of comment, comments get outdated/lost, and quick and easy to debug as an isolated function.
@gustav1416
@gustav1416 2 жыл бұрын
@@Masterrunescapeer If you’re talking about JavaScript you also have the increasing cost of the code download if you keep adding unnecessary text :). Also, don’t rely on the compiler to optimize, you always want to aim for your code to be as optimized as it can by you. The compiler might especially find it difficult to optimize calls between libraries as optimization is most efficiently and most simply done within a compilation unit. Breaking code down to single use functions is of no use at all, all it’s doing is forcing you to split code in arbitrary places and it stops you from moving code around easily without renaming functions and restructuring code. On top of that, you have to navigate the code, jumping back and forth trying to keep the trail of breadcrumbs in your head while you do so, when all of that code could be in a nice neat sequence. I’m not saying code should be repeated at all, I’m just saying I’ve seen code split into functions where the functions are used in only one place, thus making that split a waste of time, effort and at a detriment to readability.
@KevinMarquette
@KevinMarquette 3 жыл бұрын
I loved seeing the refactoring approach to explaining this. Would definitely watch you refactor more code.
@Pedro5antos_
@Pedro5antos_ 3 жыл бұрын
Me too! Refactoring is always insightful
@RichardONeil
@RichardONeil 3 жыл бұрын
I loved this video! I would 100% watch more video of you just coding/talking/refactoring. Very educational. Thanks, Nick!
@AlanDarkworld
@AlanDarkworld 3 жыл бұрын
I agree with almost all of this, except for one key aspect: The recipe shouldn't be an "active" object, i.e. it shouldn't have a "make" method, and in particular it shouldn't take an input/output stream. I think the design becomes much better if the recipe is just a data object that is passed around, and the bartender object is responsible for the "production" of the drink by reading the recipe. This also entails that the recipe itself cannot (and should not) perform an age check. Instead, each recipe should have a "containsAlcohol" flag, and the bartender should check this flag prior to making it, and acting upon it accordingly. This also gets rid of the nasty lambdas in the recipes.
@ZintomV1
@ZintomV1 3 жыл бұрын
100% agree with this. I believe it's called the single responsibility principle. Also I really cringe at the dictionary of Action objects, incurring unnecessary allocations and invocation time. I feel like in this example Action objects were used as if they're as cheap as a function pointer, which they're not. TL;DR: Action, yuk!
@Winnetou17
@Winnetou17 3 жыл бұрын
But but, I want the glass to ask me if I'm of legal age, not the bartender! Jokes aside, it can be seen that understanding exactly who should do what, the responsability of each object, it's quite hard.
@AlanDarkworld
@AlanDarkworld 3 жыл бұрын
@@jason_v12345 that's a good solution... that is, until you have multiple "features" of a drink you need to check for. You could use multiple marker interfaces but it gets messy.
@AlanDarkworld
@AlanDarkworld 3 жыл бұрын
@@jason_v12345 I am absolutely in favor of OOP. But subtyping won't help you much here. You can have a "ContainsAlcohol" interface with no members to denote that. What's next? "ContainsMilk", "IsVegan", etc... zero-member interfaces are an anti-pattern as well.
@ahdog8
@ahdog8 3 жыл бұрын
Nick is probably aware of single responsibility and he chose to have his code be the way it is because he thought it would be more simple. See the wall of text at 14:17
@florianberenice1178
@florianberenice1178 3 жыл бұрын
I definitely agree that removing "else" can make your code look less bloated, thanks for tip. Also really liked the second part of your video and seeing your thought process, please keep doing it!
@elodens4
@elodens4 2 жыл бұрын
Agree. By treating "if else" statements instead as "if guard condition do something, return", code is much more readable. The hot path should be easily identifiable.
@Zysperro
@Zysperro 3 жыл бұрын
Thank you for leaving the last part unedited! It's always interesting to follow someone's thought process.
@Timlaare
@Timlaare 3 жыл бұрын
I Really enjoyed this refactoring focused video! I Would love more refactoring content in the future.
@sandybathwater8385
@sandybathwater8385 3 жыл бұрын
The clean coding aside, the extract method and where you created the switch shocked me... I knew the ide did stuff but I never really looked into it and just did things the hard way for 25 years.
@platinummyrr
@platinummyrr 3 жыл бұрын
yea, modern IDEs have a lot of capability now!
@Voiden0
@Voiden0 3 жыл бұрын
Same here. I was like..... learning IDE stuff here haha
@sk-sm9sh
@sk-sm9sh 3 жыл бұрын
Sorry if I missed something in the vid - as I was going through it in 1.75 speed. Some examples that you described are called guard cases - and I don't recall you mentioning it so I think it's something useful to look into. For example not proceeding to drinking if under 18 is potentially a good example for guard case - because we quit from otherwise possibly a long process. Still IMHO there are a lot situations where 'else' improves readability. Recently over past year/two or so I noticed that I'm constantly being asked by fellow devs to remove else in code like: f() { if( ... ) { return A() } else { return B() } } I wonder if there is some sort of fad going about this whole else thing as it's not first time I see people talking on how to write code without 'else' and I haven't seen this idea going around as much just couple years ago. Argument that I sometimes hear is that else is redundant here. But If I go about removing all redundant things in code then I would end up with golfed code (and spaces btw - are redundant too). From readability point of view to me 'else' is not redundant because it helps keep symmetry between A() and B() keeping it on same level of indentation - to me it's slightly easier to read A and B simultaneously with single glance xxx { xxx A() } xxx B() vs xxx { xxx A() } xxx { xxx B() } It also helps to maintain intent that neither B() or A() is more special in any way (unlike in guard case situation where intent is to show that there is no process symmetry and there is special cases).
@Rexhunterj
@Rexhunterj 2 жыл бұрын
I believe not using `else` is an optimisation. I remember reading about it but CPUs can have trouble with branching code, they'll make a best guess at which branch it should read ahead into, but if it makes a mistake it has to rebuild that code path again which is slow (obviously) By not using the `else` keyword we remove branches from our code in places they aren't necessary. Generally speaking if you're writing a simple tool or DB client interface for example, writing code with less branches isn't really any use because you're not worrying about raw performance in those applications, but you might on a server running checks against certain criteria in the DB. It is also important in video games that become very complex logically and other very low-level software like driver interfaces and such.
@sk-sm9sh
@sk-sm9sh 2 жыл бұрын
@@Rexhunterj branching happens in either case either if() {return} or if(){}else{} Unless one deals with very low level high performance code this usually won't be anything that will matter as the code we write ends up modified in multiple levels until it reaches CPU anyway.
@MastahFR
@MastahFR 2 жыл бұрын
@@Rexhunterj You should never code because compiler will do this or that, or optimize compiled code. If the compiler doesn't manage what it's designed for then you should switch to another language if you need the extra perf.
@rubeushagrid4131
@rubeushagrid4131 2 жыл бұрын
You don't need to write that long just to explain what is opinion based approach. 😜
@AdamLeuer
@AdamLeuer 2 жыл бұрын
I was about to write nearly the same thing, but thank you for saying it first. I won’t try to pretend that leaving out the _else_ statement is philistine heathenry if you don’t pretend like it’s self-evidently preferable. They’re both perfectly adequate approaches that achieve the same result. All other things being equal (and in this case I think they really are equal: claims of optimization through _else_ omission ought to be presented with some evidence) I just happen to value aesthetics far more than I do brevity.
@maniprevo
@maniprevo 3 жыл бұрын
Impressive work, I am thinking how much effort you put in the work. Nice to watch your videos
@LordNementon
@LordNementon 3 жыл бұрын
Make me feel like UPS drivers that never turn left 😜
@andreibalasa745
@andreibalasa745 3 жыл бұрын
I don't use else i use otherwise 😌
@strictnonconformist7369
@strictnonconformist7369 3 жыл бұрын
You may think they’re all right, until they take shortcuts and sign for your Apple m1 Mac Mini claiming they delivered it, saying you rejected it (even emailing me a picture of “proof of delivery” those assholes, when they tried to force it off on the apartment management, even though I was home the entire day and they never got in visual range of my building), so it gets shipped back to an Apple facility across the country automatically per signed package policy of Apple, and they put the cuss in customer service and leave it to you to get it. Lazy dishonest identity-fraud-committing driver, he and his manager should be fired and then charged and punished for that crap. A true story, they take “efficiency” to illegal extremes.
@mmenjic
@mmenjic 2 жыл бұрын
They are trying to equalize the offset made by NASCAR 😂😂😂😂
@Pascal257
@Pascal257 3 жыл бұрын
I think returning early and then removing the else makes the code less readable and also extending it later on, you‘ll have to fully understand it first.
@ZintomV1
@ZintomV1 3 жыл бұрын
In this example he swapped the return early's around (see pinned comment), introducing confusion. However good practice is to return early on invalid input and then have your validated input be used at the end of the method. This is the guidance that most top developers give, and is used all throughout the modern .NET code base.
@adamoceallaigh2267
@adamoceallaigh2267 3 жыл бұрын
​@@ZintomV1 Yeah that's what I do and then use comments to explain exactly what you're doing ie. // Checking for invalid ? , where ? is any variable
@mycurrentadventure
@mycurrentadventure 3 жыл бұрын
Yes, if your check is valid/invalid then an immediate return on invalid makes sense. Anything else adds confusion because "else" tells you something about the intended logic of the code that isn't obvious when removed. But then I code in a very different style that may not be readable to others...
@platinummyrr
@platinummyrr 3 жыл бұрын
This, I prefer keeping an "if ; else" flow because it's immediately clear from the structure that the two sections are mutually exclusive. If you have any sort of code folding going on, then you wouldn't see the return until you examine the contents and realize that section never goes past the block.
@Adiounys
@Adiounys 3 жыл бұрын
@@platinummyrr but why would you have code folding inside a function? If you keep your functions fit a single screen it's not a problem.
@jonydude
@jonydude 3 жыл бұрын
I know it leads to VERY different looking code, but if a function is only ever called in one place, put the code there and use comments. When I’m debugging, I don’t want twenty function calls to follow if I only needed three. Especially because after I’ve finished reading the nested function, I need to read back up the next twenty functions it was nested inside
@omarjennane2620
@omarjennane2620 3 жыл бұрын
Totally agree with you, there is a reason we have comments
@blenderpanzi
@blenderpanzi 3 жыл бұрын
Also if you put it in an extra function someone else might come along and call that, even if it was only ment to be used in that one context, and now you suddenly have to worry about backward compatibility when you need to change that function.
@Madbird95
@Madbird95 3 жыл бұрын
That was my concern as well. I would much rather have the code in front of me, rather than having to search for it, particularly when it’s a one off that still fits in two to three lines of code.
@blenderpanzi
@blenderpanzi 3 жыл бұрын
@@Madbird95 Yes. John Carmack thinks so too.
@AJ213Probably
@AJ213Probably 3 жыл бұрын
Well, you don't always need to read every line of code sometimes and function names can quickly tell you what a segment of code does. If you also write your code in a modular and functional way you can easily test your code too even if you only use that function once.
@DrunkenUFOPilot
@DrunkenUFOPilot 3 жыл бұрын
Nice presentation! For years I've not quite understood those SOLID principles, though most of them made some sense, in some situations. Now I feel enlightened!
@fgregerfeaxcwfeffece
@fgregerfeaxcwfeffece 3 жыл бұрын
So this is where that kind of extremism comes from. I mean i totally see the reasoning behind it: simple rules But simple rules followed this strictly are the exact kind of good intentions that led to certain bureaucracy hellscapes. So i have to kindly ask for your permit A38.
@orzhovthief
@orzhovthief 3 жыл бұрын
Totally true. Langages have if/else as well as switch because they're performing well for different scenarios. This video should be called : why using if/else in a switch case problem is bad. Aside from that there are real life cases where if/else is justified.
@fededevi1985
@fededevi1985 3 жыл бұрын
It is clearly stated multiple times that this is not a strict rule. The advantage of trying not to use else is not removing the else itself (although I think this is an added value), it is that in order to do it you need to write good code in the first place. So the rule should be: If you find yourself writing an else statement, try to remove it, if you cant you should probably refactor your method.
@savire.ergheiz
@savire.ergheiz 3 жыл бұрын
Yep thinking too much will reduce the productivity especially in big project. Also we dont usually have the luxury of time when its a product. Refactoring stage comes after anyhow.
@Manuel3451000
@Manuel3451000 3 жыл бұрын
As with most rules, it's useful to know why it's a rule in the first place. While I do think using returns and switches cleans up the code nicely, there are certain cases where using an else is just simpler and cleaner than blindly following those rules. This was pretty informative and presented a good list of coding guidelines and best practices but one shouldn't be afraid to break a few occasionally if they make the code more convoluted than the simple approach.
@nofatchicks6
@nofatchicks6 3 жыл бұрын
Interesting! I much prefer using the new switch expression over if...else if...else, but I can’t see the utility in completely removing simple if...else blocks. I think understanding the reasoning behind some of these “rules” is instructive, even if one doesn’t necessarily implement them.
@BawzGames
@BawzGames Жыл бұрын
i really liked the part when you free styled and were applying open closed, the comments in hind sight were really usefull and gave me a clear insight into how i need to approach this kind of refactoring! you are great
@CrippleX89
@CrippleX89 Жыл бұрын
Nice and very helpful video! I’ve been doing this unconsciously because I’ve found out the hard way that the “pyramid of doom” (multiple levels of nested indentations) isn’t the way to go. It’s good to be aware of what one’s doing so this video really helped me gaining awareness of these patterns. One thing that I’d have done differently is right around 9:55 you return in the “happy flow” and fall through to the fail state (if input >= 18 return;). Personally, I’d return in the fail state and always end up in the happy flow at the end of the method (guard, exit early and follow the expected result - kinda like the guard-statement encourages in Swift). Thanks for posing these video’s, they’re a great learning tool!
@modernkennnern
@modernkennnern 3 жыл бұрын
I haven't really been using the else keyword for a very long time either. I didn't really realize it until a few months back either, but I think it has to do with my personal theory of 'The less indentation, the better' and generally you get more indentation from else-statements
@gavinreid9184
@gavinreid9184 3 жыл бұрын
Another advantage is that it reduces the temptation to violate the single responsibility principal - you are not doing something else.
@ProtectedClassTest
@ProtectedClassTest 3 жыл бұрын
Look up cyclomatic complexity. The same as ur personal theory
@simonfarre4907
@simonfarre4907 3 жыл бұрын
If you are worried about indentation, stop using C# entirely. You have now saved yourself multiple indentation levels.
@crash1998100
@crash1998100 3 жыл бұрын
Having an else keyword is more readable than returning out of the method if the former is true.
@mikelang4853
@mikelang4853 3 жыл бұрын
It’s the same as using “break” in “switch” “case” as he enters a call to a function with the “if” statement. The readability issue is simply due to your being accustomed to the use of “else” in main code.
@crash1998100
@crash1998100 3 жыл бұрын
@@mikelang4853 Yes, but with switch statements we know beforehand that we will only enter one of those paths, and else statements promise the same thing, but he's breaking the prosumption that those two if statements could both be executed at the same time, and if he doesn't want that then why isn't he just using the else statement which specifically serves this purpose.
@mikelang4853
@mikelang4853 3 жыл бұрын
@@crash1998100 you are free to code how you want and so is he. As long as it works as you intend, it’s just personal choices and how you view it. He’s just sharing another way that it’s possible to write code and how he is doing it now. When a function is called and once inside it, the expectation is that you do something and exit once done. There could be several “if” statements each with “return” statements if it’s true. *obviously the below is not real code* Function stoplight (){ If red, {x=stop, return } If green {x=go, return} If yellow {x= go really fast, return} } As long as the coder knows that there can only be one of the three choices, once the voice has been evaluated as true, the other choices don’t matter for that function call.
@sunnypatel1045
@sunnypatel1045 3 жыл бұрын
Like the way you handle that switch statement. I tend to move towards a strategy factory pattern. But sometimes I do not like to complicate things and keep things simple.
@shayvt
@shayvt 3 жыл бұрын
Great video. Thanks. Regarding the Open-Close principal - the method that initialize the dictionary still need to be changed when adding new drink. You can use IOC container/Reflection to complete the refactoring.
@nickchapsas
@nickchapsas 3 жыл бұрын
Yeah I mentioned this one. It can be done with either composition or attributes depending on how the dev wants to go about it but I didn't want to overbload the video. At least we eliminated method specific Open-close violations :)
@shayvt
@shayvt 3 жыл бұрын
@@nickchapsas by composition do you mean adding IDrink with PrepareDrink method then getting a dictionary of IDrink to the ctor with ioc?
@roccov3614
@roccov3614 3 жыл бұрын
This is what I call "gated if" statements. Makes code very neat and easy to follow and update. Also makes it really easy to add a comment for each check. It is limited to methods because you have to be able to exit at each check.
@lgiorgos1
@lgiorgos1 3 жыл бұрын
It's not limited to methods at all
@GavHern
@GavHern 3 жыл бұрын
I think the word your looking for is "guard clause"
@roccov3614
@roccov3614 3 жыл бұрын
@@GavHern I learnt it informally. I don't think I ever heard the proper name for it. Thanks.
@researchandbuild1751
@researchandbuild1751 2 жыл бұрын
The problem is the checks become order dependent and it may not always be clear where to add a new check. Also some checks can become convoluted if you need to check four things before deciding to return right away because now you get a complex comparison statement.
@mastermati773
@mastermati773 3 жыл бұрын
I noticed this thing when I read that Visual Studio counted both if and if-else statements as the same level of complexity during code analysis.
@pball1224
@pball1224 3 жыл бұрын
I HATE having to scroll all over the source file to read code that can fit all in one screen because someone thought breaking it out was "more readable"!
@GrahamStw
@GrahamStw 3 жыл бұрын
Refactoring at the end was interesting. Good to see your thought processes. I think a better Open-Closed approach might have been to define a Drink class (or IDrink interface) and a suitable sub-class implementation for each drink. The Drinks could then be registered with the RecipeBook to extend it, without modifying the closed RecipeBook code.
@kevinli9212
@kevinli9212 3 жыл бұрын
Totally agree, I find myself rarely use 'else' as I normally would have a return at the end of an if block.
@FrancescoDiNardo
@FrancescoDiNardo 2 жыл бұрын
Very high level content. I am glad I found your channel, I was just annoyed by all these elementary videos about coding, design patterns etc... Your content is very detailed, and I can see your efforts to try to make new developers better by writing readable code! Thanks.
@kicknotes
@kicknotes 3 жыл бұрын
Solid demo. I like your off-the-cuff style. Fluid and flexible, but still easy to follow.
@MartinvanZ
@MartinvanZ 3 жыл бұрын
Although I agree with the video. The example of jumping out of the function in the beer serve check seems to be backwards. It makes more sense to write. If (age < 18) { //Error here Return; } //Continue to serve beer here This way you jump out of the function when there is something wrong instead of assuming the code jumps out of the function when it's right. The rest of the video seems nice. :)
@nickchapsas
@nickchapsas 3 жыл бұрын
Actually I sent through the code again to refresh my memory and you're 100% right. It should be a "negative" check instead
@mirkosedda3196
@mirkosedda3196 3 жыл бұрын
Love when the code tutorials have mistakes 🤣🤣🤣
@alexp-ru
@alexp-ru 3 жыл бұрын
Yeah, I do the same error checking... if (!condition) return; instead of if (condition) { // CODE BLOCK }
@sprytnychomik
@sprytnychomik 3 жыл бұрын
It's cleaner alright, but what about the cpu's branch prediction? Isn't there a silent assumption that expression in if statement (most of the time) is more expected to be true (except for null pointer/ref check)? In init functions cleaner approach is fine, but on the critical paths / in loops might cause a lots of cpu pipeline flushes resulting in drop of performance.
@MartinvanZ
@MartinvanZ 3 жыл бұрын
@@sprytnychomik you would need to check the compiled code to verify. It is not easy to say if it would cause any performance drop. Modern compilers are very good at optimizing code. In case of doubt you could check the execution time. It really depends on the scenario. In most cases I would assume any small performance loss is negligible. Only in other case where performance matters due to many loops etc I would try to optimize the routine for speed.
@beetz0r
@beetz0r 3 жыл бұрын
Thanks for that!. I would love to see how this scenario would work in Mediatr
@vitalygaponenko4184
@vitalygaponenko4184 3 жыл бұрын
Great work. Nice example. It hard to follow this rules but it's worth it. I realized to double dot on line 25 of Bartender. It seems that breaks one of the above rules. Waiting for your next videos!
@motherofallemails
@motherofallemails 3 жыл бұрын
True story, In a software house we had a senior programmer who had allergic reactions to "if" conditional, we had to waste hours to find alternative ways around code in order to not offend him, and when the inevitable bugs later emerged BECAUSE of it, it was "never his fault". Another senior developer had issues with the "inadequate use of brackets", the code became really difficult to read because there were so many brackets, and needles to say, it slowed us down considerably for nothing more than him not trusting the order of operations and the bodmas rule.
@kwkfortythree39
@kwkfortythree39 3 жыл бұрын
Allergic to if? What did you use then?
@etopowertwon
@etopowertwon 3 жыл бұрын
TBF once you get bitten by a & b == c by converting C# into C without realizing the precedence is different, it's kinda hard not to turn C programs into lispy abomination. Though IIRC modern tools report sus precedence.
@xybersurfer
@xybersurfer 2 жыл бұрын
​@@etopowertwon i can understand how that can happen, but i would be skeptical about the precedence when mixing those bitwise and comparison operators. i only really trust the precedence of logical operators (and,or,not) by themselves, and that comparison operators get lower precedence when combined with arithmetic expressions. i tend to apply this rule for all languages
@bradmathews
@bradmathews 3 жыл бұрын
You took complicated code, made it simple and then made it even more complicated than before!
@skaruts
@skaruts 3 жыл бұрын
It always irks me though, that C# programmers seem to be always finding ways to take up more and more vertical space in the code... Every time I look at C# code I can only see like 5-10 lines of actual code in the entire screen.
@BDYH-ey8kd
@BDYH-ey8kd 3 жыл бұрын
You like spaghetti no
@TheThursty100
@TheThursty100 3 жыл бұрын
Put all the code in a single line, heck yeah!
@nemesis8508
@nemesis8508 3 жыл бұрын
Funny you say that as I am a C# programmer and I constantly think about how to use a few lines of code as possible. Idk if that makes me a good programmer but it certainly feels good having few lines of code
@1DrowsyBoi
@1DrowsyBoi 3 жыл бұрын
I think it largely depends on WHAT you're doing with that code. If you're conserving space just for the sake of conserving space, I'd rather just have the extra lines. Allman is very readable and good code should be easy to follow what's going on. Not like you're going to have to re-read every line of code multiple times every day just to understand what the code does again.
@Adiounys
@Adiounys 3 жыл бұрын
Why C# particularly? I see this everywhere. I think people think they code is more "clean" just because they spread it out, plus they can be proud how many lines they wrote. The thing is, if you had mess in your room and spread it evenly in a stadium, it may look clean there, but it's still the same mess. Personally, if I would refactor this I would write something like this: private void HandleBeerAgeCheck(int age) => _outputProvider(age >= 18 ? "Here you go! Cold beer." : "Sorry... blabla");
@manuelornato3722
@manuelornato3722 2 жыл бұрын
This video made me realize I too don't use "else" anymore! It happened totally unintentionnaly. I just applied usual recommended refactoring (and often just followed Resharper suggestions) which led me here.
@iGexogen
@iGexogen 3 жыл бұрын
If I was video blogger and decided to make video on this topic, I would call it "Why you should reduce your nesting as much as possible", problem is not with "else" keyword at all, problem is about unneccesary deep nesting. I rarely convert my code into switch statement, but if my method contains more that two nested ifs, I reconsider my architecture.
@nickchapsas
@nickchapsas 3 жыл бұрын
I highly doubt I would click on that video based on the title. This is both about else and nesting. When nesting was 1 level deep, I still removed the else because it's pointless. Nesting isn't a familiar concept to most people while "else" is.
@iGexogen
@iGexogen 3 жыл бұрын
@@nickchapsas If somebody has one level deep nesting and has elses, "why you do it? " - is the first question you gonna ask.
@T33K3SS3LCH3N
@T33K3SS3LCH3N 3 жыл бұрын
6:40 the problem with this approach is that many codebases require you to search through methods later on. Seperating one function into four makes that task a lot harder. It works great when you read the code from start to finish, but that's often not feasible in larger projects. This approach of micro-functions also creates a lot of vertical seperation throughout the file, which can drive related important pieces of code far apart when it would be much handier if they were adjacent.
@strictnonconformist7369
@strictnonconformist7369 3 жыл бұрын
I’ve been doing developer support for a total of over 6 years now, and lots of tiny functions nested deep through a dependency graph of a lot of objects that exist from who-knows-where (often set up long before you get to that code) in large codebases (either customer’s code, or OS code) especially when debugging release optimized code in assembly (without full source, but hopefully symbols) is a real nuisance. This is especially true and a major combinatorial explosion when there are multiple types of possible subclasses or implementations of interfaces/protocols (depending on language/terminology). You can read all the source code, but with a large enough OO codebase, do you really have an efficient way a priori to know which types of classes will actually be used without verifying all the possible types? Nope, not in a practical sense. Meanwhile, long procedural functions with relatively short stack depth is relatively easy to identify what’s going on, because you’ll likely have more information at hand to identify which things could actually be called: fewer potential breakpoints you need to set to identify actual flow. Multiple levels of OO dependency graphs with subtypes of objects is just a more abstract way of representing an arbitrarily complex dependency graph of hairy switch statements in a manner that’s deceptively simple in appearance: both an asset and a liability for understanding the code flow, depending on the time and reason you’re reading it and trying to modify it.
@uumlau
@uumlau 2 жыл бұрын
I would argue that splitting out methods to remove nesting is often just as difficult to read as the nesting, especially for debugging purposes. Having to hop from subroutine to subroutine just to figure out the CONTEXT of how the bug happened is a lot of work. I personally find it a bit easier to debug the nested version, because I can quickly scan up and - for example - figure out exactly what line results in the object 20 lines later being unexpectedly null. Doing that through several levels of subroutine function calls often requires me to re-run the code in debug mode over and over, once for each level of function call. Of course, both arrangements are difficult to read in their own ways, but the REAL reason for the difficulty is that the design is a brute-force decision tree. Your refactoring into a dictionary of method calls is a great way to simplify things: each drink has its own code, so I know where to debug right away. Sometimes, however, we're stuck with a brute-force decision tree. Your dictionary works because it conceptually models the requirements of a bartender very well: one action per drink. Easy peasy. In real-world coding, we often have a fairly tangled mess of requirements that doesn't parse out so neatly, namely that the requirements are a set of arbitrary rules with all the "if then" logic stated in those rules. In such situations, I find that having the coded version of those requirements closely parallel the literal requirements, no matter the level of nesting, to be the most readable - because you really can't make it more readable than the requirements. You might be able to reduce the requirements into a simpler logical construct, but then everyone after you will have to prove to themselves that the simplification is correct, so while your code might be more readable, it's more difficult to verify that it's correct. Further, if code closely parallels requirements, then it is possible to verify whether the requirements are correct! For example, SME claims your code has a bug, you show SME that the code does exactly what the requirements say, then together you both can determine whether the requirements are wrong or the code is wrong. Yeah, the code is difficult to read because the requirements are difficult to read, but dang, matching the requirements closely saves a lot of work. The guardian "return" approach you use is good, especially as I find it very easy to debug code that returns a failure quickly, as it is obvious which condition isn't letting the main method proceed. Outside of guardian code, however, having multiple exits makes things difficult to debug, especially with several levels of function calls, because it's almost never clear which call in the chain is the reason for the early exit: the guardian code needs to be at the beginning of the method, not layered throughout. Then there's the overall question of what makes code more readable. A short essay is readable because the paragraphs organize the ideas in a way that shows how they all relate together in a global sense. Some ideas are more important than others. Some ideas deserve only a sentence fragment, not a full paragraph (their own method), while other ideas deserve to be fleshed out in their own paragraph (or even two). Similarly, code is made readable by making the lines of code clearly denote the relationships of the ideas involved. You determine that it is readable code by READING IT when you are done, and editing it to make it more clear in a global sense, not in a nitpicky "correct grammar" sense. In code, we tend to pay attention to the trees in preference to the forest, because we have to analytically verify each "tree" to make sure it works right, but those who read our code necessarily start at the "forest" level, and we want our forest to be arranged such that they can quickly figure out which tree(s) to look at. There is an art to this, as what is readable to one coder isn't necessarily readable to others, and it takes a while to learn what other coders think of as easy to work with, and what they find difficult to work with. This knowledge cannot be reduced to an analytical set of rules.
@appuser
@appuser 2 жыл бұрын
I _always_ have this problem, the deeper you have to go within the stack the more you have to rely on your brain to keep track of a given path through your program. Perhaps rules around nesting should relate to subroutines as well (a method can only call another method, and maybe that one can call a method only). Another rule might be that you're not allowed to split a method unless it's used in multiple places, readability be damned, DRY is more important than clean-looking.
@falias4
@falias4 2 жыл бұрын
I think your main topic isn't the debugging or the context but having to deal with poorly written code. All your arguments come down to the fact that the code probably sucks and has many side-effects in the subroutines. If you know why you break it down in individual functions and understand clean code it will be a pleasure for other coders. With (almost) no side-effects the context is super small at any place in your code and the functions/variables tell you a story instead of showing you a forest. 😉
@zondaken
@zondaken 2 жыл бұрын
Smaller code units makes it easier to debug though? If you have a small code you can easily tell or even test if its doing what it's supposed to do.
@uumlau
@uumlau 2 жыл бұрын
@@zondaken The problem I find with "smaller code units" is that it becomes remarkably difficult to find the specific unit of code that has the bug. Even if I have a stack trace that specifies the right line, the cause of that exception is typically an unexpected null object: there is no bug in the line throwing the exception, the bug is whatever is providing bad arguments, and the bad arguments typically arise from some much earlier call that is also working just fine, but in that particular instance the database or REST service has no data. You might argue that we just need to handle the null case and be done with it. Once in a blue moon, that is the correct way to handle it. Far more often, the business requirement is to figure out why we have bad data in the first place, and at a minimum, my job is to figure out where that bad data is coming from, so someone else can hunt down why it exists on their end. "Smaller code units" is a good approach when considering only whether the code logic is self-consistent and correct, when the fix needs to be made in the part of the code throwing the exception, when the CONTEXT of the code doesn't matter. It's not so good for cases in which context matters, such as exceptions that arise from unexpected real-world data, because that bad data arises elsewhere. I need to know the overall context in order to have a clue what data was expected. And not just what class or what type, but enough info, for example, to tell whoever manages the data loading which specific id is missing from their data set. TL;DR - in my experience, most bugs don't arise from a bad line in a specific unit of code, but instead arise from the chaotic and unpredictable interactions of hundreds of perfectly-correct "smaller code units". The faster I can find which specific path through those code units causes the error, the better.
@zondaken
@zondaken 2 жыл бұрын
@@uumlau that makes sense to me. Unfortunately I'm not as proficient with real world examples. But what I can say is, that if a code unit is considered correct, it shouldnt be the source of error in said case. So if the unit accepting the passed data isnt verifying (let it be by simple asserts or complex analysis about "correctness" of data) the data, then may as well consider that unit not correct or at least error-prone. Not sure how wrong/correct I am, but that's at least from a logical point of view and with my own programming experience.
@lassel1644
@lassel1644 2 жыл бұрын
Good video! I agree on the ternary thing too. Sometimes ternary conditions could be useful, for instance for Table grid coding in UX scenarios for instance.
@fat-freeoliveoil6553
@fat-freeoliveoil6553 2 жыл бұрын
I pretty much always do this too. I'd say it's practically essential in networked code as you will often do null, permission and locked checks at the beginning of a method before continuing on.
@willemschipper7736
@willemschipper7736 3 жыл бұрын
Uses ternary operator everywhere like a boss
@nextlifeonearth
@nextlifeonearth 3 жыл бұрын
Instead of an else you can always use goto.
@csabraxas
@csabraxas 3 жыл бұрын
@@nextlifeonearth thats illegal
@nextlifeonearth
@nextlifeonearth 3 жыл бұрын
@@csabraxas if (condition) { doThatThingy(); goto afterElse; } doTheOtherThingy(); afterElse: I love programming.
@digitig
@digitig 3 жыл бұрын
Usually forbidden in safety critical code because in practice it's been found to lead to write-only code and too many bugs.
@nextlifeonearth
@nextlifeonearth 3 жыл бұрын
​@@digitig Yet safety critical libraries like OpenSSL actually use goto. I assure you the people who made that knew what they were doing. It's also the best way to get out of a nested loop or sometimes even switch. If you don't know how to use it, then by all means don't use it. Dismissing every case where it's being used is ill advised however.
@ZintomV1
@ZintomV1 3 жыл бұрын
10:13 usually instead of returning if your conditions are met, you would do it the other way round, also known as "returning early on error/invalid input". That way you can have multiple conditions at the top which will exit the method early, and the final chunk of code is where you handle your "valid" input.
@nickchapsas
@nickchapsas 3 жыл бұрын
Yeah that was a brain fart, I mention this in the pinned comment. I never actually code it the way I showed in the video so no idea why my brain at the time thought it was ok
@ZintomV1
@ZintomV1 3 жыл бұрын
@@nickchapsas No worries I just read the pinned comment after writing mine! Good video though as it does introduce some new concepts to new programmers. I'm just watching because I'm bored xD you are entertaining.
@thomstunes6485
@thomstunes6485 2 жыл бұрын
Yep, I do that also. When I have lot of conditions to check, I start to check most common ones and go out of the method/function straight away. So no need of if else if else if else blocks. Only If statements with straight return if condition is true. This makes the code way more readable (and you can write on a single line) but also much faster because you won't check useless conditions. Looks like : if (condition1) {return false;} if (condition2) {return false;} .... if (conditionXX) {return false;} return true;
@GaryWee111
@GaryWee111 2 жыл бұрын
Wow, thanks for your expalanation and examples! I finally understand how these things work, can't wait to try myself tomorrow.🥳
@avocadopeel7536
@avocadopeel7536 3 жыл бұрын
I preferred the original method, I don't wanna be scrolling up and down looking for other methods when I'm trying to find where the code flows after I've been debugging for 3 hours
@anonymouse9105
@anonymouse9105 3 жыл бұрын
I'd rather use ELSE than have multiple exit points. Having said that, one way I reduce the use of ELSE is when flow isn't affected like setting variables. For example: x=1 If a=b { x=2 } Rather than if a=b { x=2 } else { x=1 }
@Masterrunescapeer
@Masterrunescapeer 2 жыл бұрын
But you'd not do that, something like that you'd do `var x = a == b ? 2 : 1;` which is technically also an else, but you're not using the keyword. Multiple exit points if they are correctly structured as guard statements reduce complexity, since nesting if I have a large trail to go follow to see how to get there.
@anonymouse9105
@anonymouse9105 2 жыл бұрын
@@Masterrunescapeer I do like that syntax, ngl.
@aussieexpat
@aussieexpat 2 жыл бұрын
This seems silly. What if x=bla is a really expensive operation?
@nathanvangoor4979
@nathanvangoor4979 2 жыл бұрын
@@aussieexpat Exactly, very often such statements will be much more expensive then this example.
@kylekeenan3485
@kylekeenan3485 2 жыл бұрын
I agree with you, love the ternary operator.
@michaelgraf6773
@michaelgraf6773 3 жыл бұрын
Interesting approach, with javascript as my main language i dont really have many problem with the other things mentioned in these rules. I think they make sense to some degree, but with the ability to use ternary operators for simple single line if/else statements and the ability to use inline arrow functions to aviod unecessary indentations, I feel, that these rules are very easy to follow. for preconditions, like an age check or checking if we found db entries, a negative condition that uses a return statement or throws an error should be the default. Whatever rules you follow as a dev, I think the main thing to think about is, that the code we write in our highlevel programming languages should in most cases be optimized for readability and after that come things like speed and and memory usage (depends on application tough). Code thats hard to read is hard to maintain and will only get worse over time and eventually needs a large refactoring. Thanks nick for teaching the world how to write clean code
@programmer5855
@programmer5855 2 жыл бұрын
Agreed. I've never really liked using "else", I've always done what you have shown here in regards to using a switch and returning from methods.
@majorjohnson8001
@majorjohnson8001 3 жыл бұрын
I don't think this is an `else` problem, but a `nested statement` problem.
@guywithknife
@guywithknife 3 жыл бұрын
Pff just use a language with pattern matching match/case statements and flatten all your conditions 😂 Condition-heavy code isn't great anyway. I don't think a hard rule like "only one level of nesting" is a good practice, don't extract methods just to keep low nesting, extract method when its a logical nameable thing. Of course you should strive for little nesting, but I don't stress over it either. Besides, that extra nesting where he has age >= 18 would go away if he used `else if {` instead of `else { if {`. I mean, I get that examples are hard to keep meaningful yet simple enough to understand and he does call this out when he mentions the SOLID principle. That would largely solve this particular case anyway.
@draco18s
@draco18s 3 жыл бұрын
​@@guywithknife Oh sure, switch statements are great (I actually have a section of code right now that should be refactored to use it, heh). And you're right about "only one nesting level" being nice, but not critical. I've got nothing against something like: for...{ if(obj != null && obj.somevalue == checkvalue) { //do simple thing instead of for...{ if(obj == null || obj.somevalue != checkvalue) continue; but I will do things like for x...{ for y...{ if(x+ox < 0 || x+ox >= width || y+oy < 0 || y+ox >= width) continue; if(x == 0 && y == 0) continue;
@guywithknife
@guywithknife 3 жыл бұрын
@@draco18s even switch statements are quite limited, I was thinking more like what many functional languages provide. Switch statements can help, but in general the SOLID principles apply: don’t hardcode your conditions if they’re complex and may change. I agree with your example, I do that too. I suppose it’s just whatever is readable to you (in six months time when you’ve forgotten what the code does) One thing I would comment on with your example is that I rarely use continue because I rarely need to. Often it’s possible to apply Mike Actons data oriented programming advice and remove the items from the list in an earlier step, so in the loop you don’t need to skip items at all. Obviously that’s not always possible, in which case whatever, but when it is, I find it super helpful both for clarity and performance.
@davidyoun8721
@davidyoun8721 3 жыл бұрын
I must be missing something because in my opinion this is harder to read. I agree with this statement completely, if your code is nested that deep it's probably better to just methodize it out.
@draco18s
@draco18s 3 жыл бұрын
@@davidyoun8721 The lack of syntax highlighting probably isn't helping. I just meant that if the contents of my if-statement is like one or two lines, I generally won't bother with an early exit (because the early exit is *also* only one line). But I do early exits for for-loops to check for out-of-array-bounds-ness though. There's no point in extracting it out to a method because that for loop nest has *already* been extracted to a method (eg. count_adjacent_matches(grid, x, y, matchTarget))
@thomasburette9129
@thomasburette9129 3 жыл бұрын
Good practices are rarely universal. One needs a sense of 'taste' to determine whether the practice is applicable in a particular situation. You mention this quickly at the end 20:06. This applies to extracting methods, return instead of else and creating classes instead of switches. If you use extract method *where you shouldn't* you end with methods that have little meaning by themselves, are highly coupled together and code that is hard to understand because you have to keep jumping from function to function to follow what's going on. If you create class to remove switches *too aggressively* you may introduce a lot complexity (classes with composition/inheritances) that end up making code more complex than it needs to be. Other times it's the perfect choice.
@nickchapsas
@nickchapsas 3 жыл бұрын
I find smaller methods with most specific code way easier to work with and the method read way clearer to me. This is subjective, as is the whole video but I get your point as well.
@cyberherbalist
@cyberherbalist 2 жыл бұрын
I've been retired from coding for about 6 years, and I see that new syntax has been added to C# since then. Now I'm rather interested in finding out more -- thanks for waking my coding brain cells up!
@tobidaada
@tobidaada 2 жыл бұрын
I like how you use the keyboard shortcuts to efficiently navigate and refactor your code.
@mze745
@mze745 3 жыл бұрын
As far as i know this pattern has a Name: "Guard Clause"
@shikyokira3065
@shikyokira3065 3 жыл бұрын
yeah. I'm surprised it isn't a common knowledge for many programmers, in fact none knew about this in my company when I first joined. I had to teach all the developers about writing clean code and so on. Partly I blame the education system in uni that doesn't teach students about simple things as best practice and effective code writing. Me being a self taught programmer learned these through open source projects and articles, I encourage people do the same
@AyushkaPartohap
@AyushkaPartohap 3 жыл бұрын
It's expected for guard clauses to throw exceptions instead of returning an error or nothing. For example, returning an error or just returning won't work in methods with a return type. Then again this is specific to typed returns in languages that have them.
@shikyokira3065
@shikyokira3065 3 жыл бұрын
@@AyushkaPartohap not entirely true. But I get what you are trying to say. Guard clause is actually based on the return early rule, so it can also return result early not just throw exception early. Another principle guard clause follows is to reduce scope of variable, or number of scope
@bl1tz229
@bl1tz229 3 жыл бұрын
​@@shikyokira3065 First of all, I completely understand where you are coming from. Everybody probably 'wish' they knew this from uni. It is however not necessarily the uni's task to teach you things like this. Learning things like this is something that comes with practice and even then it should not be learned as "truth" or the "Best way to do something". I think it is very much more valuable to learn it by 'seeing' and experiencing yourself that 'this' or 'that' is a good approach. So what you say that you teached other developers this way of thinking about it, is something SO VALUABLE and you definitely should not stop doing. Maybe someone else will teach you a thing or two and then you would also hope Uni taught you that, but they didnt.... I guess my point is that you cannot teach "EVERYTHING" in uni and some things you learn by experience. In 1 year you will maybe think back about what you wrote and the outcome 9/10 times is probably: "I would write this better now". That in my opinion is and should be completely fine, even though you wish you would know beforehand :) That is what learning and progressing really looks like.
@shikyokira3065
@shikyokira3065 3 жыл бұрын
@@bl1tz229 um.. you got a point there. And certainly we can't learn everything from uni. I'm just highlighting the importance of it, and since uni is kinda the process we normally go through to gear ourselves up, missing this out feels like missing out 1 of the important tools that we very much need when gearing up. And i totally agree with you that learning it by 'seeing' it and experience it, is valuable. Just like in uni, we normally have to go through research papers done by other researchers. Same should be done for "programmers", go through open source projects, and obviously must at least has a standard, not a "cmd snake game" kind of project... you get what i mean
@DayZilya
@DayZilya 3 жыл бұрын
Kotlins WHEN keyword: "Let me introduce myself"
@tuberklz
@tuberklz 3 жыл бұрын
is it kind of like switch expression? i just loked at an introductory video. i think if you are familiar with .net stack, you would love f#
@aveshlutchman8573
@aveshlutchman8573 3 жыл бұрын
@@tuberklz kinda, but it's much more flexible, it's like a switch which has the full range of if functtionality available, also because it's Kotlin, you don't have to worry as much for unexpected NPE being thrown.
@tmbarral664
@tmbarral664 3 жыл бұрын
@Nick: when you changed the to function/method call, ok, it's more readable. But most importantly, it is the right way to think about any algorithm. From the general to the specifics. From the high level to the finer details. Anyway, a pretty good video you have here, mate. What you gave us here is a nice rediscovery of the theory we learned at the U. Well done. And keep going. ps: also, in the refactoring, when you remove the else and place a return, you're helping the reader to read your algorithm. I mean, the method servebeer is ... to serve beer. so that's the "algorithm", the most important part of the code. It can run without the age check. Therefore, it's good practice to do what you did. It allows the reader to see 1: the main intent 2: the exceptions.
@nmillard
@nmillard 3 жыл бұрын
Great stuff man! I've also completely ditched the 'else' keyword. I wrote an article a year back on this that blew up. I guess lots of developers still have to discover how awesome it is to live in an 'else'-free world.
@vast634
@vast634 2 жыл бұрын
Is there any problem with "else" or do you just like to jump through hoops not to use it?
@nmillard
@nmillard 2 жыл бұрын
@@vast634 when would you ever need the else keyword besides for micro optimizations?
@MrBa143
@MrBa143 3 жыл бұрын
Watched a best practice video from Unity, where they refered to this as a "Guard clause". Basically set up flags and return early if needed. Ends up with alot less "else" statements and alot less indentations
@billyii2877
@billyii2877 3 жыл бұрын
There is no need for if, else, loops or anything like that. Real men use assembler and jumps
@ChristopherSalisburySalz
@ChristopherSalisburySalz 3 жыл бұрын
I agree completely about extracting the methods and keeping indentation levels to a minimum. It is much easier to quickly identify what the code is doing without getting bogged down in details. The details are still there if you need to see them so it's a win-win for me.
@stindare2230
@stindare2230 3 жыл бұрын
The more I develop the more I agree. I usually use a little more flexibility than what he's describing, though. I didn't used to like extracting code out of methods into private methods that only get called in that one place, but the readability benefit is pretty nice. I also found that if I was doing it a lot in a given method, then it was time to possibly refactor that some other way, too.
@Rhodair
@Rhodair 2 жыл бұрын
I've definitely drifted in this direction where I use else more sparingly than years before - it could stem from bad experiences reading coworker's code nested a dozen times over - most of my code rarely goes more than 2-3 nests, but I don't completely omit else either
@tornoutlaw
@tornoutlaw 3 жыл бұрын
I am a noob and today I learnt that you can return in a void method to stop executing the following statements. Neat.
@richardikin
@richardikin 3 жыл бұрын
Multiple exit points breaks one of my strictest rules, so that's a definite no. I have no issue with simple if-else statements, but if-elseif-elseif-elseif-else type statements should be avoided if possible.
@turn1210
@turn1210 3 жыл бұрын
Yeah, it’s a bit of a code smell at that stage
@willinton06
@willinton06 3 жыл бұрын
Yeah I leave MEP for nuclear situations only
@phucnguyen0110
@phucnguyen0110 3 жыл бұрын
Thank you for this one, Nick! Not sure if this is useful or a bit too deep for an entry-level/newbie programmer like myself, but at least I understand the idea :D
@Ferdam
@Ferdam 3 жыл бұрын
I've been doing this for years and I didn't know it was part of a better code rule set. I mean, I didn't think you could actually drop 'else' keyword in any case, but I was seeing myself questioning why use it in many codes I write. From now on I'll be more confident with the decision of not using it. Good one!
@philperry6564
@philperry6564 10 ай бұрын
It's not part of a better code rule set, quite the opposite.
@oliverthane2868
@oliverthane2868 3 жыл бұрын
I agree with most of your early points ... but the level of oo is making me nauseous
@ode4473
@ode4473 3 жыл бұрын
default in switch case is "else" =D
@strictnonconformist7369
@strictnonconformist7369 3 жыл бұрын
Shhh, you’ll rouse the rabble in the insane asylum :p
@kj2w
@kj2w 3 жыл бұрын
Why use IEnumerable instead of List? Bonus Question: How would you write unit tests for those private methods? Also, thank you for 2 things: - Showing real world example of Delegates - Introducing me to Object Calisthenics
@nickchapsas
@nickchapsas 3 жыл бұрын
I use an IEnumerable because a List is a mutable data structure. I could use an IReadOnlyList instead but at that point an IEnumerable communicates the type well enough. The private methods are unit tested via the public method. You don't write unit tests for unaccessible methods but you write scenarios for the public methods that those private methods are being used in.
@kj2w
@kj2w 3 жыл бұрын
@@nickchapsas Thank you for the response sir!
@chrisfair9228
@chrisfair9228 2 жыл бұрын
I watched the whole video and I appreciate your video style. The title made me think there was some significant reason not to use else (performance or clarity perhaps), though it seems this is a 100% aesthetic choice. I am not sure I agree with this being a better aesthetic, I agree that it resulted in fewer lines per method but to me you made the code harder to follow. I personally think indention in the if/else makes the code more readable because I can instantly see that the indention level indicates that these lines of code could be equally weighted in relation to each other because they follow one another at the same indention and I can clearly see that from the if/else structure. When the else is removed for an early exit I now initially read the code as an escape condition preceding the rest of the intended processing which unequally weights the importance of the code blocks in the mind.
@AyushkaPartohap
@AyushkaPartohap 3 жыл бұрын
You sacrifice the subtle simplicity of always having one place where methods return for what is essentially a distaste for indentation and brackets since using else is not nesting. I think multi exit is ok for 5 maybe 10 liners with max 2 exit points. Beyond that, it stops feeling good.
@lukassinkus6162
@lukassinkus6162 3 жыл бұрын
Well the point is also to not have such long methods
@markojozic3944
@markojozic3944 3 жыл бұрын
Well i wouldnt say that there is a distaste for identation and brackets but more an approach to make the projects more flexible and scaleable. Imagine you'd have to implement more complexity to your software like considering laws of different countries or translations or an API for third-party. To give you a more visual representation of this imagine the following: Always throwing your cloths on a big pile in your room has the simple simplicity that you can always find everything you want to wear in one place. You dont even need a drawer. ... Makes (maybe) sense if only have like 2 jeans and 2 shirts But what if you buy new clothes . What if you want to sepperate your expensive shirts from your old sweaters? What if you dont want your other shirts wrinkled just because you are looking for a pair of jeans. What if you're tired of spending every day 15 minutes just to find your socks? The bottomline is .. the more your software grows the more you want to keep a specific structure which allowes you to minimize the effort for changes or extensions.
@researchandbuild1751
@researchandbuild1751 2 жыл бұрын
@@lukassinkus6162 then you just add even more mental context switching
@gmnevton
@gmnevton 3 жыл бұрын
Liked it, but it's more mental gymnastics, good when You have time to do some refactoring, but in real life scenarios, it is quite not afordable.
@NicolaiSyvertsen
@NicolaiSyvertsen 3 жыл бұрын
Besides most experienced programmers already return early if they can and it is obvious to do so. Why use a temporary variable when you can just return the results directly. This video went way out of scope. Explaining why you don't need else takes 1 minute tops. All the rest is about clever ways to refactor your code.
@stindare2230
@stindare2230 3 жыл бұрын
@@NicolaiSyvertsen I was thinking the same. I like the guy's videos, but this one really felt like it stretched the material. Didn't need 20 minutes in what could have very easily been 10, and 5 is still more than enough.
@lexxynubbers
@lexxynubbers Жыл бұрын
I was taught 'one point of entry, one point of exit' in 1988. Multiple returns to avoid an ELSE would violate that.
@CodingWithUnity
@CodingWithUnity 2 жыл бұрын
Started doing this about half a year ago, really helps clean your code up. If you mix this with making sure your functions are honest will naturally make you follow the boy scout rule. By honest functions I mean, don't name a function something then hide some code in it that's not obvious to the name of the function. It's a very common problem because it's so easy to do. A quick example is something that returns a value. Don't manipulate your program in a function that, any dev reading the name would assume, just returns a value.
@syriuszb8611
@syriuszb8611 3 жыл бұрын
No one: Clean coders: don't use "goto"! Everyone: ok, seems fine. Clean coders: don't use "else"! Everyone: hmm maybe? In future, no one: Clean coders: no more than 4 lines of code in a function! Everyone: what? Clean coders: don't use "if"! Everyone: wait, what? Clean coders: don't use ! Everyone: wai... Clean coders: reject humanity, return to monke! If you do not use "else" it looks a little less bloated, BUT at first glance, it looks like you print two messages instead of one. And if you collapse the if statement for whatever reason you will for sure think that second option is printed always. With "else" you know for sure, and at a glance that it will only be used sometimes. Also, else makes it more symmetrical, which is a aesthetically a plus for me. But that is only my opinion, it may be very well valid point. I, for sure am not a clean coder yet ;-).
@coalgolem4697
@coalgolem4697 3 жыл бұрын
Clean coders be like Int main(){ EntireProgram(); }
@Masterrunescapeer
@Masterrunescapeer 2 жыл бұрын
What I hate most about C# is the lack of fall-through, and only way to do so is to use a goto case, which means everyone reviewing it instantly throws it out since dreaded goto keyword. /sigh (Do agree with not using Goto though, ends up with the most spaghetti code ever, 98% of the time there is a better way of doing it)
@HoganLong
@HoganLong Жыл бұрын
@@Masterrunescapeer case statement fall-through is one of the hardest features to maintain. It is terrible. It does let you write shorter code. But objectively harder to read.
@xcoder1122
@xcoder1122 2 жыл бұрын
"Early return" has its benefits, yet it can also make code harder to read if it becomes longer as there are many places your method may be left instead of just one. Generally I only use else for "final statements", that is code that shall be executed no matter if the if-path or the alternative path has been taken and quite often such statements don't exist, in which case I will also use early return. However, following your sample, I would neither use if-else nor switches, I would actually use objects and dynamic dispatch at runtime, which is even less and even simpler code. The code is split upon more objects, yes, but the code each object is tiny and if you need to add another case, you don't need to touch existing code at all, you just implement a new object.
@mrcarlpaton
@mrcarlpaton 2 жыл бұрын
Super interesting, I always learn something new when I watch you code. I like the unscripted nature of this video my mate, thats how we program daily!
@applesthehero
@applesthehero 2 жыл бұрын
imo the ternary expression is far more readable than having an if block followed by a stranded line of code. With the ternary statement, it's you don't have the repeated output template, and it's clear that you're just toggling the content based on a check. It's just so much cleaner!
@Xiuhtec
@Xiuhtec 3 жыл бұрын
As a novice, the part that boggled my mind was how simply you automated the string at 15:50. I'd have spent half an hour figuring out how to manually create a comma separated list from my keys without an extra comma at the end or something.
@eeromutka186
@eeromutka186 3 жыл бұрын
In this video: How to multiply your LOC by 10x and make it less understandable and straight forward!
@paulmaguire7917
@paulmaguire7917 2 жыл бұрын
Nesting IF statements exponentially increases the code complexity in terms of the number code paths. If you count the number of code paths at the beginning and then compare that to the number after the else / nested IF's are refactored then you'll be surprised by the difference in values just from a small bit of code. This is what I came across and how I learnt to appreciate the complexity with nested IF statements and ELSEs particularly when it comes to systems and/or regression testing. Also, if the number of code paths is kept to a minimum then you can get away with dry testing your method(s) i.e. covering all code paths more easily.
@alcidesneto6415
@alcidesneto6415 3 жыл бұрын
Love this video, Nick. Thank you so much!
@jondo7680
@jondo7680 3 жыл бұрын
Is adding return instead of else really better? You can overlook the return and think the else part is always executed at the end. But you can't overlook an else which adds extra intention.
@wesleyguthrie5560
@wesleyguthrie5560 3 жыл бұрын
It's definitely not better. Totally violates one of the principles of Clean Code. The reason it looks cleaner is because adding an else creares an extra 3 lines of clde since he's using uncuddled curly braces. Really dumb imo. Just use ternaries.
@TheGangstaMofo
@TheGangstaMofo 3 жыл бұрын
Omg yes, that's what I thought. I feel like it actually makes the code less flexible. Say you have to edit one of the 10021 methods you need to create for this, and in one of them you forget to remove the return statement or whatever. It's gonna fuck you up. This is just so messy and illogical.
@LightRayTracer
@LightRayTracer 3 жыл бұрын
This is just silly. The "default" in the switch is equivalent to the "else" keyword. Furthermore, the ternary operator has an equivalent else part. This really is a personal choice with highly subjective advantages.
@nickchapsas
@nickchapsas 3 жыл бұрын
If you watched the full video you’d see that the switch was refactored out as well. Also something can be the equivalent of something else but doesn’t mean it’s the same
@ben-mx3cs
@ben-mx3cs 3 жыл бұрын
@@nickchapsas Default is basically else... Seems like you're splitting hairs here. And what's wrong with else? It clearly conveys the intent of the code, unlike an abrupt return in the middle of your function.
@stuartmcconnachie
@stuartmcconnachie 3 жыл бұрын
9:55 the “not old enough” is an error condition if you ask me. It makes more sense if you code it as the if condition and fall through to “serve beer”.
@nickchapsas
@nickchapsas 3 жыл бұрын
Check the pinned comment
@clashclan4739
@clashclan4739 Жыл бұрын
Expecting more software architecture, design patterns and best practice videos ❤
@henrivanwesemael
@henrivanwesemael 3 жыл бұрын
The use of multiple exit points in a function makes it harder to maintain.
@nickchapsas
@nickchapsas 3 жыл бұрын
This largely comes down to personal preference. For me, it is way harder to have a single exit point in my methods. I much prefer multiple exit points because they are very clear in terms of where the method's "story" starts and ends. Code that uses single exit point is also really hard to read for me and usually involve heavy nesting due to that, which I don't find good to my eye. Again, all very subjective.
@iGexogen
@iGexogen 3 жыл бұрын
@@nickchapsas Exit point must be one line return of already prepared result, no deep nesting, and you have mostly readable and understandable method you can have, it just don't need comments, it's self explained.
@henrivanwesemael
@henrivanwesemael 3 жыл бұрын
@@nickchapsas thanks for the reply. As an old school programmer, I guess I am used to structured programming. Enjoying the youtube channel btw!
@nickchapsas
@nickchapsas 3 жыл бұрын
​@@henrivanwesemael Thank you so much! The beauty of programming is that there isn't a single way to do it right. We are all "right" and "wrong" to someone
@Omikoshi78
@Omikoshi78 3 жыл бұрын
I haven’t used “else” in 2 years now. But first I wanted to talk about something “else”.
@weipingtoh6756
@weipingtoh6756 3 жыл бұрын
You could change the RecipeBook class into a generic IRecipe interface and have BeerRecipe class and JuiceRecipe class implement the interface. So your bartender would just have a List. The IRecipe method would just have a boolean return that signals the success/failure of the method. The bartender would loop through its recipes and attempt to make drinks with the input keywords, and stop the loop if a success is returned. It would make adding new DrinkRecipes easier and expandable for wierd Recipe edge cases as each Drink is its own class.
@nickchapsas
@nickchapsas 3 жыл бұрын
I have already mentioned this in the pinned comment
@GeranBeast
@GeranBeast 3 жыл бұрын
when i approach if/else statements, i typically invert them to avoid nesting and return early for efficiency. but that also brings up the question of the design of the code, since there might be a better way to approach the case.
@craigd9058
@craigd9058 3 жыл бұрын
@@fillybuster8371 Thank you.
What are record types in C# and how they ACTUALLY work
15:36
Nick Chapsas
Рет қаралды 116 М.
Getting Started with Event Sourcing in .NET
37:07
Nick Chapsas
Рет қаралды 1,5 М.
Let's all try it too‼︎#magic#tenge
00:26
Nonomen ノノメン
Рет қаралды 53 МЛН
skibidi toilet 73 (part 2)
04:15
DaFuq!?Boom!
Рет қаралды 33 МЛН
Why I Don't Use Else When Programming
10:18
Web Dev Simplified
Рет қаралды 1,2 МЛН
Where are types allocated in .NET and why people get it so wrong
14:35
The Switch Keyword in C# is a LIE!
10:05
Nick Chapsas
Рет қаралды 43 М.
8 await async mistakes that you SHOULD avoid in .NET
21:13
Nick Chapsas
Рет қаралды 306 М.
Stop using the HttpClient the wrong way in .NET
10:14
Nick Chapsas
Рет қаралды 181 М.
20 Nuget packages that every .NET developer should be familiar with
15:33
Don't throw exceptions in C#. Do this instead
18:13
Nick Chapsas
Рет қаралды 247 М.
Swagger is Going Away in .NET 9!
10:48
Nick Chapsas
Рет қаралды 59 М.
What is Span in C# and why you should be using it
15:15
Nick Chapsas
Рет қаралды 245 М.
You are doing .NET logging wrong. Let's fix it
25:29
Nick Chapsas
Рет қаралды 168 М.