5 ms·
genuine non flamy question here. why getters/setters. Most frameworks (and not languages) use everything public. Rails, React, golang's frameworks, flask/fast
by sandGorgon 4y ago
genuine non flamy question here.
why getters/setters.
Most frameworks (and not languages) use everything public. Rails, React, golang's frameworks, flask/fastapi. Code has generally not suffered from being public.
Would you not accept a Java framework with everything public ? i asked this question on /r/java some time back and got badly flamed. So im trying to understand this. This seems to very philosophical...but then most other frameworks in other languages dont carry this philosophy.
- courgette 4y agoI would not bad an eye. But at this point with records... I don't care. I declare a Integer 'bla' and a 'getBla()' is made available by the IDE right way. Sometimes the records fields end-up being accessible without the getter. ( declaring the record in another class for instance...). But that is also a moot point : all the data they are holding is final and I know what can be null or not.
- stickfigure 4y agoI'm currently working in a Java codebase without Lombok and the habit is to make all fields public for record-like objects. It's fine 99% of the time. Every so often I want to change the behavior of something, and it's a big PITA. For example, maybe I'd like to ensure there's a default value for something that is sometimes null. If access was via getter method, I can just override the getter: class Foo { private final String name; public String getName() { return name == null ? "Default" : name; } } No need to change the hundreds of places that call .name or .getName(). This kind of thing happens often enough that it really should be baked into the language. Lo and behold, most post-Java languages support it, including C# and (modern) Javascript. Java is a bit stubborn in this regard, but Lombok solves the problem in a way that is almost language-native.
- sandGorgon 4y ago>I'm currently working in a Java codebase without Lombok and the habit is to make all fields public for record-like objects. It's fine 99% of the time. this is so cool! thanks for sharing that anecdote. trust me, ur the first person who has ever written this publicly. so I hear your argument for getters/setters. And IMHO, all paradigms do have their usecases -probably so do CQRS and everything else. But ultimately, you can refactor using the tools available today. I would (politely) argue that your example is also a notnull situation and perhaps i would have solved it on initialization, versus the way you did it. Ultimately, you can create getter/setter structures in python as well. But in most large codebases, it still ends up being unnecessary.
- stickfigure 4y ago> you can refactor using the tools available Sometimes. You can refactor your own codebase. If you're working with independent modules, or building libraries that you publish to the world, refactor tools will not help you. You can't refactor other people's code. Even in your own monolith, this kind of refactor is not great. You've turned a 1-line logic change into a patch that spans potentially hundreds of files. Reviewers hate that. > a notnull situation and perhaps i would have solved it on initialization You don't always get to decide that. The data may be serialized in from JSON, loaded from a database, imported from some weird EDI system, etc. Maybe the initialization process is not so simple, and spread out all over the codebase (or even just dozens of constructors). > you can create getter/setter structures in python Python is extremely dynamic and while I can't remember how offhand, I would be surprised if you couldn't simply override variable access the way you can with Javascript (eg, add a `get fieldname()` method). So you don't need "getters" the way you do in Java, which makes a distinction between field access and dynamically dispatched functions (and has performance benefits).
- sandGorgon 4y ago>Python is extremely dynamic and while I can't remember how offhand, I would be surprised if you couldn't simply override variable access the way you can with Javascript (eg, add a `get fieldname()` method). So you don't need "getters" the way you do in Java, which makes a distinction between field access and dynamically dispatched functions (and has performance benefits). So this is the thing - that there is nothing in python at a language level that enables/disables this. it just doesnt give a private construct. same as in javascript. you can add getters/setters if u want. in fact ECMAScript introduced getters/setters - https://www.w3schools.com/Js/js_object_accessors.asp https://www.w3schools.com/Js/js_object_accessors.asp But the thing is, huge huge codebases exist without private. There's nothing that i can see in java that requires private. not to say, ur not wrong...but so it is with almost all patterns. even CQRS. There is a certain level of complexity when it makes sense. The question is - how early do u enforce this ?
- stickfigure 4y ago
- ithrow 4y agoThis kind of thing happens often enough that it really should be baked into the language. Since Java 17 there are records.
- sandGorgon 4y agothis too. Records are basically classes with everything public right ?
- kaba0 4y agoRecords are classes with a canonical constructor that lists every field it has. The fields themselves are not public, but a method with the same name is automatically generated for each (basically a getter, just not getName(), but name() as the former is not consistent (what should be the getter for field Xx?). This result in records being shallowly immutable.
- deepsun 4y agoOver time I shifted my opinion to consider that ternary operation as "logic", so the Foo is not the right place for that. Either Foo should've been created with "Default" already set to the `name` field, or Foo users should make the decision themselves. Foo class can only contain something, but not make any decisions, no matter how small, because it's not obvious whether a decision is still small or not anymore. Getters are still useful though, for example: class Foo { // all contents of Foo, but we want to keep it serialized for performance reasons private ByteBuffer bb; public Long getId() { return bb.getLong(ID_OFFSET); } }
- stickfigure 4y agoI'm just going to quote myself from a few hours ago: > You don't always get to decide that. The data may be serialized in from JSON, loaded from a database, imported from some weird EDI system, etc. Maybe the initialization process is not so simple, and spread out all over the codebase (or even just dozens of constructors). Real-world codebases (the ones out there running profitable businesses, built by programmers that have come and gone) are rarely so clean and pretty that you can say "well, you just should have initialized it properly in the first place!" To that, I offer you Mike Tyson's incredibly apt programming advice: "Everyone has a plan until they get punched in the mouth".
- The_Colonel 4y agoIf everything is public, you don't make a difference between an interface and implementation. Meaning, your framework users can depend on any implementation detail and if you change that detail, the framework will break for these users. They will be disappointed since they didn't know they were doing something wrong (all is public and thus available to use).
- sandGorgon 4y agothats a good reason, however a lot of code doesnt need to do these kind of contracts. They are perfectly ok being more accessible to developers than enforce a lot of correctness. Which is where a lot of the JS/Ruby/Python frameworks operate. You're not wrong - my point is that a lot of places, it is not necessary.
- The_Colonel 4y ago> it is not necessary For the price of increased breakage rate. And then people still wonder why many big projects keep choosing Java instead of Ruby.
- JodieBenitez 4y agoProperties being private seems to give Java devs (and also PHP devs to a lesser extent) a false impression of security. The lack of public/private/protected is always a surprise to fellow programmers when I introduce them to Python, even though we still have conventions and it's never a problem in practice. Culture, I guess...
- kaba0 4y agoI don’t know, it seems to be a significant reason why java codebases, no matter how bad and written by how many almost completely separate teams chug along for decades. Empirical evidence does show that Java is very good on the maintainability front:
- JodieBenitez 4y agoWe've all seen unmaintainable monstruosities in any language. I think maintainability is a subject that goes way beyond language features. But if I were to relate a language feature to maintainability, that would be proper typing, not variable accessibility. Even though it's not enforced at runtime, a Python code base with type hints makes a huge difference in maintainability compared to one without. Of course Java has that by default and it's nice.
- piva00 4y agoI use this argument quite often when someone jokingly snark about me working mostly with Java. It's not my favourite language, I've worked with quite a few others, Java has just been the most consistently less painful than anything else. Ecosystem is pretty good, dependency management works; refactorings are easy with modern tooling and the typing system also works fine. Yes, it's verbose as hell and you definitely will depend on some basic tooling to be productive, I've worked in monstrosities that we managed to strip out piecemeal and get the codebase in good shape and modernised, it does require time and an experienced team though. Like you mention, the systems keep chugging along, in places with good engineering practices it's also a given to keep updating those codebases, simplifying and it happens organically when systems are running for 8+ years with 20-30 different engineers rotating in/out during this time. It works, it's not beautiful, it's not concise. It has quirks and gotchas as any language, and requires tooling, but it's quite mature and modernised enough to be a safe bet for bigger projects. Better than any alternative I've had experience with at scale.
- thangalin 4y agohttps://stackoverflow.com/a/1462424/59087 https://stackoverflow.com/a/1462424/59087
- kaba0 4y agoI think there is a fundamental difference between “OOP classes” and data. Java didn’t have a way to differentiate between the two so a convention was created with POJOs with properties, so reflection-based tools could use arbitrary classes in some way. Records are imo a really great addition, making the difference explicit. As for why private fields are important, think of a class implementing a circular buffer with a fixed-size array. Here, the start and end indices used are private state, which is a must for proper OOP — without it it couldn’t enforce class invariants.
- sandGorgon 4y agonot denying "proper OOP". my point is that a lot of code does not need it. If u were writing the exact same code in go/nodejs/python, you would get by fine without it. You would not break the contract of maliciously trying to access variables that shouldnt be accessed. For example, a popular convention is to have underscored variable names (__thisisprivate). Works perfectly OK. 99% of getters/setters dont do anything more. They do exactly this. No validation, nothing. So I'm questioning the ordinary....not the special cases.
- stickfigure 4y ago> You would not break the contract You wouldn't. Someone else would. Without fail.
- lamontcg 4y ago> Code has generally not suffered from being public. I spent 10 years suffering under a ruby app where literally every interface had to be considered public because someone might have gone code surfing and decided to be clever, so literally nothing was a simple code refactoring of private interfaces that nobody should touch. I don't understand what kinds of software people who make this argument write, but I assume it has to be something like web services where the http routing layer is the actual public interface definition and so you're benefiting from strong encapsulation at that layer. Yes, in that case the language doesn't need strong encapsulation because your external framework already provides it for you.
- sandGorgon 4y ago>web services where the http routing layer is the actual public interface definition and so you're benefiting from strong encapsulation at that layer this is actually one of the best ways anyone has put it. You may be right. I have often wondered how does the huge amount of Ruby/Python/JS work in building large companies and products, when Java mandates all this amount of massive complexity. You may be right here - in the web services world, the hard contract of the API layer makes up for less strict encapsulation everywhere else.