3 More Laws of Writing Readable Code

Поділитися
Вставка
  • Опубліковано 21 лис 2024

КОМЕНТАРІ • 238

  • @kantancoding
    @kantancoding  Місяць тому +3

    Click here to Land Your Dream Job! Become a Microservice Expert With This Hands-On Golang Course 👉 kantancoding.io

  • @fsharpfan
    @fsharpfan Місяць тому +382

    A builder to create a simple object? No! Just use named arguments instead of positioned arguments. If your language does not support them, then maybe you need a builder. Creating a builder takes time!

    • @spicynoodle7419
      @spicynoodle7419 Місяць тому +51

      Creating procedures also takes time. Let's write everything in main

    • @TeverRus
      @TeverRus Місяць тому +50

      Named arguments are the best! Seriously, why write more code if you can write less code?

    • @trwn87
      @trwn87 Місяць тому +10

      Not all languages have named arguments though!

    • @TeverRus
      @TeverRus Місяць тому +26

      @@trwn87 Screw those languages that don't have named arguments! (jk)

    • @trwn87
      @trwn87 Місяць тому +7

      @@TeverRus To be honest, kind of true... Except there is a good alternative, of course!

  • @i_isak1451
    @i_isak1451 Місяць тому +62

    for anyone worried that using const variables will be worse for performance since you need to create variables for values now. First of all most compilers will substitute const variables for a set value anyways and is used exactly as if you just typed the number instead. Its a win win. Secondly, you should not do premature optimization anyways since it will make your code way harder to read, maintain, refactor and change later down. Only optimize when needed, prioritize more readable code before that.

    • @kantancoding
      @kantancoding  Місяць тому +11

      Good point. Also should mention that in most cases, people won’t be needing to min max performance like this in modern applications anyways. There are many situations where readability is more important.

    • @halvarf
      @halvarf Місяць тому +9

      Context is important for that general rule. It's clearly true for your standard business and web applications, but if you are on a microcontroller or in your main game loop, you have to think about what you're doing to the compiled code. Constants are no problem anywhere of course.

  • @Kebabrulle4869
    @Kebabrulle4869 Місяць тому +63

    For the last example, I would use keyword arguments (python) instead. Like createUser(name="Alice", age=30, ...). Less bloated and just as clear, and on top of that the order of the arguments doesn't matter.

    • @ktz1185
      @ktz1185 Місяць тому +3

      That's exactly what I was thinking!

    • @kantancoding
      @kantancoding  Місяць тому +11

      Yeah, would be great if all languages had that 💯

  • @fakharraza9235
    @fakharraza9235 3 дні тому

    1. Write self-documenting code
    2. Avoid magic numbers (assign variables to numbers for a dynamic approach)
    3. Avoid too many function parameters (if confusing)

  • @JProgrammingTech
    @JProgrammingTech Місяць тому +11

    Thanks man, sometimes my codebases get very chaotic, these really help

    • @kantancoding
      @kantancoding  Місяць тому

      Yeah man, me too! Thanks for watching 😊

  • @FlailingWildly
    @FlailingWildly Місяць тому +2

    Excellent advice.
    I disagree with the people who say that “self documenting code is a fallacy“. Code (small bits of functionality) can definitely be made self documenting - meaning that you should be able to understand what the function is doing by writing the code in ways that are clearer and more descriptive. However, this is not the same thing as saying “comments are bad.“ It’s not that the comments are bad, but rather that since comments are nonfunctional, it can be easy for them to fall out of step with the actual code. Comments are helpful, but they also have a built-in maintenance cost. There is definitely a place for both. If the function is complex, and cannot be easily subdivided into multiple smaller functions that are easier to understand, then yes, definitely provide well written comments for future developers.
    “Self documenting projects” are definitely a fallacy. README and CONTRIBUTING are critical documents for every repository.

    • @kantancoding
      @kantancoding  Місяць тому

      Couldn’t have said it better myself. I finally found the time to respond in that thread where the person said the thing about it being a “fallacy” but not sure if it will do any good

    • @darrennew8211
      @darrennew8211 22 дні тому

      I instituted a rule in my team that every directory's first check-in has to be a README file. Some of them were pretty stupid, but most of them came out pretty well, and I got kudos from a couple of co-workers for slowing them down and making them think for five seconds what they were doing before jumping into a new part of the project.

  • @ego-lay_atman-bay
    @ego-lay_atman-bay Місяць тому +10

    3:23 Except python allows named parameters, allowing you to pass in parameters in any order, just by using it's name. I'm just saying, if you're writing in python, you can use named parameters instead. Oh, and you can also force parameters to be named or positional.

    • @kantancoding
      @kantancoding  Місяць тому +1

      Yeah! That’s a good observation. Python is great 😊

  • @mra0ul
    @mra0ul 12 днів тому

    Love the tips. Thank you.
    On the last example, how would you call the create user function?

  • @derechtepilz
    @derechtepilz Місяць тому +19

    The last point is a non-issue if you use a proper IDE. For example, I mainly code in Java using IntelliJ and if I encounter a function requiring many parameters I can press Ctrl+P and I get a tooltip displaying which arguments to pass and where.

    • @NickCombs
      @NickCombs 29 днів тому +2

      Best practice not to assume the next person is using the same or similar tool.

    • @derechtepilz
      @derechtepilz 29 днів тому +2

      @@NickCombs In no sentence have I said that I do it or that you should just not care about it. I just said how I'd deal with it.

    • @NickCombs
      @NickCombs 29 днів тому +1

      If it's working, more power to you. I'm just chiming in in case someone else is thinking about leaning on the IDE in a more typical situation.

    • @darrennew8211
      @darrennew8211 29 днів тому +3

      @@NickCombs The likelihood you're writing a function like "createUser" and not using an IDE is vanishingly small.

    • @NickCombs
      @NickCombs 29 днів тому +1

      @@darrennew8211 No it's not. Text editors, CLIs, remote servers, and deployed apps exist.

  • @steampunkWizardStudios
    @steampunkWizardStudios Місяць тому +1

    Use "Keyword arguments" or "destructuring" for the last one.
    If you use something like TS make the parameter a type interface.

  • @Biriadan
    @Biriadan Місяць тому +16

    Not a fan of all that mutation with the builder. I’d just create the structure literal as an argument and pass that. No need for the user variable or any setter functions.

    • @kantancoding
      @kantancoding  Місяць тому +4

      Good point but it depends on the langauge. In many languages you'll run into the same issue with lots of constructor params.

    • @eturnerx
      @eturnerx Місяць тому +2

      In Typescript, I'd use a or a type that enforced mandatory properties and made anything with a sensible default optional.

    • @oli_dev
      @oli_dev 27 днів тому

      I was looking for this exact comment. This is what I do all the time, its super nice

  • @leocarmopereira
    @leocarmopereira 27 днів тому

    Just come across your channel. I love the visual effects!

  • @erichlf
    @erichlf Місяць тому +35

    Missing doc strings... I get that you don't want too many comments, but I shouldn't have to read the code to know what a function's effects, return types, or exceptions are.

    • @chillie_dude
      @chillie_dude Місяць тому +18

      Depends. On library always document functions.
      For applications don't because the cost is high to maintain such comments and they very often get out of date. Any modern IDEs can show the input/output automatically. And yes it's less detailed than comments but again for apps it's not worth and get out of date often.

    • @erichlf
      @erichlf Місяць тому +4

      @@chillie_dude I'm used to developing with plenty of people that don't have a clue why a function exists, so documentation makes it where I'm answering less questions.

    • @vlc-cosplayer
      @vlc-cosplayer Місяць тому +6

      "All my functions are less than 10 lines bro, just read them bro" 💀

    • @chillie_dude
      @chillie_dude Місяць тому +3

      @@erichlf well it's an interesting problem but I'm not convinced just commenting every function is the only solution. if a function is tricky then yeah great go ahead.
      Are the people not used to read code ? It's a skill to learn and an important one, you should ask them to try more.
      Is your code itself clear enough. Removing magical variables, better function name, explicit variable names, smaller (but not too small!) functions etc. Can help a lot too.
      So a mix of some comments, more reading and cleaner code might help. Just adding comments, which increase cost of maintainance and likelihood of being wrong, might not be the only solgion

    • @erichlf
      @erichlf Місяць тому +5

      @@chillie_dude i would say not updating comments is a problem. And should be addressed. Also docstrings shouldn't be so specific that they need to be updated, since they shouldn't explain the code. If you're changing a function in such a way that the doc string is changing you're probably doing something you shouldn't do.

  • @madbanana22
    @madbanana22 Місяць тому +9

    but how do you use the classBuilder without a classBuilderBuilder??

  • @coderwolfie2201
    @coderwolfie2201 Місяць тому +1

    Useful advice. the awkward silence at the end though.

  • @kopsha
    @kopsha 26 днів тому +1

    These coding rules are great, and they could easily work across most languages.
    Ah, that builder pattern... It’s like a never-ending checklist: set...().set...().set...() - and just when you think you’re done, it’s like, “Surprise! .build()!” As if we haven’t been constructing it piece by piece already. Really, .build(), was that necessary?

    • @darrennew8211
      @darrennew8211 22 дні тому

      It also makes refactoring harder because any new required thing you add, you have to find all the callers and make sure they're setting it. And the build() is only needed if you're going to return a different type than the builder, which is again unnecessary in OOP.

  • @MandeepSingh-td2ic
    @MandeepSingh-td2ic 15 днів тому

    Understanding coding can be daunting in the beginning but becomes little understandable later.

    • @kantancoding
      @kantancoding  14 днів тому

      That’s kind of missing the point imo. I’m not talking about a skill issue of not understanding code here. I’m talking about when experienced devs read code, what code is more annoying to read for example 😂
      You can write code such that the person reading it experiences buttery smooth nirvana 🧈

  • @ygstuff4898
    @ygstuff4898 4 дні тому

    With respect to parameters in a function, using an intelligent IDE (Eclipse, IntelliJ), if the function/subroutine/method is commented to describe the parameters, when writing the code to call the function, the IDE provides prompts for each argument: name/purpose, data type, and parameter position.
    (in Java, this is the power of JavaDoc-style comments)
    Very useful, to a point that programmer's expect to see that, and when they don't....who didn't document/comment correctly?!

  • @bigboland6160
    @bigboland6160 22 дні тому

    first rule is so important. Im almost done my cs degree and ive worked as a grader for many computer classes. so many students hear they need to write comments, and write the most useless redundant comments ever. like legit they will write i = 0; // initializing the variable i to 0

    • @kantancoding
      @kantancoding  20 днів тому

      Yeah, I get a lot of people advocating for comments in the comments sections of many of my videos. Many of them do indeed seem like students or juniors.
      I’m not opposed to ALL comments but as you mentioned, many people just write useless redundant comments.
      I’m just trying to explain that there’s a time and a place. And usually you can avoid them.

  • @kenye3057
    @kenye3057 Місяць тому +41

    When I read the legacy code , developers always give bad long name to the magic numbers, making the code more difficult to read.

    • @kantancoding
      @kantancoding  Місяць тому +5

      🫠 yeah naming can be difficult!

    • @halvarf
      @halvarf Місяць тому +3

      OTOH, developers who have trouble naming things tend to not be better at writing clear comments either.
      In the cases where the variables are only for documentation of otherwise magic numbersin the code, it can also help to put the definition and value assignment near to the point there the variable is used so you don't have to scroll around when reading.

    • @pepperdayjackpac4521
      @pepperdayjackpac4521 Місяць тому +1

      can u give an example of a bad long name of a magic number?

    • @Grif_on96
      @Grif_on96 Місяць тому

      @@pepperdayjackpac4521
      MONSTER_LANTERN_BURN_RAYCAST_LENGTH (constant) and concat_struct_of_structs_in_to_underline_separated_string (function) are some examples of my lengthy namings .
      And yes , this is from my code in commeriacl game :)

    • @jfftck
      @jfftck Місяць тому

      I would expect no better when writing comments, so what is your point? It is the whole point of code review, if the reviewer has to be told what the magic number is, or they figure it out by reading the code, it means that it should be pointed out to be renamed. This is the failure in your team, you must look out for the next developer and not rely on current knowledge.

  • @wsf-t7x
    @wsf-t7x Місяць тому

    Another approach is to just ask for a struct with the required fields. The caller can instantiate the struct before calling, or on call, and (AFAIK) unless you instantiate a struct with all fields in order, then the compiler will have you specify field names. So it ends up being like a builder object, but built into the language and with no bloat shenanigans.

    • @kantancoding
      @kantancoding  Місяць тому +1

      Great point! Yes, Go allows us to be explicit when creating struct literals so you are 100 percent correct.
      This tip is more geared towards non Go devs. For example in Java you’d need a class constructor with a bunch of params same as the createUser method.

    • @wsf-t7x
      @wsf-t7x Місяць тому

      @@kantancoding What the Java! lol
      jokes aside, i'm of the opinion that the java person should learn the go way, not the other way around. 🤣

    • @kantancoding
      @kantancoding  Місяць тому

      I’m of a similar opinion bro. The Java person should quit their job and learn Go.

  • @Naveh_O
    @Naveh_O Місяць тому +1

    I would argue that the second example needs some readable function for the logic of the tax ratio - that way the two bits of logic are separate. There's the calculation of the tax percentage, and there's the calculation of the tax value itself:
    func calculateTax(price float64) float64 {
    float64 taxRatio = calculateTaxRatio(price);
    return price * taxRatio;
    }
    func calculateTaxRatio(price float64) float64 {
    if price > priceThreshold
    return highValueItemTax;
    return lowValueItemTax;
    }

    • @timgerk3262
      @timgerk3262 Місяць тому +3

      Being literal, calculation of tax is what the greybeards call a Business Rule. The logic comes directly from real life, and should be unitary (not broken up.) Because we know that taxes go up periodically and vary from place to place, also take care that extrinsic business rules are somehow externalized, such as by dependency injection or service discovery.

  • @sealsharp
    @sealsharp Місяць тому +42

    I really dislike the common wisdom about "self-documenting code" as it is proven again and again by examples that are the simplest of simple code.
    I think it all starts somewhere different. And that's the distribution of logic into multiple methods when it does not need to be that way.
    When ever something gets so big that you might add in a comment, someone will say "just split it into descriptive methods", and yes, in the spirit of uncle bob you can split that 30 lines method into 10 simple methods. And instead of reading the code from lines 30 to line 60, the dev now has to scroll around trying to memorize 10 methods and what they do and build a mental model of how they are called. And after splitting one method into 10 methods, it's suddenly too much work to put a doc header of them, so we don't do it because we don't like tying shit after we just split that shit up for no reason.
    Three steps back. Lets not split up code if there's no reusing of the methods. Let's keep the code local, in context.
    Complex code exists, because complicated tasks exist.
    So you got complex code. Your coworker asks "what dos that do?"
    What do say? Do you go line by line saying things like "so this line checks if the first parameter is null" and so on? Of course not. Your coworker can read. Human language can is great to explain the concept of something. You will probably be able to formulate one sentence that can explain a complex block of code. Well, if you understand that code you should.
    And that's a good comment. Because three years later, someone will search for a bug and will find that block of code and ONE GOOD LINE may explain it better than anything else.
    "So what if the comments lie?"
    Comments are written with the assumption that code does what it is meant to do. Comments may "lie" when the code does not what it is meant to do, but in that case, the bug is the discrepancy between intended and actual behavior. You got two versions now, one telling you what it does, and one what it is supposed to do. You can now check if the assumptions where wrong from the beginning or if it's an implementation error and the fix is going to make the code do what the comment tells.
    That's my experience in working with complicated code.

    • @kantancoding
      @kantancoding  Місяць тому +2

      Yeah, you make some good points but like with everything there is a balance to be found. When I say to write self documenting code.. it doesn't implicitly mean that you should NEVER write comments.

    • @genechristiansomoza4931
      @genechristiansomoza4931 Місяць тому +1

      Comments should be used to tell why a certain code is there, especially for complicated logic, not what the code does.
      It does not hurt to have a private method that is not reused. It's pupose is to only split logic at this point.

    • @jfftck
      @jfftck Місяць тому

      If you can't write a simple name for what your code is doing, then it is more than likely hard to test, and that is the biggest code smell. I have been coding for over 15 years professionally, and have seen requirements change and comments still reflect the original intent, so in those cases, it is a lie on what is expected. I think it is more important to comment external APIs so you don't need to go back to the service provider's website, or you would be able to refer to older implementations when a provider breaks the contract that was given when you started using the service and would have legal grounds to ask for compensation for any losses due to service failures.

    • @jfftck
      @jfftck Місяць тому

      @@gearboxworks If you think comments are good, that is fine, but to say that comments are going to lead to better understanding of the code is being hopeful that the person who wrote it is able to express themselves in a completely understandable manner. My experience is that those same people write bad comments. Have you worked for a foreign company? You will quickly abandon comments and read the code to understand what is happening.
      It would be great if everyone could write comments that are perfect for every function, but I have experienced the exact opposite and have learned to distrust them.

    • @mrwensveen
      @mrwensveen Місяць тому

      Splitting up long and complex methods works best when you can create simple and functions that make sense on their own. Preferably these functions are pure/static, i.e. they don't change anything of importance for the calling method. Now, you don't have to scroll around anymore because the main method remains in control of the method's flow and of the object's state (if any).

  • @tobeqz7065
    @tobeqz7065 29 днів тому

    Clicked on the video just because i knew the comments would be spicy lol

    • @kantancoding
      @kantancoding  28 днів тому

      😂you’ve come to the right place

  • @NickBrown79
    @NickBrown79 Місяць тому

    These are GREAT!!! keep em coming!!

    • @kantancoding
      @kantancoding  Місяць тому

      Thanks for the feedback! Will do!

  • @kevintanudjaja7597
    @kevintanudjaja7597 Місяць тому +19

    so function createUser will create a user with a user that is already created?

    • @kantancoding
      @kantancoding  Місяць тому +7

      Hmm, no. By create user I mean actually persist the user. You’ll have to use your imagination for the logic in the function since I didn’t want to convolute the example with implementation details.
      An easy way to imagine it is that the user object in our code is different from what’s in the db. So maybe in the logic some ORM is used

    • @kevintanudjaja7597
      @kevintanudjaja7597 Місяць тому +2

      Ah I get it now. So this createUser func is an interface of SQL insert to a database. I thought it's a constructor for user struct in memory, so that's looks like inception to me.
      The builder itself is the one that will replace user "constructor" (Need to create it manually in go, because go don't have classes) of having too much parameter. Thanks for sharing

    • @kantancoding
      @kantancoding  Місяць тому +1

      @@kevintanudjaja7597 yes you've got it! And thanks for always supporting :)

    • @vlc-cosplayer
      @vlc-cosplayer Місяць тому

      Django ORM has both "create" and "save", and they almost do the same thing 💀
      It may be better to name it insert() (maybe with a bool "update" parameter that turns it into an upsert), so the intent is clearer.

  • @tkenben
    @tkenben 24 дні тому

    I suppose if we were to be picky, we would need to say that function is called something even more descriptive - especially considering your updating example with diameter - like "circleAreaByRadius", literally locking in the description of the function and thoroughly documenting it. I guess my point with saying that is, there will always be a line drawn in how self-documenting the code actually needs to be.

  • @danielmiller8223
    @danielmiller8223 21 день тому

    Issue with your Magic Numbers example. Although I agree with avoiding using magic numbers and even placing the data together in a structure, the problem with your approach is that it created a side effect. My suggestion would be to send in this data to the function or to create the data structure inside the function.

    • @kantancoding
      @kantancoding  20 днів тому

      Hey thanks for the input! There is no side effect. They are constants.

  • @sad_man_no_talent
    @sad_man_no_talent Місяць тому

    3rd one recommendation use typescript interface

  • @NickCombs
    @NickCombs 29 днів тому +2

    Many times, a fn with lots of params is built in and not worth making a wrapper just to key the values with an object. In that case, I will give each passed in value a descriptive variable. Even comments are fine there.

    • @kantancoding
      @kantancoding  28 днів тому

      Good point. Sometimes it can’t be helped.

  • @yuralis123
    @yuralis123 21 день тому

    Something I don't see addressed and I am really curious about is the UserBuilder allowing developers to write bugs. What if the email should not be null. I don't think there is a way to enforce the SetEmail method being called, which could cause weird bugs down the line. A constructor lets you explicitly set if something can be null, and if it shouldn't be null you'll get an error if you don't give a value.
    And for those saying python and javascript doesn't throw an error so it's not always true. There are ways to allow python and javascript to be typed, which will help you find bugs like this, so please use those

    • @kantancoding
      @kantancoding  20 днів тому

      Hey thanks for the input. As to your concerns, you can simply add validation for required fields in the build() method. Same thing will have to be done with a constructor. There’s no avoiding validation in that case.

  • @TheScottShepard
    @TheScottShepard 11 днів тому

    Spot on!

  • @jfftck
    @jfftck Місяць тому +1

    The last example could be solved with having multiple objects that represent the type of each and passing those in, no need for a builder. The added value of this, when a new requirement to add more values, you can add to an existing object or create a new one, depending on how that value is related to existing ones. For example, take the address value, what happens when you get a new requirement that states that the house number should be separate from the through way name? If you have an object represent the value, then you can just split them and add a method to return the full address.

    • @Betadesk
      @Betadesk Місяць тому +3

      So create 5 classes just to wrap primitive values instead of 1 builder class? That seems like a lot of overhead

    • @jfftck
      @jfftck Місяць тому

      @@Betadesk I didn’t say to make classes, structs are smaller and many languages can add methods to them and, if you’re using a language that doesn’t, you can use a function that you pass the struct into. It would add a type to a primitive and also add context.

    • @kantancoding
      @kantancoding  Місяць тому +1

      These are very good points and it is a good alternative but it depends on the context in my opinion.
      Like @Betadesk mentioned, creating 5 structs to wrap primitive types might be cumbersome. It really depends on if that type of design would benefit the overall architecture which can’t really be determined in the small example I provided.

    • @jfftck
      @jfftck Місяць тому

      @@gearboxworks If you don't understand the power of types, then you need to research how newer languages are using them. This is a way to avoid hidden bugs from getting into your system. I agree, in a perfect world, we would not need all of this, but I have seen multiple times where null pointers cause an error due to incorrect values are passed due to not utilizing types. One thing to keep in mind is not all languages have powerful typing systems, and anything that can help that is good.

    • @sunkittsui7957
      @sunkittsui7957 25 днів тому

      @@jfftck Using wrapper types is certainly very useful and robust, but wouldn't a builder object be a good balance between robustness and convenience in more trivial cases?

  • @JeffersonPires90
    @JeffersonPires90 Місяць тому

    I've finally found someone else using Agave font face :)

  • @donnewmancanada
    @donnewmancanada Місяць тому

    I used to agree with the last one, but have gone back to separate arguments. Developers tend to be lazy so they would re-use existing generic classes and just keep adding properties they needed instead of passing an object with only the parameters needed for the method call. It also prevents overloading resulting in a method full of if statements. Lastly, in a well-architected n-tier application a layer should decouple its dependencies which results in the need for mapping objects between layers.

    • @kantancoding
      @kantancoding  Місяць тому

      Hmm, some good points here but in an n-tier architecture it’s imo much easier to map objects between layers as opposed to trying to aggregate params between layers. You can also have common classes between layers depending on the overall design. Either way there’s going to be some decisions that need to be made based on the business requirements.
      I’d also argue that this type of architecture shouldn’t be referred to as inherently “well-architectured.” I’ve seen architectures like hex arch/ports and adapters as well as onion bloat simple applications with infrastructure that added no benefit. Just made the project more difficult to maintain and made it harder for devs to onboard.
      Anyways, I love your comment. Thank you

  • @champx5
    @champx5 Місяць тому

    could you make a tutorial on how to make a builder? you've got me curious on how to make those

    • @kantancoding
      @kantancoding  Місяць тому

      I already have one somewhere :) I think you can just search in my videos for builder design pattern

    • @champx5
      @champx5 Місяць тому

      @@kantancoding Alright! I shall have a look.

    • @champx5
      @champx5 Місяць тому

      @@kantancoding the funny thing is... I actually searched up builder patterns after watching this video. The first that got recommended was yours. Without realizing it I watched and when I checked your videos right now I saw the same video 😂

  • @SmoMo_
    @SmoMo_ Місяць тому +1

    Nice video, and I know this isn’t at all relevant to the coding points you were making..,,
    ,,,but that’s not how tax thresholds normally work.
    You would you the lower tax until the threshold is met and then the higher tax rate on what is left.
    Otherwise you could increase the price of an item by 1 cent and end up paying massively more in tax suddenly .

  • @vrmeup
    @vrmeup Місяць тому

    Great advice, thanks 😃

  • @Rand0081
    @Rand0081 29 днів тому

    The first rule is already thousands of light years away from the grasp of most developers. We are doomed.

  • @ФедорУсов-м9ш
    @ФедорУсов-м9ш Місяць тому

    3rd rule -> You are clearly breaking 1 entity (method call) between two lines. Never seen code style like this before:
    a().
    b().
    c()

    • @DaKeypunchAr
      @DaKeypunchAr Місяць тому

      You'll return the object at Every call lol

    • @kantancoding
      @kantancoding  Місяць тому +1

      Not really sure what the question is here 😂

    • @kevintanudjaja7597
      @kevintanudjaja7597 Місяць тому +1

      It's called fluent interface, or method chaining

    • @DaKeypunchAr
      @DaKeypunchAr Місяць тому

      @@kantancoding he's like how are you calling a method to void but you're surely not

  • @ericmintz8305
    @ericmintz8305 Місяць тому

    Floating point cannot represent money accurately because you cannot represent 1/10 as a finite sum of powers of 2. Use an accurate representations like an integer containing the smallest unit (e.g. cents, pence) or a fixed point decimal type. Uncontrolled round-off errors are almighty difficult to diagnose and even harder to fix.

    • @kantancoding
      @kantancoding  Місяць тому

      Yeah you’re right but It is not a real application. Don’t have time to explain that 10000 cents is 100 dollars and doing so would convolute the actual point I’m trying to explain.

  • @Maiuna-yc2uk
    @Maiuna-yc2uk 26 днів тому

    There is no need for builder in the last case. Use struct literals, it's better, or if your language support named arguments, just use that. A better approach than these two is to use different types (might be overkill though).

  • @kucingoyen1
    @kucingoyen1 Місяць тому

    Creating a new object for User is good, but I calling that using Builder is just ugly. You can miss some variables to be updated when we alter the object even if we have default value (in most cases).

    • @kantancoding
      @kantancoding  Місяць тому

      I see where you’re coming from but depends on the builder. You can add some validation for required fields.

  • @LBCreateSpace
    @LBCreateSpace Місяць тому

    Great advice Ty!

  • @apmcd47
    @apmcd47 Місяць тому

    Well, you should be using a docstring of some sort to document your code (javadoc, python docstrings, doxygen). Code reviews should pick up unaltered docstrings. Personally I don't want to read a function to find out what it does, that is what the docstring is for. I want to read it to find out how it does what it does.
    Too many parameters? As other have said, if your language has named arguments, use those. If not, and it has dicts/hashes, use them instead, although I suppose that is a sort of a builder. But even when using named arguments, a style-guide enforcer could complain of too many arguments.

  • @ErikBongers
    @ErikBongers Місяць тому

    A builder likely comes at a runtime cost. Use with care.

  • @mumcarpet109
    @mumcarpet109 Місяць тому +1

    Amazing 🎉

  • @saiuan4562
    @saiuan4562 Місяць тому +1

    Wait what? A method that builds a user, but its signature requires a user? The heck?

    • @kantancoding
      @kantancoding  Місяць тому

      The method doesn’t build a user. It creates a user in the database.

  • @Vlad1998996
    @Vlad1998996 Місяць тому

    these are very good videos :)

    • @kantancoding
      @kantancoding  Місяць тому

      Glad you like them! Thanks for watching!

  • @TizzyT455
    @TizzyT455 Місяць тому

    That last example didn't make any sense to me. If the original createUser function was used to create a user, and you instead put a builder in its place, whats the point of passing in an already created user into a createUser function?

    • @kantancoding
      @kantancoding  Місяць тому

      Yeah, lots of people confused about this. The createUser function creates the user in the database

  • @asagiai4965
    @asagiai4965 Місяць тому

    1st of all in the first question yes. Remember guys these are two different developers. So the validity of the code still true as long as the next developer is giving the val8d code.

  • @MiReiGi1984
    @MiReiGi1984 20 днів тому

    Rather than a builder or even a struct to hold a set of values, instead create types for each domain concept to get rid of primitive-type-obsession.

    • @kantancoding
      @kantancoding  18 днів тому

      I see your point but it doesn’t really solve the problem. For example if you have an Email type, createUser could take in fields primaryEmail and recoveryEmail both of type Email. They could still accidentally be swapped. With the builder you need to be explicit. setPrimaryEmail/setRecoveryEmail

    • @MiReiGi1984
      @MiReiGi1984 17 днів тому

      @@kantancoding For such cases, yes, completely agree. Though even then I will still recommend domain types over primitives to be used with the builder. That way a PrimaryEmail or RecoveryEmail field will still hold a valid Email value, and not e.g. a street address.

  • @Linuxdirk
    @Linuxdirk Місяць тому

    Thje formula used in the first example actually is pi * r * r and not pi * r^2. While the result is the same, those are two different formulas.

  • @skelaw
    @skelaw Місяць тому

    Last point is useles eg for js/ts. Just pass an object.

    • @kantancoding
      @kantancoding  Місяць тому

      You still have to create the instance of the object using the class constructor with the same amount of params. So you’d just move the problem to the constructor.
      Unless I’m mistaken (it’s been a while) JS/TS doesn’t support named params.

  • @gariannobinger9933
    @gariannobinger9933 Місяць тому +16

    "self documenting code" is a fallacy. Comments are not bad, they are necessary. Are they redundant with the code? They can be, but that's a good thing. Why? Because they provide a layer of confirmation, whereas code all by itself may be correct or may be wrong. Without the comments, there's no way to compare what a function was _intending_ to do (the comments), verses what it _actually_ does (the code). The problem in this video's example isn't that there were comments, its that the later developer was lazy and didn't update the comments, which is a bad developer.

    • @kantancoding
      @kantancoding  Місяць тому +7

      Tests should provide your layer of confirmation. Not comments. Otherwise there’s so way of knowing which is wrong, the comment or the code.
      Also, I’m not arguing that all comments are bad/wrong. I’m arguing that self documenting code can eliminate the need for most comments which means that when you do actually need to write comments, they are actually useful as opposed to just being redundant noise.
      Also, I don’t think that the dev that didn’t update the comment is necessarily bad. Many factors go into why a dev might not update comments. I’ve seen comments written so poorly that I couldn’t even understand what they were trying to explain therefore updating them was impossible.

    • @gariannobinger9933
      @gariannobinger9933 Місяць тому +7

      @@kantancoding What I was saying is that comments provide "a" layer of guidance and confirmation, not "the" confirmation. Yes certainly, there should be test cases. But in practical terms, the struggles around not knowing which is wrong, the code or the comments/tests is still valid in both paradigms, whether you're taking about comments or tests cases.
      Either way, when the bug report comes in, someone has to find the bug. When reading that code and wondering "hmm is this < supposed to be a

    • @kantancoding
      @kantancoding  Місяць тому +1

      The struggle around not knowing which is wrong 「the comments or the code」 or 「the tests or the code」 is certainly not equally valid in both paradigms.
      The most obvious reason being that comments are far easier to overlook than tests. In most cases, if tests are wrong, your ci/cd pipeline breaks.
      In the rare cases that a unit test is written in such a way that it’s wrong but still able to pass, it’s still part of a test suite and some integration test will likely break even if that unit test is somehow passing.
      So the odds that multiple tests that depend on some core business logic are all able to somehow pass even if the tests are wrong are far lower than the odds that some random fragile comment is neglected or simply incorrect.
      There are really no checks and balances in place for comments other than the reviewers eyes..
      and your whole argument is that good devs don’t miss these types of things but that, my friend, is the REAL “fallacy”

    • @FINALLYQQQQAVAILABLE
      @FINALLYQQQQAVAILABLE 29 днів тому

      Commenting and documenting are two separate things. Documenting modules, classes, methods, functions is absolutely a good way to provide information of what a module, a class, a method or a function is supposed to do. Most modern languages offer tools to write proper API documentation right in the code.
      Commenting lines is seldom helpful IMHO. I use to line comments only to explain unconventional bits of code that can't be cleaned up for some good reason. The reason goes into the comment.
      Call me a bad developer, but the only way I'm going to "update" a redundant line comment is to remove it altogether.

  • @matthewrossee
    @matthewrossee 19 днів тому

    While I'm a big fan of the builder pattern, I think that the example in your video is bad. The builder pattern shines when one's dealing with creating an object that has many optional parameters, but the User structure most likely requires majority of its properties to create a valid object. So, you're moving compile time checks to run time checks. You could say that you have to check if an email or a phone number is in valid format either way - ok, but then I still think it's not a responsibility of the createUser function. A dedicated Email value object that encapsulates the validation logic in a something like a factory function would be a better fit.

    • @kantancoding
      @kantancoding  19 днів тому

      I disagree. I think that the builder pattern shines when creating complex objects with many fields, even if there aren’t so many optional fields. Although, the benefits of using the pattern do increase if there are optional fields, that doesn’t negate the benefits in the cases where there aren’t optional fields.
      Actually, your argument about a dedicated Email object that encapsulates validation is in support of the use of a builder in this case. Not against it.
      That’s because in many cases, when creating an object with lots of fields like the user object, there is a series of steps like assembling parts and performing validations. A builder allows us to handle these steps at different stages prior to calling build().
      This is especially useful when we are creating immutable objects.

  • @duythanh90
    @duythanh90 21 день тому

    Nowaday, just write your code then use gpt to enhance that

    • @kantancoding
      @kantancoding  20 днів тому

      Better off asking a 6th grader…

  • @atabac
    @atabac Місяць тому

    as long as its english, code is readable to me😂 assembly is very readable

  • @el_niño_maka
    @el_niño_maka Місяць тому +1

    That s come clean code rules to keep your code elegant, good job*

  • @shanewolff94
    @shanewolff94 Місяць тому

    What is the font used in the video?

  • @ungrim97
    @ungrim97 14 днів тому

    I am not ensure constructing a User struct to....construct a user object is great coding practice.

  • @MrMassaraksh
    @MrMassaraksh 14 днів тому

    Read code, not comments. That’s all

  • @Kokurorokuko
    @Kokurorokuko Місяць тому

    Why would a function called createUser accept an instance of User?

    • @kantancoding
      @kantancoding  Місяць тому

      The instance of user is in the application memory. when calling createUser the user is persisted to disk e.g. a database

  • @cryptonative
    @cryptonative Місяць тому +4

    hate comments in general, only reasons I comment is about a strange edge case or to separate code blocks in sections given a larger function
    not sure I agree on the 3rd one, a proper lsp can help demostrate what each argument represents

    • @МаксимГорюнов-м7и
      @МаксимГорюнов-м7и Місяць тому

      What do you mean by lsp?

    • @romanpolishchuk4517
      @romanpolishchuk4517 Місяць тому

      ​@@МаксимГорюнов-м7иcode suggestions

    • @cryptonative
      @cryptonative Місяць тому +2

      @@МаксимГорюнов-м7и “language server protocol”, more specifically about something called “inlay hints” which shows the types and names of function arguments

    • @МаксимГорюнов-м7и
      @МаксимГорюнов-м7и Місяць тому

      @@cryptonative this is probably a level I haven't gotten to yet, thank you, I will look into it deeper

    • @suibora
      @suibora Місяць тому

      @@МаксимГорюнов-м7и LSP is already standard in most code editors. When you try to call a function in VS code or nvim, it will show you a preview, or 'hint' of the arguments and types that the function takes

  • @JProgrammingTech
    @JProgrammingTech Місяць тому +1

    How do you edit your videos? I wisg mine looked so clean

  • @akam9919
    @akam9919 Місяць тому +1

    Readable code, schmedable code. Make updated comments a requirement before code gets merged. Yes, comments can lie, but so can variable names, which objectively are just memory addresses with built-in comments. Their names are not for the computer, they are for you the developer. Make comment changes part of code review. You could create a function just like the one at the beginning, but if there is no circle that needs it's area calculated but some thing else that has a virtually identical formula, is the code really self-documenting? If we are okay with updating variable and function names, updating comments should be no different. Ontop of that, If I have a game that has 30 enemy types, and each attack pattern is created by a function, should I change each function name to "consecutiveNormalPunchesAttack" or "falconSmashAttack"? What if each has to conform to an interface? Should I make a private function that has the sole purpose of documenting what the attack is supposed to be like? Perhaps if there is some extra special logic, such as randomly chosen attacks that each have their own complex logic, but if I have a 20 simple enemies that basically have only simple but unique attack function, I think making extra and redundant functions is only going to make a file longer, bloated, and harder to follow. I'd rather have a clear comment that explains what the code is supposed to do, which is what the real purpose of comments is. It isn't about what the code does, it's why it's there.

    • @alexaneals8194
      @alexaneals8194 Місяць тому +2

      Commenting is essential to code maintenance and yes they should be updated; however, comments should never describe what the code already does. Comments should include why the code was written or to encapsulate the code so the developer does not need to look at the code to use it. A comment like "x + y = z" is useless and redundant; however, a comment stating that we need to add such a such function to comply with a business or regulatory requirement warns the dev to not change the code unless that business or regulatory requirement is changed or there is an error in complying with that requirement as the code is currently written.

    • @gariannobinger9933
      @gariannobinger9933 Місяць тому

      These posts are good advice.

    • @leerothman2715
      @leerothman2715 28 днів тому

      @@alexaneals8194That just sounds like putting the requirements as comments in the code to me? We have better tools to capture this data.

    • @alexaneals8194
      @alexaneals8194 28 днів тому

      @@leerothman2715 The problem is when the requirements are not kept with the code then bugs creep in with each release. Devs are not going to go looking through all of the requirements docs every time they change the code nor will they look at the commit statements in git or any other code repository. In reality the only time anyone looks at those statements is after everyone's hair has been set on fire with a sev 1 or 2 bug.

    • @leerothman2715
      @leerothman2715 27 днів тому

      @@alexaneals8194 Well that might be your reality, but it certainly isn’t mine. Writing & reading comments isn’t going to stop bugs, automated testing will do a much better job (especially if you practice TDD). Those tests will also let all developers know why the functionality is there. If comments are so important then why do IDE’s grey them out by default, they deliberately make them fade into the background for a reason. The application requirements are not just for developers they are for the whole team to discuss along with the stakeholders, how do you do that if is distributed all over many code files?

  • @lashlarue7924
    @lashlarue7924 Місяць тому

    I don't really agree that code needs to be self-documented. If you have to comment it in longhand English to reduce cognitive load then you should have just written it more clearly from the outset.

  • @lucemiserlohn
    @lucemiserlohn Місяць тому +4

    Method chaining, really? I thought Java demonstrated very well why NOT to use that crap.

  • @KlausBayer390
    @KlausBayer390 Місяць тому

    Which programming language is this? go?

  • @igboman2860
    @igboman2860 Місяць тому

    I mean go isnt really design for the user business. Why not create a struct without the abstraction

    • @kantancoding
      @kantancoding  Місяць тому

      It depends on the language. In Go you can create a struct literal and be explicit when setting the fields but this video isn’t Go specific.
      In Java for example, to create an instance of the user you’d need to use the class constructor which would have the same problem with the params as the create user function.

  • @AlfredLotsu
    @AlfredLotsu Місяць тому

    the devops playlist is gone

    • @kantancoding
      @kantancoding  Місяць тому

      Hey bro. There's good news and bad news about that playlist. If you want more information feel free to DM me on Discord.

  • @StephanHoyer
    @StephanHoyer 18 днів тому

    example of rule two is violating first rule, priceThreshold is not a good name. higherTaxPriceThreshold would be better.

    • @kantancoding
      @kantancoding  17 днів тому +1

      Imo the “higher tax” part is redundant. Especially when you look at the whole statement, it’s already clear that the threshold being exceeded results in higher tax.

    • @StephanHoyer
      @StephanHoyer 17 днів тому

      @kantancoding surely depends on what other constants you define in that file. If only this one I'm fine

  • @venusearth6682
    @venusearth6682 Місяць тому

    🙌🏽🙌🏽❣️

  • @coder_one
    @coder_one Місяць тому +2

    The slogan "Write self documenting code" stands in contrast to the fact that for some reason, most Go programmers (including the language's creators) write code in such a way that most variables are meaningless, unreadable 1-3 letter "words"; functions are also exaggeratedly called abbreviations as if Go programmers were deducted from their paycheck for every letter in the code.
    Therefore, it should be made clear - idiomatic Go is often a contradiction of "self documenting code."

    • @alexaneals8194
      @alexaneals8194 Місяць тому +2

      Self-documenting code is impossible. Code can only tell you what it is doing not why it was written. Most cases that I have run into where a dev has really screwed something up is not because they could not understand what the code was doing, but rather they didn't realize why the code written that way. A function returns null and the dev assumes that the function has a bug and changes the function to not return null and crashes a completely unrelated system. An address space is not initialized and a dev assumes that it's a bug and makes sure to initialize the space only to compromise the encryption algorithm (this occurred in a linux router software update that created an exploit).

  • @user-tk2jy8xr8b
    @user-tk2jy8xr8b Місяць тому +1

    The last problem is easily solved by typing. Instead of practicing primitive obsession and using raw strings, wrap them. This way it'll be impossible to accidentally swap the arguments and have the code still compiling after that.

    • @LittleLily_
      @LittleLily_ Місяць тому +1

      Having different types would definitely help in the case shown in the video and most other cases, but there are situations where a function does actually accept multiple values of the same semantic type, such as multiple names, or multiple ages (such as to calculate who is older), etc. In those situations you usually only have two values of the same type though so it's not too bad, and if your language supports named arguments then that would be the best solution in those specific cases.

  • @djteejay87
    @djteejay87 Місяць тому

    Creating a user struct to create a user 😂 Brilliant.
    Almost all modern languages support named parameters, this approach would be way clearer than the one explained.
    The other two pieces of advice are good ones though.

    • @kantancoding
      @kantancoding  Місяць тому +1

      I think you’re confusing persisting a user and creating a user object in the application as being the same thing. Hope it helps! 😊

    • @djteejay87
      @djteejay87 Місяць тому

      @@kantancoding I understood what you were doing there, for me it's not worth to create that User class/struct. If you are working with an ORM, maybe you can use a mapped entity of the Users table.

    • @djteejay87
      @djteejay87 Місяць тому +1

      @@gearboxworks I would not create an object with a builder anyway. I'd rather create a lightweight structure/class just for the sake of passing around those params. And I would only create it if the context you described applies.

    • @whydoyouneedmyname_
      @whydoyouneedmyname_ Місяць тому

      I agree he should have mentioned named parameters, but we're using Golang as an example which doesn't have them, almost every startup nowadays uses a Go backend so thats perfectly reasonable

    • @DaSquyd
      @DaSquyd 28 днів тому

      Whether the language supports named arguments or not is irrelevant. It will always be cleaner and easier to see what the values are by a params struct. Otherwise, you'd have to check in the function itself to figure out what the arguments are. It still doesn't solve the problem of accidentally switching arguments around either.
      Regardless, if you find your function is taking in enough arguments to push it to the next line... you might want to reevaluate what it is you’re even doing...

  • @МаксимГорюнов-м7и
    @МаксимГорюнов-м7и Місяць тому

    The last one can be avoided if different fields have different types. Overkill? NO! Useful type system

  • @madbanana22
    @madbanana22 Місяць тому

    2:25 THATS THE SAME THING AS USING COMMENTS???

  • @EvgenRymar
    @EvgenRymar 26 днів тому

    why code in this language a so ugly?