The fact the explanation makes more sense during showing the post makes it clear that it was way too hard to explain something so obvious to someone that doesnt understand how to write c#. At the end I just feel like you try to make simple something that is already way too simple. You're a hero for trying to save people who believed that post ;(
Imagine someone reading this and then applying it to a game in Unity or MonoGame; every time something gets hit and loses HP, you have to replace the entire object rather than just updating the HP value.
In case you might have steered away from using Records for EF; or WPF; I can tell you that the argument attribute [property: Key], [field: Index], and/or [param: RandomParameterAtrribute()] in the record's constructor/signature will allow you to have the same attribute-based class design you may already be used to. You already know that you're using a dated and wildly unpopular framework that, much like WinForms, is NOT going to get any more love from Microsoft in future releases. I would implore you to look into Electron, or at the very least Photino; which are web-based wrappers for SPA/PWAs that any well written MVVM/XAML project could be transposed into.
@@asteinerd if you are talking about WPF then I can't agree with this statement. WPF is still one of the most used desktop frameworks, it is especially popular in enterprise. XAML is more pleasent experience than html + css (even with frameworks) and also offers much faster rendering.
@@asteinerd i am lucky to develop for an industry that almost entirely uses Windows for console apps so cross OS support isn’t a concern. We looked into Electron and found it much too heavy. We maintain legacy apps in WPF but you are right, new applications are generally written using SPA but using Blazor. I am not a fan boy of Microsoft but if they continue to provide support it is hard for other platforms to compete. As an aside, like most developers I had a steep learning curve with WPF but once I got the hang of it I found the framework to be quite elegant. I never got into hardcore usage of XAML but most things could be easily done by the code behind.
I always forget about Records in C#. I keep thinking they're useful every time I see them used, but I always forget about them when writing my own code.
I really agree with most things you said, especially in related to those posted texts. But as a note I would say, the point with having immutability (by default) is make you think better about what you mutate, and express that well in code. The idea is not at all that you suddenly start copying everything around, because fact that's still a way of changing things, albeit while copying. But the idea is rather that what you actually want to mutate, you should also make that actually mutable, and be explicit about that. What I like in Rust so much, that mutability is generally not done on the level of structs and other types, but for each individual variable. Just like you can also choose to have either a reference or a direct value. And tune the lifetime of it. In C# this is all baked into the types itself. Reference vs value type, readonly, ref struct (which has method scope bound lifetime). This is idiomatic to the language however. So therefore I keep following that approach, and it matches here with object oriented programming and properties.
Yeah it's context that matters. Such advice usually refers to when ppl make everything an auto property just by sheer momentum. But yeah, instead on focusing on fields vs properties, they then talk about immutability because it's the hip thing to talk about and everything has to be about immutability and purity
I agree that every class do not have to be immutable. BUT if you intend to make a class IEquatable or IComparable, yes it has to be immutable, or at least properties used for comparison. For example, if you put instances of an IEquatable class into a HashSet so that there's no duplicate, and if you mutate a key property of one of the instances, there could then be a duplicate in the Hashset and then it is an issue.
There is one case for the field approach. If you have large structs like Matrix or Quaternion you can pass it by reference `Method(in lssrgeStructToPass)` so to avoid creation of new struct on each method call. You cannot do that if this is a property.
I think people doing such radical statements are either up for controvercy to begin with or just forget that most of the time the answer in programing is "it depends"
For very high throughput demands, use properties with [MethodImplOptions.AggressiveInlining] attribute. Normaly, the JIT compiler will use it automaticaly for 4 instructions or less methods. You can enforce its use for properties, but it should not be needed unless you want to ensure high performance compilation (and you are not using reflection)
In the case of pure properties in release mode, the JIT compiler should usually optimize the properties and use the fields directly. This means properties and fields have the same performance, the getter/setter methods are never called.
I actually agree with his advice in general, but not for the reasons he listed lol What I like about properties is that you don't need to premeditativly add getters and setters. You can just start with a field and refactor into a property when you need some logic without breaking your public API. Starting with a { get; set; } property makes no sense, you're adding a layer of indirection for no reason.
Adding `{get;set;}` does not break the API, but it does break the ABI, requiring recompilation of code that uses your thing as a library. In C#, {get;set;} aren’t that bad, I would agree that getters and settesr are cargo cult in Java. (And also, how often do people really end up adding logic to a property in the future?)
@@Kwpolska Didn't think about that, thanks for mentioning it! I mostly know C# from a gamedev perspective where it's not a big deal to just recompile when updating dependencies, but I can imagine it's nice to be able to swap out a DLL in live environments without needing to recompile/restart the entire system.
The reason why I'd avoid auto properties specifically (if I could, curse EF with its strict usage of only properties and built in json serializer for the same by default) is because then it becomes a superfluous function call in both directions. I was once asked why I pull an array's length out any time before I run a loop and it is for this very reason, every time the comparison in your loop is made, you no longer only have a comparison, but you then also have a function call of which I am unsure of if it gets optimized out.
He was really triggered by this one 😅 (but for a reason). I didn't know that much about the topic and learned some things with the video, the difference between me and the OP is that I don't share tips about things I'm not sure about lol
9 месяцев назад
I literally have multiple structs in my library that has "public required type Thing { get; init; }" and even "public required type Thing { get; internal init; }", even better than the advice
I agree with most of this, but I still haven't heard any good argument for 'naked' auto-properties as a principle. Changing the approach would probably not be of much use because of conventions. I just hate having conventions that are there for no good reason. I have yet to hear a good one from anyone that isn't circular (i.e. you should use the convention, because the convention is expected). I try to avoid setters and would rather use explicit Set methods, but I got to the point where I rarely use properties, even though I declared them. So they effectively become readonly fields to the outside. Getters and setters (and especially init setters) are great for dumb/data classes, for anything else I don't find them all that useful.
The name "property" is very intentional. It communicates that it is something about the state of the instance. Methods are what the instance does. The syntax of using properties is similar to accessing fields, because that's what it is supposed to represent, accessing something with additional encapsulation and the ability to add behavior and sanitization. There's a third, which is indexers, which are technically just methods as well but are build to look like accessing an array-like indexed data structure. We could just as well write methods, but we could also write an indexer that has nothing to do with accessing any index if we feel like it. Probably not the best way to communicate what's actually done.
I would love C# to have a default of immutable variables/fields/properties and require a mutate keyword, but it could be a modifier for namespace or project configuration value. It is better to specify mutability than to apply read only using readonly or init keywords. I find that setting to read only can be missed, but trying to mutate something that is immutable would fail and make you mark it as mutable to use it.
Hey Nick! Great advice about with keyword. Never knew about it. Always I learned great explanation of immutability in this video as something which can’t be changed after it has bern constructed. Thank you so much for sharing!
Hello, Nick, I have a question that has been bothering me since the beginning. Sure, while there is an encapsulation principle, C#'s syntax to access properties and fields is absolutely the same. So my question is: why bother creating default { get; set; } accessors (and thus create unnecessary functions) when I can just create a public field AND THEN if I need it encapsulated (i.e. There is now some business logic like dont assign negative values) I can just add the { get => ... set => ...} and no existing code will be broken (unlike Java) Is it all really just because of the reflection?
Convention is a big reason as someone already mentioned but there are also other reasons. Just put that question into Google and you'll find a SO page that lists a lot of reasons to use auto properties rather than public fields.
For one, properties can communicate design intent in terms of mutability control, especially as it relates to collaborators. Fields are much more limited in this respect as they can only express the mutability concern only as far as the field's initialization goes. As such, I never consider auto-property accessors and mutators to be useless because the code is more expressive as to the design intent. And because the compiler elides the underlying method calls as part of optimization, I can retain code that is expressive regarding the design while still enjoying the benefits performance. So I think your question should be asked in reverse: given that auto-properties don't incur a performance cost over fields, why would you want to use fields to begin with?
Your existing code WILL be broken by doing that. Oh, you'll be able to compile everything again without touching the code. But if the entity with the fields and the code that calls it are in 2 different assemblies, you won't be able to replace the assembly with the entity definition with a new version that has properties without recompiling the assembly that holds the calling code.
@@selism this one actually resonates a lot with me, dont get me wrong, the other comments all bring important points to the table, but yours is actually revealing a contradiction in my own Thanks!
They seem to have misunderstood what immutability is for. The real benefit is in having a crystal clear API. That is, if you return something with properties with get/set all over the place, the implication is that if you change it that it changes… but this is rarely the case. Sure, that value on that instance might change in memory, but it’s done nothing to persisted state unless this has been implemented internally within the class (which is almost never the case in reality). Immutable properties makes it clear to the consumer that you can’t do this. It’s self-documenting. Nailed it with get; init; -> much clearer and doesn’t require a verbose constructor, AND it’s fully compatible with JSON serializers.
Making objects immutable IS what you want the vast majority of the time, and it is only relatively rare cases where having them be mutable makes more sense. Database records like this "User" are an example where immutable is better. While it is true that copying all the fields when you want to fake updating a User is slower, you have to keep in mind that the times when you'd legitimately want to do that are very rare, so the fact it is a bit slower isn't a problem in practice, because you don't do that often, and meanwhile the immutable is optimized for the much more common scenario where you DON"T want to update the object.
Even their example is broken. They say If you have the User with the FirstName John, why should you want to change the name to Mark? It's obviously a different Person, so it needs to be a new Object. What is with the surname? That can change when someone marries for example, is that not the same person then?
It is legal in most places for a person to change their first name at some point in their life. It’s less common than changing last name at marriage, but it does happen.
Do you have a submission form for eyebrow raising posts? I came across some for Typescript this past weekend on X and I can't stop *face palming* from it and seeing how exuberant everybody was about the post. Keep laying down your justice Nick! It is giving us hope :)
Yeah, I gave this author crap for this on Linked-In for garbage posting. This guy proved he doesn't understand properties, immutability, proper naming, when to use constructors, etc. Nick's video is spot-on as always.
Putting special cases aside: in particular, what is the major advantage of using getters and setters instead of a direct access to a field? I mean, if in the end the access it the same, you can read and modify a thing from anywhere outside
There are no real advantages. In fact, if you have autoproperties without extra code, JIT optimizer is smart enough to simply throw off intermediate calls and use direct field access anyway.
Thanks for answers so far. I will share a bit of a context for my question: years ago I was working with Java and getters/setters vs fields was definitely a subject of heated discussions. And sometimes it sounded like “you have to do it this way, because this is The Only Clean Way” without really justifying it. Nowadays, after several years in JS/TS I sometimes wonder how vastly different approaches can be across languages and their communities. And, in the end, kinda everyone creates a software that works and has its better and worse time when maintaining it. And when I see a big value in having TypeScript instead of JavaScript when it comes to evolving a large codebase, I at the same time do not believe props/fields argument has any real significance (unless working with things that enriches the code somehow and expects props or working with public APIs and necessity to not break them while having to adjust our code etc, I assume)
OOP has been created in order to re-create real-life scenarios in a program. Just imagine a real life scenario with an employee. "Oh, sorry. I noticed you misspelled me 'Jhon' in my company account". "Oh gosh dang it. Please can I have back your company ID card, your company laptop and ... could you submit your application again. Yea i know what you wanna ask. I can't just change the name, I have to create a fully new user. Each user also get's a new ID card and laptop. Don't ask. By the way ... your wage is readonly too, so be we're gonna meet again next year."
We're getting close folks LOL! My new favorite clip of Nick; ruclips.net/user/clipUgkxxq_NLg3b0eMkCmws0B2EY079YuYms61w?si=bkH_WfMEFzLGa4kO We're just missing two more words and a camera slap. I'm sure the code-cop series will lead to this. 😝
For webservices, DAOs are the only classes where mutability makes any sense. I wish c# were an immutable by default language with opt-in mutability like rust.
There is just one huge problem with c# records: "with" statement has limited mutation scope with assignments only, what makes complex assignments (partial, conditional, switch assignments or mutation methods) impossible or difficult. Almost unusable IRL. Having readonly fields allows you to define specialised constructor, where you can assign all fields however you like. Not to mention that field access time is always faster and easier for JIT/AOT to read/write, because sometimes its inlining logic is just umfathomable. Do you have a video with fields/properties access performance benchmarks for real life scenarios? Reflection-based access to fields/properties is almost the same. I don't get why EF/XAML/Blazor stuff cannot read/write fields the same way they do with properties. Even readonly fields could be assigned if needed. Fields need less typing and can be multiply declared. (public string Name, Surname, Email;) Fields can also have visibility modifiers (public, private etc.), can be agumented with attributes, so what's an added value of being a property, if there is no computation in getter and no special logic in setter?
What about property performance - are getters-calling have no effect in terms of speed? May be this have some impact, that make it reasonable to eliminate props on super high load systems?
It does increase performance. Setting a property or setting a field does make a difference. But we are talking a game loop with tens of thousands of such calls. Edit: Though last benchmarked on net core 3.1...so ages ago.
unless you do some validation on the getter, the performance diff is virtually non-existant. Even a billion read call to a property won't make it slower than 5% vs fields, or 0.2 ns diff (till.red/b/1). It's not wise to sacrifice future-proof for a measle increase in performance.
@@BriezarSo just to be sure, I made benchmarks for it on sdk 8.0.200 and 6.0.411. For pure setter, it makes no difference. But doing a sum of property on an object and a sum of field on an object is 30us difference for 100k objects on sdk 6, but 8 on sdk 8. For 1mil objects, it makes a difference in context of 16 ms per frame, but not on a new sdk version. I've ran the tests multiple times and they were not consistent, so if you were to even consider this change, benchmark it.Edit: I did some more tests where you wrap multiple properties (time, speed, offset, and readonly property to get distance). For 1mil objects, it's 0.5 ms but it's optimized in net 8.
unless you do some validation on the getter, the performance diff is virtually non-existant. Even a billion read call to a property won't make it slower than 5% vs fields, or 0.2 ns diff (till.red/b/1)
I think the bigger reason they say to use it is performance. Properties are slower than fields as properties are like a method call while a field directly accesses the object/value it contains
unless you do some validation on the getter, the performance diff is virtually non-existant. Even a billion read call to a property won't make it slower than 5% vs fields, or 0.2 ns diff (till.red/b/1). It just smells premature optimization, and not even a good one.
You're asserting here that there's a performance cost for auto properties, do you have benchmarks that show this? My understanding is that the compiler elides that "method call" away.
I am not saying I agree it’s a proper reason because it’s not and as people has said it’s virtually non existent but I have seen multiple people say “well if properties are slower why the f*** would you rather use them?” Which is why I mentioned this as this is the most common reason I have seen
@@gnack420 it does not do this as he showed a property is converted to a field with a getter and a setter of which both are methods in the way they are executed so it does not abstract it away but rather is just syntactic sugar
This advice is obviously coming from a Functional Programing enthusiast. The techniques used for Functional programing don't make sense if you are thinking about things from an O-O perspective, which of course they don't, because its two totally different programming styles.
Yeah, I don't like properties either. They're an invitation to put logic in the getters or setters. Classes can either model services (controllers, db clients, api clients, ...), or data. You don't need properties for either unless you're refactoring a legacy codebase and need to maintain a stable API. If you're starting a new projects, then you're better off imposing on yourself to just use constructor-initialized fields.
Also, having undateable database records is also a bad practice in the most common cases. The vast majority of the time, database tables should be insert-only, representing events that are immutable rather than mutable entities.
Mutability is great if the application is inherently functional in its nature. Like compilers, cli tools or data processors. Games and other GUI applications need to maintain states. Creating new object everytime for a small change is very expensive. Imagine creating a new player object 60 times per second just to change x,y position of character on screen.
They definitely didn't understand get-only properties that you can initialize from the constructor or required readonly get/init. I've been trying to explain how bad LinkedIn is for programming advice for years haha.
Honestly, I still think properties are lame the majority of the time because nothing beyond setting/retrieving the value is abstracted (and with some languages, at significant performance cost outside of release builds) I kind of just tolerate it because .NET (unlike Java and many others) takes all the boilerplate out by making it as easy as Type Name {get; set;}, so I have no real reason to be obstinate about it.
At the risk of being unpopular, I think Properties are a bad thing, they just add confusion, by mixing up processing and storing values. You have methods for processing and fields/variables for storing values, allowing processing in two places just makes things harder to understand. Imagine a new developer trying to understand all the subtle differences with all the different property options: (internal, public, private, static, readonly, const, virtual, abstract, required, private set, init). In the end you just want to set a variable for internal or external use. There is no need for this level of subtlety. If you wanted to simplify C# (which I think is desperately needed) removing properties would be a good starting point, IMO. Would it really be so hard to just to use Private and Public fields and that’s it?
For day to day cases, properties can configure the restrictions of what you can do with variables inside and outside the class, like if outside is able to set it, while still retrieve it, or not. You cannot do this with fields alone. I'm not a huge fan of the bloat properties give, but it works better for bigger enterprise software (or something else serious is other form) than fields. For example, when consumer expects value in one format you give them originally, but you want to change how that value is handled inside the class, you can turn the auto property into full property and adjust this behaviour, without introducing a breaking change. Or you can add subtle behaviour to trigger on get/set, without having to tell user to switch from using field to a method, or validation purposes (but I'd prefer compile-time solutions there). Later on in the development these requirements might come in. The learning curve of properties is just not that good and never has been, many teachers either skip or repeat the same confusing theory.
I feel like for Nick's blood pressure LinkedIn needs a way to signal *dis*approval of these posts. 250 people think this bad advice is great, but how many shook their heads and scrolled on?
@@7th_CAV_Trooper I dont like OOP very much, even though i write it every day - but i can live it and understand it. I even agree with nick this time. Also the compiler is smart enough to not generate a second backing field, if you already use one. For example: ImmutableArray without initialization breaks your application on access. So to fix that, i have a field that is always initialized to Empty and is modified/returned in the property only. I dont understand why MS introduced that feature, using a struct that breaks on read when you dont initialize/set it.
@@F1nalspace The reason is for you to not needing to necessarily allocate every time you modify it, using structs is cheaper this way. I think the problem is microsoft not treating an uninitialized ImmutableArray as 'Empty' by default.
Even if the advice about immutability was good, they missed giving you good advice about even that. They should have said use "record" instead of class for everything...
Immutable is good. If you're using readonly auto properties, why not use fields. Constructor is absolutely the right way to set fields. Should not be possible to create incomplete object. Record doesn't work because you can't protect the object from invalid initialization.
@@7th_CAV_Trooper Fair enough. Even with Nullability checks activated, external dependencies could initialize fields as null. Having said that, for your own application records are OK.
had some devs like this in my team, who confidently threw these words senselessly, and manager couldn't differentiate between their nonsense and truth, ended up with massive fack ups!! These are the same people who write these kind of trashy things on linkedin ... 👍🏻
well well, the records are bloated data structures. fields are the slimest but they are not well supported by the .net framework. so yeah, there is a point there, but it won't work. :)
Let's all just start throwing naming conventions out the window too. Wether or not you're a '_field' or 'field' type of guy, it's generally accepted that 'Property' is the naming convention. Now you're just confusing any and all implementors of your code (just imagine this actually making its way into some kind of library you implement). Do you expect everybody to decompile your library to figure out where you're messing with us by exposing fields using property naming conventions??? Anyway, the whole thing is a mess and I see very little purpose and/or advantages to it. This person just doesn't get OOP, trying to turn it into something it's not. Just imagine WPF/XAML w/o binding?!? No doubt MVC model binding would bomb on this too, since it can't map that object. Just imagine X, Y & Z. This is just plain bad.
At the end FP, OOP, immutability, mutability, ... are tools that you can use to solve a given problem. There is no in general this is better than that.
I find it painful to see that the argument "object construction should be used sparingly because it is time-consuming" is still used. Unless you are dealing with millions of objects being constructed the creation time is negligible, so please stop using this excuse. Your machine has at least 8 cores each performing bilions of operations per second so stop it already. Furthermore I agree that you shouldn't make all classes immutable but it is an underused feature. In the example of changing the name I agree to make it immutable because it's part of the identity of the object. John isn't Mark. Any other object that has a reference to it might run in trouble because now suddenly someone out there thought it necessary to change the value of an identity field. And now Mark owns John's car, congratulations, who's going to pay for the damage to John? You?
Expose fields is dangerous cause c# can address directly a reference to it. That is only useful in some situations, but only in these situations. By convention, the only public fields that I do expose as public are the static readonly one.
@@diadetediotedio6918 The reason for encapsulation is to not allow, not only the access (obtaining) of the class information but, even more so, the unauthorized modification of information. Unlike Java, in .NET it is possible to obtain a managed reference of a field, which could modify a 'final' field. That is useful and powerful, but dangerous. Please check the following code: using System; using System.Runtime.CompilerServices; public class Program { public static void Main() { PublicClassField obj = new("Text0"); ref String refField = ref Unsafe.AsRef(in obj.PublicField); Console.WriteLine(obj.PublicField); refField = "text1"; Console.WriteLine(obj.PublicField); } public class PublicClassField(in string value) { public readonly String PublicField = value; } }
@@diadetediotedio6918 The reason for encapsulation is to not allow, not only the access (obtaining) of the class information but, even more so, the unauthorized modification of information. Unlike Java, in .NET it is possible to obtain a managed reference of a field, which could modify a 'final' field. Check this code. using System; using System.Runtime.CompilerServices; public class Program { public static void Main() { PublicClassField obj = new("Text0"); ref String refField = ref Unsafe.AsRef(in obj.PublicField); Console.WriteLine(obj.PublicField); refField = "text1"; Console.WriteLine(obj.PublicField); } public class PublicClassField(in string value) { public readonly String PublicField = value; } }
You know how people will learn how to do something, then create "how to" videos or guides on it? As if they're an expert - but they're just doing it to reinforce their learning.... that's what that LinkedIn post smells like.
true!!! I remember seeing people posting about learning javascript and now after a span of a few months they are posting "how to" with words that seems like GPT generated
Instead of doing useful work, developers nowadays pay too much attention to imaginary best practices, many of which become just a kind of religious cults with negative value
People who think getters/setters is encapsulation are also the same people who think every class needs to be immutable and they are the majority Uneducated OOP meets Uneducated FP
The problem with social media these days is that negative feedback isn't visible anymore to all.
Truth! I hate that... we need to see the negative.
@@SpaceTrumpBarak Obama wouldn’t be happy about that 👨🏿
Exactly
@@saedabumokh9577 Ye Ol Bardock Obama can yell all he wants but I can't hear it because of my Wall.
People get their feelings hurt when you tell them they're wrong...more now than ever in history.
There are so many reasons why immutability can be good and that LinkedIn post managed to identify none of them.
The fact the explanation makes more sense during showing the post makes it clear that it was way too hard to explain something so obvious to someone that doesnt understand how to write c#. At the end I just feel like you try to make simple something that is already way too simple. You're a hero for trying to save people who believed that post ;(
I start to think people are exploiting this channel by sharing such ridiculous statements on LinkedIn... can't be other way.
No, LinkedIn is in fact this ridiculous because postcount++.
Or these advices doesnt exist in real lige?
@@ErnaSolbergXXX they exist, i've seen many myself
Not necessarily.. these posts happen in all programming languages
I didn't know about the with keyword. But it's great.
Thank you Nick, good explanation
I am very tempted to comment on these posts: "Congratulations! Your post has been featured in Nick's Code Cop series!"
I see no reason not to comment that 😁
@@Not.Your.Business there's a reason: not to get blocked.
@@petervo224 comment from one of your throwaways ;)
😂
Imagine someone reading this and then applying it to a game in Unity or MonoGame; every time something gets hit and loses HP, you have to replace the entire object rather than just updating the HP value.
Why to replace only some objects? Let's make the whole world immutable so we can change everything every single frame 😂
Great example!
@@RsApofis I can't believe I thought of HP before location or some other constantly changing stat. XD
Reconstruct all the objects all the time! 😂
Immutability is a concept from functional programming. it's not always the right choice in OOP
Yes, not using properties makes using EF harder but also WPF. It may not be the framework of the day but some of us still like and use it.
Hello, fellow XAML enthusiast ❤
True, these frameworks are very dated. They can't be improved now due to breaking changes.
In case you might have steered away from using Records for EF; or WPF; I can tell you that the argument attribute [property: Key], [field: Index], and/or [param: RandomParameterAtrribute()] in the record's constructor/signature will allow you to have the same attribute-based class design you may already be used to.
You already know that you're using a dated and wildly unpopular framework that, much like WinForms, is NOT going to get any more love from Microsoft in future releases.
I would implore you to look into Electron, or at the very least Photino; which are web-based wrappers for SPA/PWAs that any well written MVVM/XAML project could be transposed into.
@@asteinerd if you are talking about WPF then I can't agree with this statement. WPF is still one of the most used desktop frameworks, it is especially popular in enterprise. XAML is more pleasent experience than html + css (even with frameworks) and also offers much faster rendering.
@@asteinerd i am lucky to develop for an industry that almost entirely uses Windows for console apps so cross OS support isn’t a concern. We looked into Electron and found it much too heavy. We maintain legacy apps in WPF but you are right, new applications are generally written using SPA but using Blazor. I am not a fan boy of Microsoft but if they continue to provide support it is hard for other platforms to compete.
As an aside, like most developers I had a steep learning curve with WPF but once I got the hang of it I found the framework to be quite elegant. I never got into hardcore usage of XAML but most things could be easily done by the code behind.
Being able to blend functional and OOP concepts in an optimal way is the mark of a good C# developer.
I always forget about Records in C#. I keep thinking they're useful every time I see them used, but I always forget about them when writing my own code.
I really agree with most things you said, especially in related to those posted texts.
But as a note I would say, the point with having immutability (by default) is make you think better about what you mutate, and express that well in code.
The idea is not at all that you suddenly start copying everything around, because fact that's still a way of changing things, albeit while copying. But the idea is rather that what you actually want to mutate, you should also make that actually mutable, and be explicit about that.
What I like in Rust so much, that mutability is generally not done on the level of structs and other types, but for each individual variable. Just like you can also choose to have either a reference or a direct value. And tune the lifetime of it.
In C# this is all baked into the types itself. Reference vs value type, readonly, ref struct (which has method scope bound lifetime). This is idiomatic to the language however. So therefore I keep following that approach, and it matches here with object oriented programming and properties.
While learning OOP, I always wondered why public fields exist if they shouldn't be used
It’s extremely helpful to put a breakpoint in the setter to find exactly where some value is getting set. Especially with rambling legacy code.
Yeah it's context that matters. Such advice usually refers to when ppl make everything an auto property just by sheer momentum. But yeah, instead on focusing on fields vs properties, they then talk about immutability because it's the hip thing to talk about and everything has to be about immutability and purity
I agree that every class do not have to be immutable.
BUT if you intend to make a class IEquatable or IComparable, yes it has to be immutable, or at least properties used for comparison.
For example, if you put instances of an IEquatable class into a HashSet so that there's no duplicate, and if you mutate a key property of one of the instances, there could then be a duplicate in the Hashset and then it is an issue.
There is one case for the field approach. If you have large structs like Matrix or Quaternion you can pass it by reference `Method(in lssrgeStructToPass)` so to avoid creation of new struct on each method call. You cannot do that if this is a property.
I think people doing such radical statements are either up for controvercy to begin with or just forget that most of the time the answer in programing is "it depends"
Public fields (read only if you will) are only justifiable with interop or with very high throughput demands.
In the other 99.78% go with properties.
For very high throughput demands, use properties with [MethodImplOptions.AggressiveInlining] attribute.
Normaly, the JIT compiler will use it automaticaly for 4 instructions or less methods. You can enforce its use for properties, but it should not be needed unless you want to ensure high performance compilation (and you are not using reflection)
In the case of pure properties in release mode, the JIT compiler should usually optimize the properties and use the fields directly. This means properties and fields have the same performance, the getter/setter methods are never called.
Also count in Unity inspector elements. They also have to be public fields in order to be exposed in the inspector.
What's your reasoning? Auto-properties give you nothing and are lowered to inline fields anyway.
@@brianviktor8212 No, you can use [SerializedField] on private fields or [field: SerializedField] on properties.
I actually agree with his advice in general, but not for the reasons he listed lol
What I like about properties is that you don't need to premeditativly add getters and setters. You can just start with a field and refactor into a property when you need some logic without breaking your public API.
Starting with a { get; set; } property makes no sense, you're adding a layer of indirection for no reason.
Adding `{get;set;}` does not break the API, but it does break the ABI, requiring recompilation of code that uses your thing as a library. In C#, {get;set;} aren’t that bad, I would agree that getters and settesr are cargo cult in Java. (And also, how often do people really end up adding logic to a property in the future?)
@@Kwpolska Didn't think about that, thanks for mentioning it! I mostly know C# from a gamedev perspective where it's not a big deal to just recompile when updating dependencies, but I can imagine it's nice to be able to swap out a DLL in live environments without needing to recompile/restart the entire system.
I love these series so much. You are so on point on everything.
The reason why I'd avoid auto properties specifically (if I could, curse EF with its strict usage of only properties and built in json serializer for the same by default) is because then it becomes a superfluous function call in both directions. I was once asked why I pull an array's length out any time before I run a loop and it is for this very reason, every time the comparison in your loop is made, you no longer only have a comparison, but you then also have a function call of which I am unsure of if it gets optimized out.
Nick's reactions in this video are brilliant and just say it all.
He was really triggered by this one 😅 (but for a reason).
I didn't know that much about the topic and learned some things with the video, the difference between me and the OP is that I don't share tips about things I'm not sure about lol
I literally have multiple structs in my library that has "public required type Thing { get; init; }" and even "public required type Thing { get; internal init; }", even better than the advice
I agree with most of this, but I still haven't heard any good argument for 'naked' auto-properties as a principle. Changing the approach would probably not be of much use because of conventions. I just hate having conventions that are there for no good reason. I have yet to hear a good one from anyone that isn't circular (i.e. you should use the convention, because the convention is expected). I try to avoid setters and would rather use explicit Set methods, but I got to the point where I rarely use properties, even though I declared them. So they effectively become readonly fields to the outside. Getters and setters (and especially init setters) are great for dumb/data classes, for anything else I don't find them all that useful.
The name "property" is very intentional. It communicates that it is something about the state of the instance. Methods are what the instance does.
The syntax of using properties is similar to accessing fields, because that's what it is supposed to represent, accessing something with additional encapsulation and the ability to add behavior and sanitization.
There's a third, which is indexers, which are technically just methods as well but are build to look like accessing an array-like indexed data structure.
We could just as well write methods, but we could also write an indexer that has nothing to do with accessing any index if we feel like it. Probably not the best way to communicate what's actually done.
I heard the opposite one time.
Use properties for everything, that way you can see the amount of references above the line in Visual Studio
Still don't understand why you can't use fields instead of get-set properties? Fields are faster and you can add get-set any time is you need it later
I would love C# to have a default of immutable variables/fields/properties and require a mutate keyword, but it could be a modifier for namespace or project configuration value. It is better to specify mutability than to apply read only using readonly or init keywords. I find that setting to read only can be missed, but trying to mutate something that is immutable would fail and make you mark it as mutable to use it.
On topic of immutable-everything, could you perhaps talk a bit about where it makes sense to use functional approaches? Maybe even interop with F#?
Hey Nick!
Great advice about with keyword. Never knew about it. Always I learned great explanation of immutability in this video as something which can’t be changed after it has bern constructed. Thank you so much for sharing!
Hello, Nick, I have a question that has been bothering me since the beginning.
Sure, while there is an encapsulation principle, C#'s syntax to access properties and fields is absolutely the same.
So my question is: why bother creating default { get; set; } accessors (and thus create unnecessary functions) when I can just create a public field AND THEN if I need it encapsulated (i.e. There is now some business logic like dont assign negative values) I can just add the { get => ... set => ...} and no existing code will be broken (unlike Java)
Is it all really just because of the reflection?
There is no real reason to do that. Just a code style convention pushed by Microsoft.
Convention is a big reason as someone already mentioned but there are also other reasons. Just put that question into Google and you'll find a SO page that lists a lot of reasons to use auto properties rather than public fields.
For one, properties can communicate design intent in terms of mutability control, especially as it relates to collaborators. Fields are much more limited in this respect as they can only express the mutability concern only as far as the field's initialization goes. As such, I never consider auto-property accessors and mutators to be useless because the code is more expressive as to the design intent.
And because the compiler elides the underlying method calls as part of optimization, I can retain code that is expressive regarding the design while still enjoying the benefits performance. So I think your question should be asked in reverse: given that auto-properties don't incur a performance cost over fields, why would you want to use fields to begin with?
Your existing code WILL be broken by doing that. Oh, you'll be able to compile everything again without touching the code. But if the entity with the fields and the code that calls it are in 2 different assemblies, you won't be able to replace the assembly with the entity definition with a new version that has properties without recompiling the assembly that holds the calling code.
@@selism this one actually resonates a lot with me, dont get me wrong, the other comments all bring important points to the table, but yours is actually revealing a contradiction in my own
Thanks!
I always thought you use properties for things you intend to serialize and fields for things you don't. I totally accept if Im wrong on that!
C# also has record structs now, for stack-allocated immutable records :)
So, with all those bad advises, has LinkedIn became TikTok?
In past years it was taught that is recomended and idiomatic to expose public as properties for future compatibilty reasons.
They seem to have misunderstood what immutability is for.
The real benefit is in having a crystal clear API. That is, if you return something with properties with get/set all over the place, the implication is that if you change it that it changes… but this is rarely the case. Sure, that value on that instance might change in memory, but it’s done nothing to persisted state unless this has been implemented internally within the class (which is almost never the case in reality).
Immutable properties makes it clear to the consumer that you can’t do this. It’s self-documenting.
Nailed it with get; init; -> much clearer and doesn’t require a verbose constructor, AND it’s fully compatible with JSON serializers.
“The only (buzz) word missing here is clean” 💀💀💀
Making objects immutable IS what you want the vast majority of the time, and it is only relatively rare cases where having them be mutable makes more sense. Database records like this "User" are an example where immutable is better. While it is true that copying all the fields when you want to fake updating a User is slower, you have to keep in mind that the times when you'd legitimately want to do that are very rare, so the fact it is a bit slower isn't a problem in practice, because you don't do that often, and meanwhile the immutable is optimized for the much more common scenario where you DON"T want to update the object.
Even their example is broken.
They say If you have the User with the FirstName John, why should you want to change the name to Mark? It's obviously a different Person, so it needs to be a new Object.
What is with the surname? That can change when someone marries for example, is that not the same person then?
It is legal in most places for a person to change their first name at some point in their life. It’s less common than changing last name at marriage, but it does happen.
Do you have a submission form for eyebrow raising posts? I came across some for Typescript this past weekend on X and I can't stop *face palming* from it and seeing how exuberant everybody was about the post. Keep laying down your justice Nick! It is giving us hope :)
Yeah, I gave this author crap for this on Linked-In for garbage posting. This guy proved he doesn't understand properties, immutability, proper naming, when to use constructors, etc. Nick's video is spot-on as always.
Putting special cases aside: in particular, what is the major advantage of using getters and setters instead of a direct access to a field? I mean, if in the end the access it the same, you can read and modify a thing from anywhere outside
With complex/messy code one big benefit is you are able to set breakpoints on setters and getters
There are no real advantages. In fact, if you have autoproperties without extra code, JIT optimizer is smart enough to simply throw off intermediate calls and use direct field access anyway.
@@ErnaSolbergXXXwell, if you were writing immutable objects you wouldn't need those breakpoints.
Thanks for answers so far. I will share a bit of a context for my question: years ago I was working with Java and getters/setters vs fields was definitely a subject of heated discussions. And sometimes it sounded like “you have to do it this way, because this is The Only Clean Way” without really justifying it.
Nowadays, after several years in JS/TS I sometimes wonder how vastly different approaches can be across languages and their communities. And, in the end, kinda everyone creates a software that works and has its better and worse time when maintaining it. And when I see a big value in having TypeScript instead of JavaScript when it comes to evolving a large codebase, I at the same time do not believe props/fields argument has any real significance (unless working with things that enriches the code somehow and expects props or working with public APIs and necessity to not break them while having to adjust our code etc, I assume)
Perhaps open / closed principle is better accomplished with properties than with sheer fields.
OOP has been created in order to re-create real-life scenarios in a program. Just imagine a real life scenario with an employee. "Oh, sorry. I noticed you misspelled me 'Jhon' in my company account". "Oh gosh dang it. Please can I have back your company ID card, your company laptop and ... could you submit your application again. Yea i know what you wanna ask. I can't just change the name, I have to create a fully new user. Each user also get's a new ID card and laptop. Don't ask. By the way ... your wage is readonly too, so be we're gonna meet again next year."
You've got my like, there is so much garbage advice on linkedin that its almost comical
We're getting close folks LOL!
My new favorite clip of Nick; ruclips.net/user/clipUgkxxq_NLg3b0eMkCmws0B2EY079YuYms61w?si=bkH_WfMEFzLGa4kO
We're just missing two more words and a camera slap.
I'm sure the code-cop series will lead to this. 😝
@9.00 that record won't have required fields right? does that matter? Is it possible to add the required keyword for a records?
They will be required, yes.
For webservices, DAOs are the only classes where mutability makes any sense. I wish c# were an immutable by default language with opt-in mutability like rust.
There is just one huge problem with c# records: "with" statement has limited mutation scope with assignments only, what makes complex assignments (partial, conditional, switch assignments or mutation methods) impossible or difficult. Almost unusable IRL.
Having readonly fields allows you to define specialised constructor, where you can assign all fields however you like.
Not to mention that field access time is always faster and easier for JIT/AOT to read/write, because sometimes its inlining logic is just umfathomable.
Do you have a video with fields/properties access performance benchmarks for real life scenarios?
Reflection-based access to fields/properties is almost the same. I don't get why EF/XAML/Blazor stuff cannot read/write fields the same way they do with properties. Even readonly fields could be assigned if needed.
Fields need less typing and can be multiply declared. (public string Name, Surname, Email;)
Fields can also have visibility modifiers (public, private etc.), can be agumented with attributes, so what's an added value of being a property, if there is no computation in getter and no special logic in setter?
Obviously, if you can't change a class, you can't maintain it. Therefore, the maintainability metric is maxed out!
2:23 - i feel you did that a bit too hard to yourself 😂
What about property performance - are getters-calling have no effect in terms of speed? May be this have some impact, that make it reasonable to eliminate props on super high load systems?
It does increase performance. Setting a property or setting a field does make a difference. But we are talking a game loop with tens of thousands of such calls.
Edit: Though last benchmarked on net core 3.1...so ages ago.
unless you do some validation on the getter, the performance diff is virtually non-existant. Even a billion read call to a property won't make it slower than 5% vs fields, or 0.2 ns diff (till.red/b/1). It's not wise to sacrifice future-proof for a measle increase in performance.
@Briezar Who ever do getter setter validation in 99.99% cases))
@@BriezarSo just to be sure, I made benchmarks for it on sdk 8.0.200 and 6.0.411. For pure setter, it makes no difference. But doing a sum of property on an object and a sum of field on an object is 30us difference for 100k objects on sdk 6, but 8 on sdk 8. For 1mil objects, it makes a difference in context of 16 ms per frame, but not on a new sdk version. I've ran the tests multiple times and they were not consistent, so if you were to even consider this change, benchmark it.Edit: I did some more tests where you wrap multiple properties (time, speed, offset, and readonly property to get distance). For 1mil objects, it's 0.5 ms but it's optimized in net 8.
I would expect fields to be faster as they do not require a methode call to access the backing field. Does someone have a benchmark on this?
unless you do some validation on the getter, the performance diff is virtually non-existant. Even a billion read call to a property won't make it slower than 5% vs fields, or 0.2 ns diff (till.red/b/1)
I think the bigger reason they say to use it is performance. Properties are slower than fields as properties are like a method call while a field directly accesses the object/value it contains
unless you do some validation on the getter, the performance diff is virtually non-existant. Even a billion read call to a property won't make it slower than 5% vs fields, or 0.2 ns diff (till.red/b/1). It just smells premature optimization, and not even a good one.
You're asserting here that there's a performance cost for auto properties, do you have benchmarks that show this? My understanding is that the compiler elides that "method call" away.
If one method call is a tragic performance loss then C# was a bad choice of technology in the first place.
I am not saying I agree it’s a proper reason because it’s not and as people has said it’s virtually non existent but I have seen multiple people say “well if properties are slower why the f*** would you rather use them?” Which is why I mentioned this as this is the most common reason I have seen
@@gnack420 it does not do this as he showed a property is converted to a field with a getter and a setter of which both are methods in the way they are executed so it does not abstract it away but rather is just syntactic sugar
WPF is not going to work properly with fields, because framework assumes interaction with user-defined data through properties.
This advice is obviously coming from a Functional Programing enthusiast. The techniques used for Functional programing don't make sense if you are thinking about things from an O-O perspective, which of course they don't, because its two totally different programming styles.
Sounds like the OP was implicitly trying to create an event sourcing application - then forgot to mention the architecture
I like these videos about LinkedIn posts
Yeah, I don't like properties either. They're an invitation to put logic in the getters or setters. Classes can either model services (controllers, db clients, api clients, ...), or data. You don't need properties for either unless you're refactoring a legacy codebase and need to maintain a stable API. If you're starting a new projects, then you're better off imposing on yourself to just use constructor-initialized fields.
Also, having undateable database records is also a bad practice in the most common cases. The vast majority of the time, database tables should be insert-only, representing events that are immutable rather than mutable entities.
Mutability is great if the application is inherently functional in its nature. Like compilers, cli tools or data processors.
Games and other GUI applications need to maintain states. Creating new object everytime for a small change is very expensive.
Imagine creating a new player object 60 times per second just to change x,y position of character on screen.
Take a look on the ECS architecture, you will see how this could also work at least partially.
They definitely didn't understand get-only properties that you can initialize from the constructor or required readonly get/init. I've been trying to explain how bad LinkedIn is for programming advice for years haha.
Code Cop don't take us properties. They are such a great reminder to good old delphi and object pascal. 😊
Know who else hated mutability? Colonel William Stryker.
The text of this LinkedIn post looks more like it was AI-hallucinated than written by an actual developer 😂
Honestly, I still think properties are lame the majority of the time because nothing beyond setting/retrieving the value is abstracted (and with some languages, at significant performance cost outside of release builds)
I kind of just tolerate it because .NET (unlike Java and many others) takes all the boilerplate out by making it as easy as Type Name {get; set;}, so I have no real reason to be obstinate about it.
At the risk of being unpopular, I think Properties are a bad thing, they just add confusion, by mixing up processing and storing values. You have methods for processing and fields/variables for storing values, allowing processing in two places just makes things harder to understand.
Imagine a new developer trying to understand all the subtle differences with all the different property options: (internal, public, private, static, readonly, const, virtual, abstract, required, private set, init). In the end you just want to set a variable for internal or external use. There is no need for this level of subtlety. If you wanted to simplify C# (which I think is desperately needed) removing properties would be a good starting point, IMO.
Would it really be so hard to just to use Private and Public fields and that’s it?
For day to day cases, properties can configure the restrictions of what you can do with variables inside and outside the class, like if outside is able to set it, while still retrieve it, or not. You cannot do this with fields alone.
I'm not a huge fan of the bloat properties give, but it works better for bigger enterprise software (or something else serious is other form) than fields.
For example, when consumer expects value in one format you give them originally, but you want to change how that value is handled inside the class, you can turn the auto property into full property and adjust this behaviour, without introducing a breaking change. Or you can add subtle behaviour to trigger on get/set, without having to tell user to switch from using field to a method, or validation purposes (but I'd prefer compile-time solutions there). Later on in the development these requirements might come in.
The learning curve of properties is just not that good and never has been, many teachers either skip or repeat the same confusing theory.
I feel like for Nick's blood pressure LinkedIn needs a way to signal *dis*approval of these posts. 250 people think this bad advice is great, but how many shook their heads and scrolled on?
What??? 🤣🤣best parts of the video 😛
I think functional bros space out too much sometimes.
Embrace the funk, man. Embrace the funk.
They should add dislikes to LinkedIn ngl
I have a feeling this person just hates OOP lol
Or they hate debugging code. Immutable objects is the right answer most of the time. Not all the time, but most.
@@7th_CAV_Trooper
I dont like OOP very much, even though i write it every day - but i can live it and understand it. I even agree with nick this time. Also the compiler is smart enough to not generate a second backing field, if you already use one.
For example: ImmutableArray without initialization breaks your application on access.
So to fix that, i have a field that is always initialized to Empty and is modified/returned in the property only.
I dont understand why MS introduced that feature, using a struct that breaks on read when you dont initialize/set it.
@@F1nalspace
The reason is for you to not needing to necessarily allocate every time you modify it, using structs is cheaper this way. I think the problem is microsoft not treating an uninitialized ImmutableArray as 'Empty' by default.
The reason you use fields instead of properties is to mess up the training data of LLMs
Even if the advice about immutability was good, they missed giving you good advice about even that. They should have said use "record" instead of class for everything...
Immutable is good. If you're using readonly auto properties, why not use fields. Constructor is absolutely the right way to set fields. Should not be possible to create incomplete object. Record doesn't work because you can't protect the object from invalid initialization.
I think records do prevent invalid initialization as well as required init fields.
@@PedroPabloCalvoMorcillo show me how to perform null checks.
@@7th_CAV_Trooper Fair enough. Even with Nullability checks activated, external dependencies could initialize fields as null. Having said that, for your own application records are OK.
Feels like generative ai wrote the original post
Hey Nick, some back your vid (ruclips.net/video/QdfAOVk77v0/видео.html ) don't use fields use properties and now this? Anything changed in C#?
They are both bad advice
had some devs like this in my team, who confidently threw these words senselessly, and manager couldn't differentiate between their nonsense and truth, ended up with massive fack ups!! These are the same people who write these kind of trashy things on linkedin ... 👍🏻
well well, the records are bloated data structures. fields are the slimest but they are not well supported by the .net framework. so yeah, there is a point there, but it won't work. :)
Let's all just start throwing naming conventions out the window too. Wether or not you're a '_field' or 'field' type of guy, it's generally accepted that 'Property' is the naming convention.
Now you're just confusing any and all implementors of your code (just imagine this actually making its way into some kind of library you implement). Do you expect everybody to decompile your library to figure out where you're messing with us by exposing fields using property naming conventions???
Anyway, the whole thing is a mess and I see very little purpose and/or advantages to it. This person just doesn't get OOP, trying to turn it into something it's not.
Just imagine WPF/XAML w/o binding?!? No doubt MVC model binding would bomb on this too, since it can't map that object. Just imagine X, Y & Z. This is just plain bad.
"Please use Hungarian Notation."
There is no one size fits all.
At the end FP, OOP, immutability, mutability, ... are tools that you can use to solve a given problem. There is no in general this is better than that.
John cannot age in an immutable object.
I find it painful to see that the argument "object construction should be used sparingly because it is time-consuming" is still used. Unless you are dealing with millions of objects being constructed the creation time is negligible, so please stop using this excuse. Your machine has at least 8 cores each performing bilions of operations per second so stop it already.
Furthermore I agree that you shouldn't make all classes immutable but it is an underused feature. In the example of changing the name I agree to make it immutable because it's part of the identity of the object. John isn't Mark. Any other object that has a reference to it might run in trouble because now suddenly someone out there thought it necessary to change the value of an identity field. And now Mark owns John's car, congratulations, who's going to pay for the damage to John? You?
Expose fields is dangerous cause c# can address directly a reference to it.
That is only useful in some situations, but only in these situations.
By convention, the only public fields that I do expose as public are the static readonly one.
Why exactly this is "dangerous"?
@@diadetediotedio6918
The reason for encapsulation is to not allow, not only the access (obtaining) of the class information but, even more so, the unauthorized modification of information.
Unlike Java, in .NET it is possible to obtain a managed reference of a field, which could modify a 'final' field.
That is useful and powerful, but dangerous. Please check the following code:
using System;
using System.Runtime.CompilerServices;
public class Program
{
public static void Main()
{
PublicClassField obj = new("Text0");
ref String refField = ref Unsafe.AsRef(in obj.PublicField);
Console.WriteLine(obj.PublicField);
refField = "text1";
Console.WriteLine(obj.PublicField);
}
public class PublicClassField(in string value) {
public readonly String PublicField = value;
}
}
@@diadetediotedio6918
The reason for encapsulation is to not allow, not only the access (obtaining) of the class information but, even more so, the unauthorized modification of information.
Unlike Java, in .NET it is possible to obtain a managed reference of a field, which could modify a 'final' field.
Check this code.
using System;
using System.Runtime.CompilerServices;
public class Program
{
public static void Main()
{
PublicClassField obj = new("Text0");
ref String refField = ref Unsafe.AsRef(in obj.PublicField);
Console.WriteLine(obj.PublicField);
refField = "text1";
Console.WriteLine(obj.PublicField);
}
public class PublicClassField(in string value) {
public readonly String PublicField = value;
}
}
I'm first for once?
OrDefault
Lol
you're null
@@nickchapsas Did you just suggest he might be null? 🤣
@@nickchapsas 😂😂 Love your videos, keep up the great content!
Some of these "advices" are so ridiculous they need no debunking.
Some haskell dev using C#
LinkedIn needs a dislike button.
You know how people will learn how to do something, then create "how to" videos or guides on it? As if they're an expert - but they're just doing it to reinforce their learning.... that's what that LinkedIn post smells like.
true!!! I remember seeing people posting about learning javascript and now after a span of a few months they are posting "how to" with words that seems like GPT generated
Please show the authors, I'd like to block people like this :)
100% that article was AI generated.
At this point they are just baiting to be on code cop. Can't make this up
Idiocracy
Instead of doing useful work, developers nowadays pay too much attention to imaginary best practices, many of which become just a kind of religious cults with negative value
jesus
It's sad how bad this video actually is.
Yeah this advice is for Java people. No thanks.
This post seemed like it was AI generated
That is probably the worst advice in Code Cop so far. Took me 1 second to think "init".
People who think getters/setters is encapsulation are also the same people who think every class needs to be immutable and they are the majority
Uneducated OOP meets Uneducated FP
Lmao u dont know what encapsulation is😂