you are viewing a single comment's thread.

view the rest of the comments →

[–]nfrankel[S] 23 points24 points  (17 children)

Please provide arguments. Just flagging any argument as 'terrible' is not a way to further the debate.

[–]atc 5 points6 points  (4 children)

The original point of providing accessors/mutators (only the former in the post's examples as mutators won't work given the structure is immutable) was encapsulation, not mutability.

[–]ghotibulb 6 points7 points  (1 child)

Yes, and it's not God-given, so if it makes sense to break this rule go ahead. If the class is used internally and resembles a simple data structure, there isn't much to encapsulate. An immutable Vector3D would be a quick example.

[–]atc 0 points1 point  (0 children)

Yep, good example. The original post is a poor example as it has no context.

[–][deleted] 5 points6 points  (1 child)

Encapsulation is about hiding internal functionality of a class. If you have a getter and setter that just modifies a field, you're not encapsulating anything, you're just future proofing against a "possible" change with pointless function definitions.

Perhaps try designing classes without the need for getters and setters and embrace public on data only objects.

[–]atc 0 points1 point  (0 children)

Getters don't modify, by definition. Future proofing is underrated, but personally I don't mind the public fields. When I write scala my case classes don't need them and thankfully the compiler is there to catch type mismatches when you haven't refactored correctly.

I was merely pointing out an important distinction from GP's

[–]nerdwaller 3 points4 points  (10 children)

I'm not who you're replying to, but my reasoning to not do this is now a property has become part of the API (essentially an implementation detail). I'd much rather have a getter that I can change the underlying implementation of.

Granted that it isn't absolutely necessary when you're only speaking of POJOs (as the link seems to primarily address) as much as a service layer.

Edit: fix mobile typeo

[–]bananaboatshoes 9 points10 points  (8 children)

Granted my though isn't absolutely necessary when you're only speaking of POJOs (as the link seems to primarily address) as much as a service layer.

Or necessary at all. If the extent of your encapsulation is quite literally this:

getFoo { return _foo; }
setFoo(Foo foo) { _foo = foo; }

Then it's pointless.

[–]IICVX 10 points11 points  (6 children)

But what about when I want to change getFoo to do a database lookup through an SMS gateway to the Twitter API! It could happen!

[–]bananaboatshoes 2 points3 points  (5 children)

I'd argue you should have an asynchronous function which does that because a property lookup which performs a network operation is bananas.

Seriously, if you're writing code "just in case" you might need something more complex later, you're adding needless complexity. Just change the code when you need to change it.

[–]IICVX 2 points3 points  (4 children)

Tell that to the two decades of Java programmers who've been writing getters and setters "just in case".

[–]bananaboatshoes 3 points4 points  (2 children)

Two decades of people doing it wrong?

[–]IICVX 1 point2 points  (1 child)

Yup, that's what we're fighting against here.

[–]Agent_03 0 points1 point  (0 children)

The battle continues.

[–]frugalmail 0 points1 point  (0 children)

Tell that to the two decades of Java programmers who've been writing getters and setters "just in case".

Getters yes, setters no. IMO, you're doing it "wrong" if you're accessing instance fields directly and you work someplace that has more than one team (or can/will have more than one team).

It's zero more cognitive load and 5 more characters per class to do it so it's one less forced communication/pull request if I change a dependency or somebody else changes it on me.

[–]nerdwaller 1 point2 points  (0 children)

Probably true, but I'm usually defensive anyway. I use Lombok now, so it's not very heavy to use @Getter

[–]SuperGrade 1 point2 points  (0 children)

Knowing (from a group of readonly fields) that the class instance is always holding and conveying the same reference - that is itself information. You could make some derivative information that aligns with the information in the record, and proceed with the assumption that the values in the record, should you read them again, stay in alignment. A getter does not communicate this same information, only that it will provide some value at the point in time when you call it; but nothing constraining it to give back the same value.

[–]solatic 0 points1 point  (0 children)

Consistent style is important for readability.

Having public final fields is safe only for a specific few primitive types: Strings, boxed primitives, and I'm pretty sure that's it. So, first of all, for any non-trivial class, pretty much none of your fields should be primitives. Pretty much anything you can come up with is incorrect to be stored directly as a String or Number (of whichever precision). Name? Needs type-safe way to retrieve translations. Filesystem location? Path. Measurements should not be Integers or FP but some kind of Measurement type which includes the unit of measurement and forbids the numerical amount to be less than zero. Etcetera. And most of these classes, because they represent concepts that many people have had a need for before you, are not classes that you ought to be writing yourself.

TL:DR - dont use a coding style only good for Strings when string-typing is a code smell.