4 ms·
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. Every so
by stickfigure 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.
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> that there is nothing in python at a language level that enables/disables this Yes, there is. `@property` allows you to change a vanilla field to a getter/setter without modifying client code. >> override variable access the way you can with Javascript (eg, add a `get fieldname()` method) > in fact ECMAScript introduced getters/setters That exchange was weird. > huge huge codebases exist without private I'm honestly not quite sure where you're going with that. Huge codebases exist in COBOL too. It sounds like you're trying to argue that the software world doesn't need encapsulation. I disagree. Maybe you took my comment "99% of the time it's fine" the wrong way - 99% isn't good enough. The 1% wastes a lot of time and energy, it's better to have language support for encapuslation. Java's support for encapsulation (getters) is pretty tedious. Lombok and records (too modern for this codebase, unfortunately) fix that. Thus "getters/setters are a nonissue".
- sandGorgon 4y agoi hear you - then let me ask you: what would make Java frameworks better (not the language) ? Not just for existing developers, but also people who are new to the language and are doing the old golang vs java eval.
- 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".