This was really great, I like the time you took to explain the difference between a bounded, and unbounded channel as it relates to async/sync behavior. Really useful
@69k_gold23 сағат бұрын
Bad programmers waste hours refactoring code duplication, good programmers copy and paste because: 1. Makes their job easier 2. There will NEVER be a case where two objects will use the same code forever, you can try to prove me wrong I'll wait
@YallDotBizКүн бұрын
If you don't duplicate code, you only have to be right once.
@IsaacHlungwaneКүн бұрын
5 Questions Need To Be Answered & Whether It Was Written By A Junior, Mid or Senior Won't Matter : 1. Is it EFFECTIVE - Does it solve the problem? 2. Is it EFFICIENT - Does it solve the problem well? 3. Is it TESTABLE - Can I write Unit tests for it?1 4. Is it MAINTAINABLE - Can I look at it after a year and understand what I'm looking at? 5. Is it SCALABLE - Can it grow or shrink without changing the logic to accommodate the traffic increase or decrease?
@MagnoLimaКүн бұрын
The code starting with func helloHandler() with all in one code should be the senior code. Like I would not waste time with fancy code, what for? Even the others codes have good readability... nah the one using generics could fit for the mid
@kevinsummerianКүн бұрын
Beeing a senior developper, I'd say the best one was the one written by the junior dev (the one on the left at the end of the video). Both of the mid and senior ones don't have enough advantages to them compared to the simplicity of the junior devs one. Sure there is re-usability that was thought by the senior dev one, but having only one endpoint in doesn't provide enough context to justify the early abstraction.
@adambickford8720Күн бұрын
A bad abstraction isn't the problem, it's the 900 gigs of other things that depend on that wrong abstraction that's the issue. A bad abstraction can also introduce all kinds of coupling that is near intractable in a real system
@jean-mariedormoy5790Күн бұрын
Cool video As others already pointed out, inheritance vs composition would be great 😊 Also design patterns are a must-know (adapter, facade, visitor...)
@kantancodingКүн бұрын
Agreed! Thanks for watching :)
@LakmalHckz2 күн бұрын
As a rule of thumb, always go for the composition over inheritance :D
@acidbunny9992 күн бұрын
The fact you only have 40k subs is a crime. Subscribe people
@kantancoding2 күн бұрын
Hey, thanks for the support 🙂 More subs will come!
@atlas_192 күн бұрын
4:33 Bro gave us time to discuss it the topic in pairs.💀
@kantancoding2 күн бұрын
Groups of 3 😉
@Carrymejane2 күн бұрын
11:19 😮 amazing
@nikkis81022 күн бұрын
I'm such a visual person and your drawings are helping me so much! Thanks so much!!
@kantancoding2 күн бұрын
Happy to help!
@joeyfinkel2 күн бұрын
What’s makes the “wrong” abstraction wrong? And why not just use concatenation for the print method to print the type of the document instead of using if statements?
@kantancoding2 күн бұрын
The print method is just an example. The point is, each document type needs to have its own implementation of a method.
@jonathanvioleta35782 күн бұрын
On 3:40 thats exactly how i solve things that are duplicated, for depending on the file type specific print, I would just create a different function to handle many if-else statement their or create a seperated based on a filetype most likely what's on the last example shown..
@kantancodingКүн бұрын
Yeah it’s kind of like untangling a knot 😂
@jonathanvioleta3578Күн бұрын
@@kantancoding Indeed 😂
@youyeye6662 күн бұрын
This is really a great video on programming thinking logic! Please continue to do it. Finally, thank you very much.👏👏
@kantancodingКүн бұрын
Thank you! I’m happy to hear that 🙂
@shipooprincess6702 күн бұрын
3 of them made by junior devs
@kantancoding2 күн бұрын
😂
@insentia84243 күн бұрын
I don't touch duplicated code until either: a) I start fiddling with the code and need to change both instances rather than just one of them b) My program is feature-complete and abstracting the duplicate code won't make it harder or, more importantly, slower to read c) It's a problem I have a lot of experience solving and know already that abstracting it is the best way to go about it Otherwise, I don't bother, because it would cause the following scenario: I'm shoving time into something other than the problem I'm actually dealing with just to solve something that *might* become a problem (time neutral if any of the above three would have become true). It also *might* be completely irrelevant (loses time). It *might* also be harmful to abstract it by causing me even more extra work down the line (loses time twice). Best-case scenario it's time neutral, any other scenario it's a loss of time, time I could have used to significantly improve my code where it actually mattered. Also, I'm sure if someone wanted to waste their time, they could stretch "every code duplication is bad" to such a degree that it would become comically ludicrous, humans are really good at shenanigans that.
@kantancodingКүн бұрын
🤣 i see your point. I feel like humans especially devs can stretch the shenanigans in either direction, either in favor of some duplication or against it entirely.
@Brunvelop3 күн бұрын
Why add a print method depending in the file type is the wrong abstraction? Can someone explain? Thank you!
@adambickford8720Күн бұрын
He explained it: open/close principle
@estranhokonsta3 күн бұрын
Fyyor such a basic exemple and being probably at the beginning of a more complex app, to me the less abstrattyctions the better. It sthould be the needs of the real app that ask for abstractions and not our tastes. Early abstractions are code polution. This means that i prefer the first and third exemples. Though if it is just a toy project then everything is valid.
@tvm45593 күн бұрын
How do you edit these videos? The quality is freaking amazing!
@kantancodingКүн бұрын
Thank you! It’s a lot. I wouldn’t be able to write it out here 😅
@dwried3 күн бұрын
This may be a bit over the top, but I like to write comments before every function describing what the function is expected to do and any assumptions being made. Just the act of writing out any assumptions will cause you to rethink the way a function is written for the better.
@kantancodingКүн бұрын
Yeah this is a good point. Many languages actually encourage this for exported functions and this type of commenting has helped me on many occasions as well. Problem is when those comments don’t get updated with the functions
@dwriedКүн бұрын
When I first started doing it, I thought it was crazy pointless, until I realized how much stuff I assumed to be true.
@DraconiusDragora3 күн бұрын
Law nr.4: Always comment on what something is doing. Not only will this allow you to remember why it was made in the first place, but it can help anyone else who needs to look over your code. This can also help them find a function, a code block, or array they might need to change.
@jfftck3 күн бұрын
The last example where the properties were injected into the different document implementations, it could also have been a Document object that takes a document type object, like PdfDocument, and those would have the unique actions that each type would need. But this would be a better approach if you have an application that has a document that needs to be exported to different formats, as you would need a concrete document object that is what is being exported to other formats. But I agree that both are valid options to the problem at hand and would need a common interface for the individual document types.
@kantancoding3 күн бұрын
Great observation! I like that idea
@colingale3 күн бұрын
When i was learning Pascal my teacher said if you have to repeat code more than once then put it in a procedure and name it well and when you get enough under one bracket then split off into a tpu(separate .c file and header for C coders but pascal just has .pas which include header and code)
@el_aslysoufyane3 күн бұрын
Thank you broo
@kantancoding3 күн бұрын
Always a pleasure brother!
@soloshottie4 күн бұрын
okay no. that first one could have been good advice, but you're reasoning for even trying to avoid deep nesting is so off. doing those inversions on so many if statements doesnt give you less if statements to process, because you still need to be aware of all those steps, all it does is make it less clear that they're all tied together. you've made the problem worse. in some contexts, yeah inverting your if statements is great. the example you're giving is 100% not that case. it was easier to read before you did that, because it was easy to tell that all those if statements were conditions before the core code could run better advice: add "and" to your if checks. you can cut down a line if you do this, having less if statements and less indents, but personally I still only check for two values at most if possible, otherwise you're *actually* needing to remember multiple checks at once. in the nested block you show as an example, you dont need to recall each piece, short term memory at best, you can focus on each line and say "after this is true, then we check this. if this is also true, then this-" and after each if those ifs you can push the previous line out of conscious thought
@asagiai49654 күн бұрын
As this may well be true. The truth is that sometimes it might not work. But you should still avoid duplicate if possible. Idk if it is a hot take, but I think you should only use generics for actions of (limited classes) Idk how to define limited because it's up to the person. But if it is getting longer and hard to maintain, you probably should stop using it.
@mrngwozdz4 күн бұрын
And thats why ppl have problems with microservices, are creating problematic commons and so one. Just because you just say "never ever duplicate"
@kirannhegde4 күн бұрын
Where can i find the code samples?
@shahedcassim73924 күн бұрын
relaxing video. Very nice
@whoizNiKHiL4 күн бұрын
You have to keep in mind that others are going to read the code you have written. So it don't not only have to be functional but also easy to read and optimized
@cryptonative4 күн бұрын
maybe I’m out of touch but the example at 3:43 is the best one to me. it gives you the best of everything, little duplication, readable code and easily extensible code.
@kantancoding4 күн бұрын
The one that I referred to as a “wrong abstraction” has many problems in my opinion. What if more file type specific functionality emerges? Then we’d need to have this if else structure in every class method related to that logic. We’d then need to continue to extend this if else structure in every file type specific method. Unit testing would also be super difficult.
@cryptonative4 күн бұрын
@@kantancoding If more functionality emerges and it's more specific I'd reconsider then but it's hard to know in advance. That's in essence the argument I think, that is, most times you don't know in advance. I understand that sometimes you get nested if/else and could get a little annoying but to me it looks fine. When you get it gets more complex than a few if/else statements I'd say that the cue to consider a better solution. I also don't see why unit testing it's harder. Maybe less organised as you will need multiple tests per class but still think that's fine.
@kantancoding4 күн бұрын
Good points!
@Vlad19989964 күн бұрын
keep on doing such videos, it helps understand how to organize code.
@kantancoding4 күн бұрын
Thanks, will do!
@SkielCast4 күн бұрын
I believe one interesting aspect that is often overlooked when doing this type of refactors is "time to understand". Code is read more than written. That means that if we optimize the "time to write new code" we may offer sacrifice "time to understand the codebase". I would rather have the code duplicated as with the two different documents classes because that is self-contained than having abstractions (even if they are proper) but that requires 2-3 clicks more to understand what it does. In this case the examples are trivial but in large codebases, having to do 10-12 clicks just to understand everything that a 20 line snippet does because of all the abstractions is a real pain. Of course, once you familiarized with the abstractions it becomes second nature, but it raises the entry bar somewhat inadvertedly most of the time. "We can solve any problem by introducing an extra level of indirection. …except for the problem of too many levels of indirection" I believe many codebases have many more levels of indirection than they need This is specially important if the dev team is new to an existing codebase, if the team has several jr devs, if one spends more time reviewing code from different codebases, etc.
@kantancoding4 күн бұрын
Some good points here! My honest take is that, with modern IDEs, indirection isn’t as big a problem as people make it out to be. You can hover over function names to get a window to what a function does. You can create key-mappings to quickly jump to function definitions and back (or better yet, learn vim). Also, I think the time saved on maintaining duplicate code more than makes up for the initial learning curve that comes with abstractions. But like you hinted at, this is in many cases up to the organization or team.
@jearsh4 күн бұрын
one thing about extracting/abstractions...is that you're giving something a name. as long as you have good naming, it will describe what the abstraction does/can do. so you won't have to dig into code to understand what it does. (see: coding to an interface, not an implementation)... if you have to go thru code to understand it, it's not well factored, poorly named, and it's probably doing too much. unfortunately i see the opposite. i see more codebases with little to no indirection. i just left a project with piles of code duplication. the familiarity didn't help understand things. all the copies had drifted in implementation, so even if you saw something similar before, you still had to walk thru the code line-by-line to understand how "this version" worked. there wasn't any consistency across the entire app.
@kantancoding4 күн бұрын
@jearsh Couldn’t have said it better myself
@SkielCast4 күн бұрын
Regardless of how good your IDE is, being 10 clicks away is never a nice DX, even if you can go back and forth at lightning speed Moreover, when reviewing PRs you don't have any of those features (neither Github nor AzureDevOps), which introduces friction and delay If we talk about 2/3 levels, this is not a problem, but DRY creates many levels, i.e. DTOs, repositories, data mapper, managers, services, controllers, etc... Sometimes, this is needed but more often than not it is introduced way earlier in the codebase than needed I would pose he problem the other way around at the extremes, what is worst, a codebase full of wrong abstrsctions or full of duplicated code, I would argue that the latter is a lesser evil and can be refactor easier One can control their own code but often we need to work with code written by someone else, having that person written duplicates code is easier to work with than the work abstraction One should try to use he proper abstraction always but it is important to mediate on how that guidance could be interpreted or misinterpreted by everyone else and what is more problematic if done wrong This is very subjective as I usually review code with this characteristics
@omegand.4 күн бұрын
That last example looks so bad lmao, just make an abstract class and inherit it for all types of document classes
@kantancoding4 күн бұрын
Inheritance isn’t always the better choice. In fact, there are many situations where composition is a better design choice than inheritance. But, it depends on the application. In this case, the choice between composition and inheritance was irrelevant to the explanation 😉
@alvydasjokubauskas25874 күн бұрын
@@kantancoding Next topic for video!
@omegand.4 күн бұрын
@@kantancoding I agree with the commenter above me 🤗you should make a video giving your take on the differences
@kantancoding4 күн бұрын
Thank you both for the good suggestion. I think I will!
@MichalKuzmicki4 күн бұрын
The last code with DocumentProperties - It looks more like typical using the definition of composition and when it is better than an inheritance.
@kantancoding4 күн бұрын
There’s not really enough context since the examples aren’t used to explain composition vs inheritance in this video.
@Zensi1234 күн бұрын
What is your process and software that you use to create this awesome video?
@kantancoding4 күн бұрын
Hey thank you! It would take a long comment to write that out but the main thing I use is DavinciResolve
@thefunnybuddy41384 күн бұрын
what font is that? I want it.
@kantancoding4 күн бұрын
In the description 😉
@ViraLok4 күн бұрын
I just start learning design pattern, it looks like proxy pattern.
@nisargkhodke1104 күн бұрын
In the example of the document types cant we use a list and run a for loop to check if the doc type is available and use only one class? Is this wrong approach or not possible?
@kantancoding4 күн бұрын
Hmm, you mean make instantiating the class O(n)? If I’m understanding you correctly it means that every time you instantiate the document class, you would need to loop through n document types.
@nisargkhodke1104 күн бұрын
@@kantancoding Oohk. So if we go by your example the time complexity will remain O(1) rit? Make sense if thats rit. Thanks!!
@user-lj4lo7cx7m4 күн бұрын
What about extending the class whenever its possible?
@kantancoding4 күн бұрын
The right abstraction is going to depend on the real world business requirements and the overall design etc. I just used composition as an example.
@user-lj4lo7cx7m4 күн бұрын
@@kantancoding Thank you
@asagiai49654 күн бұрын
I think you shouldn't extend if you don't need to. And if you need to extend. The extend must be unique or something.
@Mhmd_SHA4 күн бұрын
🎉
@maximusultra99285 күн бұрын
what language is the first code in?
@kantancoding4 күн бұрын
Go
@fallenarchangel87095 күн бұрын
gotta admit, did some of the nesting 'mistakes' you mentioned, noted it under great advice, for naming i find it the best to write the convention used in a comment at the start of the file. not sure how helpful it is to some people but since there are a few i wanted to make it easier for potential other programmers
@freddyperla79445 күн бұрын
Also, naming convention is very important.
@kantancoding4 күн бұрын
Yes! I agree
@freddyperla79444 күн бұрын
@@kantancoding I've spent days trying to come up with the right function name and variable names.
@_ramar5 күн бұрын
2:55 me when i buy alcohol and not only does it add the electronics and general tax, but also that im paying for everyone before me because total is a global variable
@kantancoding5 күн бұрын
💸
@el_aslysoufyane6 күн бұрын
BEST explanation brooooh
@kantancoding4 күн бұрын
Thanks bro. Glad it helped
@vasiliynkudryavtsev6 күн бұрын
I really like how Verilog has freedom of the switch-like case statement to the point of "reverse case statement". E.g.: case(1'b1) isMaintenacePeriod: log.Fatalf("feature unavailable"); !isAuthenticatedUser: log.Fatalf("invalid user"); !isAuthorizedUser: log.Fatalf("permission denied"); default: doWork(); endcase SystemVerilog even adds features like unique and priority.