One day the "advice" will be so horrible that at the end of the video you will say "Stop Coding".
@jcx-2003 ай бұрын
That's an April Fools video for next year sorted
@borislavborislav55453 ай бұрын
Thats AI in 3 years
@yorkaturr3 ай бұрын
Clean code means readable code. If you need to come up with your own data structure for every parameter you use, it's a nightmare to debug. Maybe it's just me, but I like to use basic datatypes whenever possible. It's especially good in the backend if you can match your datatypes in code to datatypes in the database.
@defeqel65372 ай бұрын
if you don't have named parameters in your language of choice, then having concrete types (like enums) makes the code quite a bit more readable on the client side
@brianm18643 ай бұрын
I agree with you. If the boolean is obvious (apply discount vs do not apply), then go with the boolean. If it's not obvious, like "apply discount pro-rated to all items" vs "apply discount to highest price item" (stupid example I know but best I could come up with on short notice), then an "applyDiscountToAll" boolean can be confusing, since it's not obvious what false does. Then you use an enum.
@mattymattffs3 ай бұрын
Better example would be apply discount, apply upcharge, none. That kind of business logic can be complicated fast
@sirsneakybeaky3 ай бұрын
I have a thing for enum switch statements. They just are so clean and easy to read. Bonus as complexity grows your switch case can be a bitmask on any set of bits. 0 = 0b000, enum = no_discount, 1 = 0b001 = discount_highest, 2 = 0b010 = discount_all, 4 = 0b100 = discount_couponed. Then just evaluate each bit If((discount_flags && ( 1 >> i) !=0) //add bitmask and switch
@SixOThree3 ай бұрын
My biggest problems with booleans historically has been the calling methods don't give visibility into what parameter the bool is for. But now IDEs pretty much all describe the parameter for you. My previous practice before this was a thing was to use the parameter name in the method call (kind of like you do for optional parameters).
@hb-man2 ай бұрын
Why the Boolean? ProcessOrder(1000) vs. ProcessOrderWithDiscount(1000). Some code higher up decided if a discount is to be applied, why can this code part not call order processing accordingly?
@catgirl_works2 ай бұрын
@@hb-man Because the caller might not be the one making the decision. The discount flag could come from an object passed via an API or pulled from a database. This is why the example code is so bad. You wouldn't write order processing functions like this. It's not even remotely realistic to how you'd handle order discounts.
@danpaun22793 ай бұрын
avoiding boolean parameter and splitting in two functions often will mean to have the "if else" statement at an upper level :)
@CodeAbstract3 ай бұрын
thats exactly what Chapsas said
@gileee3 ай бұрын
No you wouldn't usually. What people do is they have some functionality that deserves it's own function. But then they start using that functionality in other higher level function but they require slight difference in behavior and instead of making two clear lower level functions (where one can still call the other for the common functionality) they decide to use a bool param and use it to enable the change in behavior. You're adding an if where there doesn't have to be one and it's actually slower.
@stevenbroshar79483 ай бұрын
Exactly. That makes flow control clearer to the reader.
@evancombs51593 ай бұрын
@@gileee yeah, when you have this situation you have two options. 1. Break it up into two functions with similar but slightly different code. 2. Take a page from functional programming, and pass in a function that represents the difference between the two processes.
@DiegoMenta3 ай бұрын
You could also use two types
@smathlax3 ай бұрын
I think in general people need to stop saying that there is any one correct way to program. Even if something is a good rule of thumb the vast majority of the time, that doesn't mean it does or should apply to every situation. Sometimes it's better to forget these "best practices" and just use your common sense.
@stevenbroshar79483 ай бұрын
Sortof agree. But don't forget the advice. Follow it usually but be willing to make bold choices when you think it's wise.
@evancombs51593 ай бұрын
While true, we have to understand there is a learning curve to programming, and this isn't something that most people will understand right out of college. These design rules are training wheels for inexperienced coders. At some point you can take them off, and you'll have an understanding of when to use them and when to break them. That understanding isn't something that comes naturally, it is something that is learned.
@smathlax3 ай бұрын
@@evancombs5159 I don't think you should use a rule if you don't know why it's there, and the only way you'll know why it's there is if you have the fundamental understanding. Once you have that you can look at the rules and decide if you want to use them for each specific case.
@smathlax3 ай бұрын
For example when I was new I learnt the "keep your methods small" rule by having absolutely massive methods to the point where they became unreadable and extremely difficult to change. Because I learnt this the hard way, I now have the nuance that sometimes it's okay to have large methods, for example when initialising flags/objects at the start of a program. I don't think it would be helpful to just be told "keep your methods small" without having any idea why you should do that.
@mattymattffs3 ай бұрын
The only correct program that exists is an empty file
@yogibarista28183 ай бұрын
Clean code appears to have fallen to the same fate as Martin's other evangelisms - e.g. Agile. There are virtues in patterns, but once they become a religious dogma that all code needs to be coerced into conforming, they lose much of their value. The argument of avoiding passing booleans because it means branching inside a function, as apposed to branching outside to call separate functions, appears on the surface to be a case of following a pattern for its own sake.
@pzodeosrs29 күн бұрын
Exactly. In that scenario you're having to branch at some point anyway. If you're having to do many complex conditionals/branching then you're probably trying to do too much in one place and should rethink your business case/scenario to separate concerns appropriately.
@xhavierrhovira28583 ай бұрын
Ok, now I want a video of Nick refuting those *blergh* CleanCode™ tipes from Uncle Bob
@BamYazi3 ай бұрын
Uncle Bob is the Life Coach who tells you how to live whilst having $50k debt, and regularly misses his car repayments .. his job is to make up problems with code
@ZILtoid19913 ай бұрын
If you need a good argument against clean code, just try developing games using those practices. Instant single-digit frames per second at best! Also it might be just me, but many "Clean Code" practices just make the code less readable for me. While I often give very descriptive names to classes (which I sometimes use in "unusual" ways), structs, functions, etc., I don't annotate code by putting them into their own functions.
@brixomatic3 ай бұрын
@@ZILtoid1991 Game coding, at least the high performance part, as with code for high frequency trading, comes with its own challenges and you need to make trade-offs in several areas regarding your code. In any other regard, a good design is way more important than outright speed, because what really counts for most applications is the time it takes to enhance your software with new functionality and how to deal with changing requirements and correctness. This is where "Uncle Bob" code comes from: Separation of concerns, dependency injection/inversion of control and as a consequence: injecting functions (or Enums that can easily be changed to contain functions) rather than Booleans, things like the DRY principle or not leaking abstractions/the Law Of Demeter, etc. they all serve to make your code more testable, more robust and easier to change. If you injected a function/object to handle the discount, rather than a boolean, you could rather easily add another discount, without changing the method itself and by not polluting it with foreign functionality. I've seen booleans like that ripple into the domain model, including respective SQL statements and when the requirement changed not only did you have to change wide parts of the code base, but also, and more importantly, deal with migrating a legacy data base, or even worse: other services that consume the same data, but sit with another team. You don't want this.
@hb-man2 ай бұрын
@@ZILtoid1991Uncle Bob isn't exactly focussing on Game development, is he? And if you know the inverse square root function from the Quake or Doom engine, that's obviously the opposite of clean code, but it is lightning fast - but it had to be invented only once, so isn't subject to changing business requirements. Speed optimization is the opposite of readable, changeable code.
@RiversJ2 ай бұрын
@hb-man Game Development is the one field where your Default option must be performance unless the programmer knows it's inconsequential. The kinds of idiocy and jank I've seen some 'cleancode' auditors suggest to game devs is just utterly ludicrous. Just the amount of virtual method calls over a 5ms timespan is Very relevant. Coming back to, it's Highly context dependent. I absolutely do not write business service functions like i do say a serializer or a game loop. Becoming proficient in your domain and in your tools should always be #1, then you can know which styles and processes work for what you need to do.
@alexbarac3 ай бұрын
There's a coding principle called KISS, with which the author of this advice does not seem to be fully familiar...
@DevelTime3 ай бұрын
Why not? KISS does not mean writing code in assembler and risking that you are absolutely prone to simple typos.
@fusedqyou3 ай бұрын
@@DevelTime What are you talking about? Point is that you don't need to over engineer code with enums when you should just use a bool
@tedchirvasiu3 ай бұрын
@@DevelTime I think writing code in assembler is definitely not simple and the other s.
@Ilix423 ай бұрын
Ah yes, Knights In Satans Service.
@alexbarac3 ай бұрын
@@Ilix42 You're wrong, it's actually Keepers of the Solid State.
@SteffenSkov3 ай бұрын
To uncle Bob's defense I think it is worth remembering where he comes from. Being "a senior" developer myself, I have also been through that period of time where object oriented programming was new enough that everybody were designing class hierarchies so deep that they were reaching hell. People were writing methods several hundreds of lines long. Nobody paid attention to number of arguments for functions/methods. My impression is that nowadays new developers are learning better OOP skills during their education, and therefor those somewhat extreme measures put forward by uncle Bob seems completely out of place. There are still some valuable points to what he is saying/writing, I think.
@easycheesy1872 ай бұрын
Enum is even more complicated because evaluating it defensively, requires checking the else (unknown) value state, to ensure a later developer hasn’t added states that your method isn’t aware of.
@Robert-yw5ms3 ай бұрын
Passing booleans is a bigger problem in languages that don't support named arguments. Js/ts is the one that immediately comes to mind. Edit: also it's definitely valid to start with the boolean, evolve to an enum if there are more than 2 options and finally inject the discount as a strategy if that gets too complicated. Refactoring is allowed!
@AmateurSpecialist3 ай бұрын
I think this might fall under "premature optimization." Granted, in the past, I've converted bools to enums when they magically got a third value, but it's so dang trivial that you should just let the bools be bools until you need them to be anything else.
@ryankueter94883 ай бұрын
The context of the code matters. In many instances, automatically using Enums could be over engineering. If it only requires a Boolean, then use that. In many instances, an Enum works well, especially for parameters. Or if something else would work better, then use that. But don't implement unused code features that could lead to confusion, like implementing a base class that contains no functionality, or an Enum where a Boolean value would suffice, or applying a more complex pattern, such as creating a class that returns a true or false value. That advice came from a mid-level developer aspiring to be the teacher instead of continuing to be the student.
@RealCheesyBread3 ай бұрын
In every project I work on, I end up replacing about 50% of boolean fields and parameters with an object, struct, or enum over time as the project matures. It's not because I am trying to follow some rule but because something eventually ends up requiring me to do so to avoid obliterating code readability and maintainability. Booleans just don't contain enough information to be useful in many situations. I'm not saying to avoid using them. I am just saying you should keep in mind that there's a 50% chance you're gonna end up needing to replace the boolean(s) with something better in the future. Don't write your code in such a way that you're gonna be fucked when you decide to replace the boolean later.
@Tldr2053 ай бұрын
But is this not the way it should be? Implement simple logic, and refactor to more complex when the business requirements need it?
@JohnSmith-fz1ih3 ай бұрын
@@Tldr205It depends. If you don’t think scope changes are likely to happen in this code, keep it simple and use the Boolean. If you think this code is likely to get extended in future changes, then take the time to make it an enum (or whatever makes sense) now so you don’t have to change every call to your function as part of refactoring. That to me is the point. Rather than “never pass a Boolean” or “passing booleans is fine”, it all comes down to understanding how big the project t is likely to get and building it from the beginning in a way that makes sense for that size project.
@Tldr2053 ай бұрын
Make sense, I'm also do tired of all the do this and not this statements, when it all comes down to understanding context and pros and cons
@damianjblack2 ай бұрын
All depends what the boolean is for. If it's a simple condition ("the file opened successfully" vs "the file did not open successfully") go with the boolean.
@Palladin0073 ай бұрын
With CleanCode, it's not the rules that count, but the fact that we deal with these rules, even if we don't follow them - hopefully after careful consideration.
@F1nalspace3 ай бұрын
We use a lot of booleans for method arguments in our production code and one boolean is not a problem, when it has a good name. As soon as we have more boolean, regardless of the order - we replace all booleans with an flags enum or better, separate the method into multiple ones, if possible (often this is not possible, due to duplicate code). But there is always a point, where you have to glue them together, so in the end - you don't gain that much by splitting methods. I personally like booleans in methods or functions and as soon as i have more than one directly following the other one, it is a code-smell and i replace it with an bit-flags enum instead.
@avisian80633 ай бұрын
Flags are great, but I also consider them code smell. As many times as I see them well utilised I see them as a band aid for an overly complex method that needs splitting
@DevMeloy3 ай бұрын
Each case is different, but in general passing a Boolean is a last result and to me is a sign that some rearchitecting is in order. For the example Nich shows, I'd rather pass in an optional param "existingDiscount" if possible. Also, I don't understand the hate for "clean code", sure some things Bob takes too far but don't throw the baby out with the bathwater because you don't like the guy.
@avisian80633 ай бұрын
@@DevMeloy the hate is for Clean Code(tm) not clean code. If you get me?
@DevMeloy3 ай бұрын
@@avisian8063 I've watched clean code(tm) and walked away with some good knowledge, do I subscribe to every commandment? No, but it seemed like the hate for clean code came from a dislike of Bob not necessarily his views on code. Not being argumentative, I honestly didn't look into what "Bob did" to piss everyone off... And honestly don't care.
@avisian80633 ай бұрын
@@DevMeloy no, I mean Clean Code(TM) as a saleable product. Like capital A agile. It's the grifters who treat it like its commandments that are annoying (and who have followers who treat it as gospel)
@404HumanNotFound3 ай бұрын
I think it would be better to have a method that calculates the discount and passes the discount into the ProcessOrder method, which always does the discount, even if there is no discount.
@phill68592 ай бұрын
It depends on the discount structure. You could have quantity break and value break discounts. You may only get the cheapest one. I worked on something that had a standard price and a discounted price if you paid a separate delivery charge for the week, it calculated which you were better off with and it charged you the least. Ultimately you may have to price everything to work out what the discount is. In that case you need a method that returns the discounted price and the full price You should have a data structure that allows you to pass in all the data, including any voucher codes etc.
@vchap013 ай бұрын
An enum can provide additional values like GoldDiscount and SilverDiscount. But for business logic that includes orders and pricing, it would make sense to use a strategy pattern instead of conditionals. For simple/POC projects, a boolean is perfectly fine.
@NKay082 ай бұрын
It would make sense to have the enum replace multiple boolean parameters (applySilverDiscount, applyGoldDiscount). Especially in your example, because these options are probably mutually exclusive. Designing the application, so it can potentially calculate different types of discounts in the future can be good, but on the other hand you can be wasting time by overly generalizing your methods when you have a clear use case.
@MrMatthewLayton3 ай бұрын
"Call one method in the true case, and the other method in the false case" just suggests that the if/else moves up a level to the function that calls those functions. As a mid-level engineer, my tech lead also told me that boolean arguments should be avoided, because when you read it at the call site (assuming that you either haven't been provided with a named argument, or using a language where named arguments aren't supported), then you don't know what that boolean means, without looking at the function itself. In contrast, an enum provides additional information that expresses the intent of the argument (as per the LinkedIn post)...at least, that was the rationale I was given. Neither approach bothers me.
@NKay082 ай бұрын
I don't even really understand the second argument. Yes, in plain text it is maybe more readable, but most editors nowadays should have a feature to show you which values correspond to which parameters. And perhaps you are even already passing properly named variables to the function, then it would be no issue as well.
@kikinobi3 ай бұрын
Sometimes you really really just need a simple boolean and you will never have to change it
@frankroos11673 ай бұрын
Too often I see people who want a single, simple solution for all problems. Not only do I see that desire, I also see that educators need books to do their thing. And it's easier to put single, simple things in books. That's what causes many cases like this: "Oh, I see a problem in that corner over there. Ah, I know the solution. And now that solution is the answer to everything." (And there I was thinking that it was 42.) I sign my emails with the quote "When all you've got is a Hammer, every problem looks like a Nail" as a reminder that a single solution doesn't exist. Instead, I have a toolbox (or rather, a toolcart) full of tools. For each problem, I need to find the right tool. Sometimes, it is to avoid a boolean. And at other times it is to use a boolean. Teachers would do well, not to teach just a single tool, but to teach multiple tools, and how to decide which tool to use. And I think Nick Chapsas is helping a lot with that. So, thank you for spelling it out in video's like this one.
@trader5483 ай бұрын
Project on day one: There are only two types of discount, discount or no discount (booleans are everywhere in the code base, all public API, etc) Project on day one-hundred: We have currently 673 discount schemes, depending on the customer type, geo location, day of week, phases of the moon... 😆
@Tldr2053 ай бұрын
True but hopefully a refactoring occured when the business logic changed to reflect it and a new and more suitable solution was found perhaps a discount calculator class or something like that.
@khatdubell3 ай бұрын
@@Tldr205 Or, if you (not you specifically, you in the general sense) are willing to admit that people who have gone through all this already might actually know a thing or two you don't, you could listen to what they have to say and design it without the bools to begin with, because its a small upfront cost to pass in a function as opposed to a bool is good design that can save your ass later. I'm a huge YAGNI guy, i try not to add anything to my code that isn't needed. But that has to be balanced against what experience tells you is the likely outcome of passing around bools. The truth of the matter is, the bool is more likely than not to _be_ the refactor. People LOVE to tack a bool on to the end of an existing argument list and default it's value. Absolute trash.
@brixomatic3 ай бұрын
@@Tldr205 and it's easier to refactor this, if you didn't start with a boolean in the first place. Don't use YAGNI as an excuse to start out with a bad habit. I've seen Singletons established with a YAGNI mindset that still haunt applications to this day and are next to impossible to weed out, because that would require too much time and development never stands still.
@RiversJ3 ай бұрын
@@khatdubell The issue in that scenario of yours is not bad practice in terms of which specific unmanaged type they use for parameters, but lack of effort to keep the code maintained and refactor often when changes occur. These are conflated to each other dangerously often. I would be very suspicious of anyone especially a very senior developer offering absolutes, far too often the presumptions are either outdated or do not apply nearly as universally as implied. A senior giving such advice Always does warrant examining the topic and how it does apply to you however
@khatdubell3 ай бұрын
@@RiversJ I think it depends on who you’re dealing with. I’ve seen people pass ints by const & “because passing by ref is faster”. I think that is an example of what you’re talking about. I would never take random advice from such a person. If, however, it was someone I know writes quality code, and it doesn’t contradict things I already know, I’d be inclined to accept their advice without questioning it.
@antonmartyniuk3 ай бұрын
Nick's mimics in this video are hilarious
@PbPomper3 ай бұрын
I agree that passing down flags to a method is a definite code smell. If you pass a flag, you probably need two different methods or encapsulate that flag (for example create an Order object and pass that down). The advice itself isn't even that bad, but the example they show is (like you said).
@phill68592 ай бұрын
The worst situation is where people add a boollean to aupport callers that pass the wrong parameters and the values need to be cooked five levels deep and the bool gets passed around.
@TheBunzinator2 ай бұрын
I completely agree with you. There are use cases for passing a bool, and there are use cases for calling one func for true and one for false. But either way, there is a conditional somewhere. Unless the situation lends itself to branchless code. Relegate dogma to prioritised options at best.
@marktrinder6263 ай бұрын
I’m always amazed how so much clean code is thrown away and rewritten. 😂
@CGX1063 ай бұрын
I'm already grateful that you're venturing into these dark corners of LinkedIn, so I don't have to.
@DotDager3 ай бұрын
Te quiero mucho, Nick Capas.
@keyser4563 ай бұрын
It's when people make broad sweeping statements and overgeneralizations that they get themselves into trouble. Heard a new kid that joined our team a few years back confidently declaring relational databases were "too slow". He wanted to build everything with no-sql and document databases because that's what he was taught. It didn't matter that most the senior devs around him could write (and in many cases have written) entire systems against a relational datastore that would run circles around anything he built. Because he heard something from someone, it must be true in his head.
@ghevisartor60053 ай бұрын
What about the feature of editors to show the label for parameters? To avoid naming the parameter specifically, if you dont have many of them that are optional and need to choose. Alzo Zoran Horvat have videos specifically on discounts and use type pattern matching with objects. I guess it depends on the complexity of the domain.
@pseudohyena3 ай бұрын
This. I'm so tired seeing all those boomer pieces of advice. Add prefixes here, shorten names likes that, don't use this, but use that, write comment for everyting... And their justification is "It's more readable, debugable etc". Ffs do you all write code in Notepad or something? Every modern IDE has features that help you understand what is what. Without you making code worse with their advice. And then the same people are going to write code like this: int32 GetCntPrdNum(int32 p_Num, FooBar p_Prd); To then add 10 lines of comments to explain that "Cnt - Count Parameter", "Prd - Product Parameter" etc. I've seen it, I hate it.
@winchester25813 ай бұрын
Sure it depends, but the example from the video cannot explain the meaning of the advice. However, commenting on Zoran's videos, there are valuable examples like replacing `IsPublished` property of `Book` class with more robust representation
@lukasvavrek29093 ай бұрын
In my team, I would much rather see code optimized for readability in GitHub (i.e. for PRs) than relying heavily on an IDE configuration. Other than that, I agree - start simple, and introduce the complexity gradually based on your needs.
@RoyBarina3 ай бұрын
I think you should split your comment into two distinct comments
@BobKatLife3 ай бұрын
Sucks when you have to tell the boss you can’t answer his question because you failed to consider the need for a “not yet selected” option.
@VanderScript3 ай бұрын
Alway enjoy your videos, I have my team of developers watch your channel too. Code Cop ones are my favorite.
@davidgncl3 ай бұрын
If there's a chance that the logic could change in future, i.e. the discount rate will change, then an enum is on the right track but it's still wrong. Strategy pattern would be better there.
@local93 ай бұрын
enum traps are real and can create an even more annoying mess. Edit: Seeing Uncle Bob hurt, I read through his books when I was being 'forced' to learn Java...
@Shynobyn3 ай бұрын
Basically big consulting firms put juniors and interns to work with little guidance and no coding standards and at this point Clean Code is basically this minimum set of standards which can help preventing this kind of crap. It isn't that great but it's something. For instance regarding this topic you find functions with a boolean paramater where the two branches are copy pasted anyways, and it's all the same except for a couple lines that change based on the parameter. So at first glance it looks like it would be better to separate this in two functions, until you look closer and realise it's just those 2 lines that change.
@marcusmajarra3 ай бұрын
My best coding advice: beware of coding advice that starts with "never" or "always". Instead, look to the "why" of the advice as it will instruct you on what some good motivations can be. From there, you can better assess how a specific situation will be best fit by a particular code style. Regarding passing Boolean parameters, I agree that they can sometimes lead to ambiguity if the code doesn't read clearly. That being said, it is sometimes a necessity, especially if the caller has no knowledge of when in the method call the conditional logic should be executed, which is likely to be the case when you're invoking the method of a different class. You can certainly opt to create multiple methods with different responsibilities rather than introducing a Boolean parameter, but this doesn't scale well if there need to be more options in the method call. Exposing a different method call for every single permutation will litter the API, which can be a real pain when designing a class library for public use. Generally, if a particular operation has a good number of different permutations in terms of how it's executed, I will tend to favor a parameter object to encapsulate all the various options in the call and delegate the responsibility of dispatching the work to the callee since they're more likely to be an information expert on how to execute the operation.
@SuperLabeled3 ай бұрын
LinkedIn has a setting enabled by default called "Use my data for training content creation AI models". I firmly believe developers are trolling linkedin to train bad AGI.
@colejohnson663 ай бұрын
The post's "reasons" already look AI generated. No sane programmer would write that.
@markcahalan56983 ай бұрын
"Clean Code" is for people that don't care about Time or Space And in the case of a dozen two line functions instead of two bigger ones, traceability
@JanusChan3 ай бұрын
I don't wanna split my order method in 'Orders with Discounts' and 'Order with Discounts' and then need to make a seperate payment calculation method to not have code duplication in both? This does not save me anything and does not make anything more or legible... I could just add one life with an if statement and a boolean..... I totally agree with you here.
@davidklempfner8263 ай бұрын
I can't believe the article didn't mention the main reason for using enums over bools as params, the fact that you can add an extra value to the enum and it's not a breaking change. You can't do that with a bool.
@RetroAndChill3 ай бұрын
The one place with booleans I would agree on is C++ or C# methods that have a possibility of failing, and they return a boolean and have the actual value you care about as a reference parameter that is set, then yeah don’t do that. C++ has an optional type in its standard library and while I’m not sure about C# it’s not too hard to implement one that has similar behavior.
@mDoThis3 ай бұрын
I wanna more clean-code-triggered-Nick :D You should make separate series going through this book!
@kevinison37403 ай бұрын
Clean code depends on the eye of the beholder sometimes... Not sure I completely agree with all this. Especially after about 40 plus years.... But it does give me something to think about, Thanks Nick!!
@DevelTime3 ай бұрын
This time I don't agree with you, example being 2:36 -- and this is why I use only wrapped ids -- NumberId, GenderId, WordId, etc. There are no "raw" ints used as ids in my code for a reason. Of course stating "don't use bool" is somewhat too strict, but I am all in for "limit their usage". The example provided is not good because of the reason you mentioned -- this is basically one fragile code (because of ambiguous type) exchanged with another fragile code (because the type is now open but it is handled like boolean). But the surface of the method (signature) is way stronger in the second case -- it is "readable" vs "bomb-proof", there is no chance in the second case to mistakenly pass for example "IsForeignerCheckbox.Value" instead of "DiscountEligible.Value". So in short, I fully support the idea of using enums (but not in the sense as presented in the lecture included), it is counter measure against human errors, being tired, not fully understand what goes where, typos (consider also that today we usually type 2-3 characters, and the rest is added by IDE).
@BinaryLizard3 ай бұрын
The YAGNI principle, or "You Ain’t Gonna Need It", is a software development practice that states that features should only be added when they are required. Use the damn Boolean!
@bnm03123 ай бұрын
A Boolean is simply a bit of data that the called code uses to perform its function. So documentation is mandatory if you're writing an API and expect those writing code to call it know what to pass in and why. The values expected for the method to receive need to clearly defined and what the values mean, and how those values can affect what happens in code. Enums don't work well for public API's, because they get converted to integers, which mean they need to be documented as well. What does 3 mean? The developers on both sides of the calling/called need to be clear with the intent of each of the parameters being passed. What the data types are is insignificant if the knowledge behind the parameters is understood.
@doichev-kostia3 ай бұрын
Can’t you just pass the discount instead of the bool? It can be an unsigned integer (uint8) that will indicate the percentage. Well, the parameter should also indicate that those are percentages we are talking about. If you don’t want any discount - pass 0
@demetriojunior1643 ай бұрын
Honestly in this particular case, would be even more valid to question why a [bool applyDiscount], if a [decimal discount] would make so much more sense here. Everytime i'm working on parameters like this i stick to it's original purpose. If i'm using the word "discount" somehow, it becomes so more auto intuitive to use a float point number instead of a boolean, because the word "discound' just tells my brain to think about a number with probability for 2 decimal cases. Also, anytime i have a method with a bool value where the "if true" routine is complex and/or long, i rather to shatter into more than one method.
@digitalmachines2 ай бұрын
I have watched this videos more than twice. And I think I simple agree with uncle bob. And I have tried to granulate this to very real life code scenario. I believe bool is simple do this or do that switch and every do this or do that can be put into a method (it can even be a private method). It is cleaner, more readable and easier to manage that passing a booling to a method
@ypetremann3 ай бұрын
For me, boolean have a problem that is not related to boolean blindness but more about memory allocation, flag enums can be easily implemented in modern languages and be really practical.
@BadMemoryAccess2 ай бұрын
"Ah yes, let me introduce a new type which basically just encapsulates a bool, just so that I don't have to pass bools around" lmao who even thinks like that
@tomtoups3 ай бұрын
I used to think that booleans only occupied one bit in memory; it doesn't. It takes an entire byte because the smallest amount of memory you can load into a register is a byte. BUT that's not all. Many times, booleans take up many bytes because of how memory has to be aligned, and padding is added to make it aligned along address boundaries. But that's still not all, because that extra space can go over the cpu cache pipeline, degrading performance and causes cache misses. Here's my take, if you have a lot of booleans, then use a [Flags] enum, which can allow you to pack 31 booleans in 4 bytes if the enum is a default of int32 (or 32 if you use an unsigned int), 8 booleans if it's a byte, and 64 bools if it's an unsigned long.
@illidan062 ай бұрын
for clarity on scalar values use the "newtype idiom". In C# you can do "public readonly record struct ApplyDiscount(boolean apply);" and then "ProcessOrder(new OrderId(1000), new ApplyDiscount(true))" is heavily used in haskell and Rust, unfortunatelly in C# you need the "new" which makes it a bit verbose. I think is a bit of overkill for bool if your variable/parameter have good names (shouldApplyDiscount), but for OrderId I think it gives tons of clarity (and avoid issues with passing the wrong "int"
@OtakuNoShitpost2 ай бұрын
This ks reminding me of my boss wanting us to make a string valued enum and the static method to read that value (which we would have to rewrite for every namespace) instead of just passing a bloody string in when calling methods which literally build strings for string valued protocols/frameworks (such as web urls, markdown, etc)
@maacpiash3 ай бұрын
return falsen't;
@user-tk2jy8xr8b3 ай бұрын
Consider a better advice: "instead of passing a boolean, just create a class with `T Choose(Func left, Func right)` method which runs the correct function depending on whether you have `true` or `false`!" :D
@holger_p3 ай бұрын
Looks a bit like over-engeneering and a slowdown in performance. You extend the world beyond a fixed number of choices known at compile-time. If that's your goal, do it.
@user-tk2jy8xr8b3 ай бұрын
@@holger_p I thought the ":D" part would play as a sarcasm marker. But generally that's the eliminator pattern which is useful for DUs (which `bool` also is; it lacks any additional structure though and has a built-in eliminator `?:`) in the absence of a proper patmat support
@tymurgubayev48403 ай бұрын
when I'm adding a boolean parameter to a method, I found it useful to stop for a moment and consider if it should be an enum, or maybe two methods instead. More often than not I decide to keep the boolean, but sometimes I do choose another option.
@coolmenthol3 ай бұрын
Gatekeeping in the software industry is one of the worst things. Both approaches have their pros and come from a good place. The simple boolean and the more complex example are just different ways of solving problems. I bet the author has years of coding under their belt, probably with some solid Java experience, and can abstract things so much that even their coffee order needs a design pattern.
@MrKlarthums3 ай бұрын
You could instead create a type to encapsulate all necessary state. This is really a non-issue for one boolean, but when you have several, you get a combinatoric explosion and good luck providing unique names to have a handler method for each code path. Or you could just...hover so your IDE will tell you what each parameter is or run an IDE feature/extension which shows a label for every parameter.
@PedrosBanioles3 ай бұрын
Looks fantastic, certainly lots of flexibility over xunit and opening opportunities to make complex testing easier
@sergeybenzenko66293 ай бұрын
The only justification I can think of is that if you have 2+ boolean parameters, then make them separate enums so you don't mix them up when calling a method.
@ianosgnatiuc3 ай бұрын
That's discount option, which means there might be several kinds of discount. That makes sense if you plan to have more than one kind.
@omargoodman29992 ай бұрын
I've just recently started picking up some basic coding. I'm taking some self-study lessons in JS, leading into AppScript. Before that, I used to primarily do "in-sheet" coding for spreadsheets. And, before that, the last coding experience I had was a class on C++ almost 25 years ago in HS. So I'm not exactly _devoid_ of coding knowledge, but I'm nowhere near fully-versed in modern coding standards. But even just looking at this, it seems like *both* approaches are a bit crazy. Using an Enum _just_ to re-invent the Boolean is flat-out dumb, no argument there. It's basically _half_ a Boolean; you only care when it's _true_ and do *nothing* if it isn't true, so all you're doing is turning the if/else into "if and only if; then". But there _is_ kind of a valid point to be made regarding the If/Else. If you have two entirely dissimilar branches, it probably *should* be two separate functions. And if they overlap, instead of passing a Boolean parameter, why not just pass the Discount value *directly?* Or even use a Truthy value? So, for example, the function could take a number either from 0-100 for a percent discount as a parameter, or 0-1000 for a permille discount, or even just from 1-0 as a cost multiplier. Then just process the payment with the cost adjusted by the provided discount. No need to even _check_ what it is; if the discount is 0% or the multiplier is 1x, that's just full-price. I'd only bother with creating fixed values through an Enum if there were specific discounts I wanted to _enumerate._ For instance, memberDiscount would give 10% discount, employeeDiscount will give 15%, and managerDiscount gives 20%; and a "None" case as a default. Seems like that would be a more sensible use, to create a list of valid discount values.
@LarryB153 ай бұрын
I get really sick of these rules. Firstly they should never be rules, at the most they should be guidelines. Sometimes it's better to use a single method with a couple of bools, other times it's better to separate the methods. But think, you could separate a function with a single bool into two functions. If you had two bools you would need 4 methods and 3 bools would mean 8 methods. Think of the naming hell, MyMethodWithClause1ButNotClause2 etc. The point is, do what feels right at the time. I would rather write a function, test it and check it in rather than wasting another 15 minutes debating whether my approach is right.
@JohnnyCoRuyzo3 ай бұрын
I like to use a option class, and set the properties with boolean parameters. Only if i have multiple booleans on that function, or multiple booleans that will need to be passed thru bigger functions. And the default value will be defined inside the option class.
@alexanderqwerty3 ай бұрын
Thank you man, for trying to stop clean code madness
@alanthomasgramont3 ай бұрын
I see this in architects all the time especially if they are not writing code daily. They will rip apart your PR without understanding the added work they are adding now and in the future. When you had a dozen sun methods to control its difficult to know their dependencies. Someone coming into your code a year later will need to spend time understanding the order and where in your code that three line method is effecting.
@TheXenoEnder2 ай бұрын
Good tooling can also make things like this easier to reason through. Visual Studio has an option for showing parameter names with inline constants and such, as an example. Also, have to say the clickbait title totally got me on this one 😅
@travisabrahamson88643 ай бұрын
I agree the bool has a finite list where the enum has an infinite list which potentially creates cognitive problems. The approach should be looked at why do we need a bool parameter and determine are we doing different things or are we doing the same thing with a twist. The other part is does this code need to know about that decision? Such as should I have cases where the discount is calculated differently - Flat, Percentage, based on when its paid such as a 10% discount if paid in 10 days Net on 30? This may indicate I've to simple a concept on Amount Due or on Discount itself.
@logiciananimal3 ай бұрын
Passing booleans is a bit a of a problem if you have a language without named parameters in method/function calls. Also, sometimes we sloppily use booleans to represent any binary state, which can be very confusing, particularly if the first situation I mentioned is also the case.
@Rolandtheking3 ай бұрын
I think both cases are valid, the boolean one is shorter, but allows any boolean to be passed in, even if it represents something else. Also a boolean cannot easily be extended, perhaps if more discount options arise. If the advice is to replace al places where we pass in a boolean, it is probably not worth it, and miht make the code needlessly longer.
@aodfr2 ай бұрын
The problem is context. This method/function is going to be called somewhere in the code base. How does that unknown method call this method. Can it be called from multiple methods without breaking the system or is this method a part of some sort of pipeline where it gets called only once?
@ThomasAngeland3 ай бұрын
void ProcessOrder(OrderId, IDiscount); readonly record struct OrderId(Guid Value); interface IDiscount { void Apply(OrderId) } class NoDiscount : IDiscount class PercentageDiscount : IDiscount // more discounts...
@BenMcCallums3 ай бұрын
The one thing I would say is that doesn't at all relate to "Boolean blindness" or any of these silly reasons lol is that the enum can be extended over time to support additional cases. So often in our API design sessions we'll change a configuration type bool column on an entity to an enum like FooMode or BarType. Bool can pigeon hole behaviour toggling very quickly.
@AndreaLanfranchi3 ай бұрын
I'm with you on finding this advice totally stupid. And there are reasons for that: - Applying method overloads (just to remove a boolean from a signature) simply moves the branching logic from the callee to the caller (so no benefits) - As long as the boolean really depicts and drives a single, not entagled, true/false condition those are perfectly fine. (example : ProcessOrder(bool applyDiscount, bool isFrequentBuyer) might be confusing and dangerous to maintain) - In the example provided is WAAAAYYY more dangerous to have the orderid passed as an int ... as int can be anything. How we could enforce at compile time the function is not called using, say, the day of the week as an order id ? - etc etc
@jamesreynolds31673 ай бұрын
The code base i work on has so many Booleans passed into functions like this. If there's 1 bool passed, it's more likely the next person will say fuck it, and pass another bool in. And this just gets bigger and bigger over time. This has always bothered me. Would would you suggest as a way to refactor this?
@warmachineuk2 ай бұрын
One problem with Boolean parameters is lots of them for lots of options. When (not if as it’s inevitable) you add another option, the parameter signature changes, breaking existing client code. As I use Java 8, which doesn’t have calling with named parameters, client code has a bunch of trues and falses, so is hard to read. Using a vararg enum means client code is a list of enum values and more enum values can be added for more options.
@tigerseye12022 ай бұрын
What I often see is coding advice like "Don't do X because if you use it excessively and without reason then your code becomes bad." Like, yeah, obviously you shouldn't use things excessively without reason, but that has nothing to do with any specific programming habit, it's just a general rule.
@alanschmitt98653 ай бұрын
That rocket emoji is a dead giveaway for Bing’s GPT implementation
@Kiccsalad20113 ай бұрын
Just couldn't agree more. Exactly what I think of these short sighted dogmas. And this is one of the most aggressive ones.
@ehanneken3 ай бұрын
The discount is a transformation of the price, so it should be passed in as a function. If there’s no discount, pass in the identity function. (All of this assumes you have to have a method with a very abstract purpose like “processing.”)
@imqqmi2 ай бұрын
Just use a multiplier in this case, if it's 1 no discount, any value below 1 it's a discount, no bool or if clause needed.
@zachemny3 ай бұрын
I think, the advice comes from supporting code where there are no named arguments. Invocations like "MethodName(true, false, false);" look really convoluted. But when you have something like MethodName(applyLogic1: true, useMode2: false, isOption3Enabled: false) it becomes much more clear what's going on here and enums become quite redundant. This also applies to string literals and other scalar types. Therefore, if you pass literals of any type to a method, it would be more preferable to use named parameters for them. Or instead, just use named constants.
@mattbristo69333 ай бұрын
It's ok until another developer comes along and doesn't follow that convention
@zachemny3 ай бұрын
@@mattbristo6933 If the function is supposed to be used throughout the codebase by multiple developers, then surely, we can design it to impose more explicit code style. But if the function is purposed for a more limited scope, like private method, then IMO we may have booleans and generally more relaxed definition.
@mattbristo69333 ай бұрын
@@zachemny bit in the example it is public otherwise I agree
@0xAC3 ай бұрын
I think Nick is absolutely correct here. Overall, named parameters are extremely powerful tools in the context of creating readable code. There are other techniques as well, but indeed, just replacing boolean with an enum is not solving anything. In context of Uncle Bob, I think it is interpretation problem. I don't think he meant that boolean should not be passed to a method ever but that often it is better idea not to. On github there is a massive number of examples of wrong methods design. The real problem is absolutely different. People hear an advise and bilindly apply it without understanding the context or purpose.
@billynomates77143 ай бұрын
You're still going to need an if statement if you have two methods - but you'll have more of them if you have to call that method multiple times if different places.
@holger_p3 ай бұрын
By architecture it adds some type-safety. As well as you could add "7 meter + 5 miles = 12 'nonsense'. You could do the same thing on the logical level. You do not "or" combine things, that aren't combinable, you add kind of a unit to the value.
@alpheusmadsen84852 ай бұрын
This may be an issue with the difficulty of finding a good example to illustrate the "problem" -- but after staring at the code for a bit, I cannot help but wonder: why isn't the discount a part of the order itself? All the things that are needed to process the order should already be a part of the order -- whether the order is a class, a join of database tables, or an actor, or even just a list of lists of lists (JSON, XML, or s-exprs) fetched from a hashed dictionary, the "apply-discount" should already be done!
@ulfjohansen21393 ай бұрын
There is also the problem that the enum is not guaranteed to have only two values. In fact it could be any number that can be represented by the underlying type
@rafageist3 ай бұрын
I think I'll write an article about this. For now I'll summarize that there are no dogmas in technology. And I've already talked about how "clean code" is subjective and relative. I could pass the amount to be discounted to that function, and thus remove the responsibility of the function to look up what that amount is. What I'm trying to say is that using bool as a parameter, or using an enum, or different methods, will be fine if it's justified and if it works for you in your context. In the example of LinkedIn it's not a good justification, nor is what Bob says a justification for not using booleans as parameters.
@tonydrake4623 ай бұрын
so i use bool to pass down where to all a 0 value to a lookup (definition All Things = 0) for my PairValue lookups. If I had a seperate function, I would either replicate a bunch of code, OR a complex chain where the True passed a 0 value to the false function - which feels very complex.... OR should I do that??? I might see how it looks..
@holger_p3 ай бұрын
Enum item names are used throughout the entire application. For a boolean paramenter you "invent" a new parameter name on each method you are passing it into. And here you could make mistakes. Especially on refactoring, there is no automated "rename all" for case you ever change the meaning of the original value. It's simply type safety, not to call a function(bool isenabled) with function(IsFrozen). With bool the compile would allow it, with two different enums, he wouldn't.
@davidmartensson2733 ай бұрын
For the given example its wrong, a single boolean with a good named for the argument is not a problem, as you say, if it more or leas split the internal processing into two completely separate paths, having two methods and lifting the if to the parent is probably better. But one case where sending booleans are bad is if you for some reason have multiple booleans to the same method. In that case I find that having named enums makes it easier to quickly glance at the call and know what the arguments really are, but of cause then you cannot use "none" as a boolean value but rather "AddDicount" and "NoDiscount" or similar. Or if there are multiple booleans, maybe add an options class to send in the parameters. That way you also can set only the parameters you need changing and leave the rest out to use default values. BUT as you mention, the int for orderId is in the context of clean code way way worse :D and especially if you need to send two int values for two different Id's, where swapping the order of them will not cause any compilation error. So replacing that with either an OrderId class, or as mentioned, adding am options or argument class would probably do more to improve the example. I do like most of the Clean Code rules BUT they need to be treated with some common sense, like som much else, they are guidelines to have in mind, not hard binding rules, and the end goal is always to make the code easy to read and maintain, and if a simple boolean is sufficient, why ad another class. Now, if your going to pass this boolean around, maybe through multiple levels of methods or similar, then adding an enum might still be useful since you are no longer dependent on the naming of arguments or variables that might change throughout the path if multiple developers have written different parts, but that is a whole different can of worms ;) For any similar case I prefer the way of Domain Primitives where not only are you avoiding raw data types, but you anything more varied than a boolean, you also can add limits. OrderId's most likely should not be able to be 0 or negative, same with price and quantity, AND you get the type check in the methods for free when using such domain specific classes :)
@TheWoodad3 ай бұрын
"Uncle Bob"'s advice is a bit draconian. I would hope that most developers would take the time to consider the trade-offs in applying such advice. Splitting methods into two just for the sake of clarity by way of name doesn't always solve a problem and often tends to increase technical debt internally, especially when the original method with the boolean parameter shares code between both branches, whereby the split now requires duplication of code. But let's just say that this shared code can easily be refactored into yet another method. Imagine the original method has several blocks of shared code refactored into separate methods. Dubious "Uncle Bob" might consider this as "clean code". I say it's possibly adding unnecessary complexity and also quite likely adding some degree of performance hit. All to gain some minimal form of clarity by eliminating the use of a boolean? I would issue caution if applying that advice at face-value and conduct a benefit analysis evaluating the value trade-offs. Now, as method arity increases with many of them being boolean, naturally that should raise some red-flags and warrant an immediate 'stop and investigate' even if calling said method using named parameters.
@NickTheCodeMechanic3 ай бұрын
I wish people would stop doing dumb things in C#. But if they did, I wouldn't be able to charge for fixing their screwups :)
@holger_p3 ай бұрын
It's not dumb. Sometimes it's old, things that were not possible 20 years ago. Or it's quick and dirty, they had to meet a deadline within 4 hours, and then you minimize typing. That's a topic of renovation in a chill moment.
@NickTheCodeMechanic3 ай бұрын
@@holger_p talking about the bools and small mistakes that shouldn't be, regardless of .net version.
@MonkeyMotoMan3 ай бұрын
Totally agree, excellent analysis
@DanielNit3 ай бұрын
I think that the authors intention MAYBE could have been extensibility. The case where you not just apply some discount, but you want to apply multiple different discounts. Then using several booleans would be a very bad road to follow and thus easily lead to annoying logical complexity and bugs. In that case, the given example was dumbed down too much to lose any focus on that aspect of extending the code into such complexity, as most examples do to be as concise as possible. Overall I guess most agree with you that for this trivial case of just ONE logical branching, it absolutely makes no sense to add a certain complexity. And these strong "clean code advocates" often go down a road of really ugly code in my book when they split a simple logic into tens of methods for the sake of extracting every tiny bit while still maintaining less than X lines of code per class.
@gweltazlemartret67603 ай бұрын
5:24 "bool can only have two values" -albeit a bit false (because, you know, _null_ ), I've read api concern about having an input for buying a ticket at discount, then with vip mode, then with another thing bloated inside. So to keep the method simple, just use an enum and have the internals of the method do the routing. BUUUT if you have the need to expand the enum, you'll have to reship the api exposing it, and the consumers will have to update aswell, exactly same as an api change -because it is. At the end of the day, it’s not different than having multiple dedicated bools, and/or dedicated methods. So, *the code smell* could actually lie in the *enum* side.
@fritzfahrmann47303 ай бұрын
what about options objects?
@karolstopinski83503 ай бұрын
This comes down to logical organization of a code. You make a function to combine input parameters and spit out a result. If the result depends not only by some values but also some flags you want to have all that processing done inside that function thus need to have some bools passed to it. That enum looks stupid for a bool. For a bigger group of possible states it makes sense but for just two states no.