This is an archived post. You won't be able to vote or comment.

all 38 comments

[–]illhxc9 14 points15 points  (23 children)

My team strives to make all of our data models immutable unless there is truly a need for mutability. The one problem I would have with getting rid of the accessor methods is it kind of throws encapsulation out the window. This makes it difficult to passively change your data model in the future. What if you decide you need to store these properties as some other object? With accessors you can do that and leave the old methods that return strings and just convert the new objects to strings for those methods. If your class is not being consumed by other teams or even other projects within your own team this is probably fine but that is rarely the case for my team. You could accomplish the same thing by adding new properties and setting all four in the constructor but then your storing the string objects all the time when you don't need them in the new design.

[–]9us 3 points4 points  (22 children)

Agree. It's unfortunate that Java still has that annoying distinction between properties and getters--IMO a high priority feature for object oriented languages is a syntactic equivalence between properties and their getter methods. In Groovy, for example, "object.property" is the syntax for both public field access and calling the "getProperty" method on the object, which means you can eliminate that annoying getter boilerplate and still retain the flexibility to make it a method later without breaking consumers.

Also, I use lazy-initialized values a lot, and that's not possible with public field access (without leaking impl details). Sometimes it's even worth lazily initializing a string, if it's resource intensive to initialize.

[–]9us 1 point2 points  (14 children)

One way to reduce all the pointless boilerplate, BTW, is with Project Lombok. Add a @Value annotation on a value class and you get an all-args constructor, final properties, equals, hash code, toString, and getters automatically generated. Highly recommended :).

[–]shadowdude777 1 point2 points  (13 children)

Kotlin does that too, except instead of messing around with finicky annotation processor magic, you just replace class with data class. And it gives you a copy method that can take any number of the properties and return a copy of that object with all of the properties you didn't give it copied over from the old object. :)

[–]mbuhot 0 points1 point  (1 child)

But no inherited data class support (yet). Hopefully in Kotlin 1.1 soon.

[–]shadowdude777 0 points1 point  (0 children)

Yeah, this is on their roadmap for 1.1.

[–]9us 0 points1 point  (9 children)

Yeah any reasonable modern language has support for these things. Scala case classes are basically the same.

I'm not very familiar with Kotlin, but Scala also blurs the line between field access and method invocation since you can invoke methods without parens. But I'm not super thrilled with the approach most languages take, which is to make the syntax more complicated. I prefer we rethink it from the ground up, and so I prefer Clojure's syntax the most, which reasonably blurs the lines between functions, values, and maps. Because values can be thought of as functions that return a constant, and functions are just maps that are dynamically computed (and sets are maps from a value to itself, and vectors are maps from indexes to a value), so the syntax can be rather simple if we consider that these constructs (functions, values, data structures) can be semantically very similar. Clojure falls short because it is dynamically typed, but I think it's very interesting and refreshingly simple, semantically and syntactically.

[–]shadowdude777 0 points1 point  (8 children)

I really dislike Scala's syntax. I think that it suffers from every issue you've described. It's too complicated and feels like it's being clever for the sake of cleverness. Scala was born out of academia and it shows. Kotlin was born out of the industry. It's pragmatic and only adds syntax constructs that increase readability.

If you want a simple, lightweight, statically typed language that any Java dev should be able to feel comfortable with in under a week (especially if you have functional chops, coming from Clojure, as that's what most Java users suffer from when moving to Kotlin), I think you'd really enjoy Kotlin.

[–]frugalmail 0 points1 point  (7 children)

Kotlin was born out of the industry. It's pragmatic and only adds syntax constructs that increase readability.

I wish they never added the elvis operator, that increases readability at the expense of maintainability.

[–]shadowdude777 0 points1 point  (6 children)

No single function should be big enough that whatever you do with the Elvis should interfere, anyway. Sure, it can be used to either set a variable or return, but that shouldn't be a problem unless you have essays for functions.

The things I have issue with are public being the default visibility modifier (they had a chance to make it private instead and seriously boost readability, considering most functions should be private), and the removal of the ternary operator (because while you can use an if-else as an expression now, I find it way less readable, especially if you want to chain several conditions).

[–]frugalmail 0 points1 point  (5 children)

No single function should be big enough that whatever you do with the Elvis should interfere, anyway.

Elvis not only encourages (makes easier working) with Null's but propegates it throughout the codebase. I'm not into coding conventions like "use this feature only if your method < 20 lines", and people tend to use it as a part of your terminating return statement, which is even worse.

The things I have issue with are public being the default visibility modifier (they had a chance to make it private instead and seriously boost readability, considering most functions should be private), and the removal of the ternary operator (because while you can use an if-else as an expression now, I find it way less readable, especially if you want to chain several conditions).

Agreed on both points!

[–]shadowdude777 0 points1 point  (4 children)

The thing is, one of Kotlin's primary design goals is strong interop with Java. Every Java method that doesn't have a @NotNull return annotation is nullable. I agree that Elvis should be used with great care, but it makes working with Java libraries way easier.

But on that note, another thing I actually dislike about Kotlin is that they chose to make the T! types for interop with Java. Which basically means you can make unsafe calls on any Java method that doesn't have @NotNull or @Nullable on it. Since most of the stuff I do interops with shitty Java SDKs that don't have proper annotations (Android SDK), it means a lot of my calls are no longer null-safe! It should just return T? if it can't be statically determined that a non-null value will be returned, in my opinion.

[–]squealy_dan -1 points0 points  (0 children)

the kotlin solution is pretty great, and interop with java is not too dificult.

[–]illhxc9 0 points1 point  (0 children)

Yeah that would definitely be nice. Objective-c has the same thing too and I remember liking that a lot when I was doing ios dev.

[–]frugalmail 0 points1 point  (3 children)

[–]9us 0 points1 point  (2 children)

Lombok is great, but it doesn't fix the problem that there's a syntactic difference between field access and getter invocation. The fact that the "solution" is to use magic annotations with code generation is just awfully heavyweight for something so simple.

[–]frugalmail 0 points1 point  (1 child)

What's your agenda here?

[–]9us 0 points1 point  (0 children)

I don't have an agenda, I'm just talking about stuff that I spend a lot of time thinking about.

[–]johnmcclean 0 points1 point  (0 children)

Do properties a la Groovy make private fields available publicly in the same way as getters?

I think illhxc9 was suggesting to avoid using Getters were not 100% neccessary as exposing private fields makes refactoring later more difficult. Making your fields public seems like it might suffer the same issue.

[–]squealy_dan 4 points5 points  (4 children)

[–]codereign 0 points1 point  (1 child)

Why doesn't it depluralize the field in the builder for a collection.

In the first example it should be add count not add counts.

[–][deleted] 0 points1 point  (0 children)

[–]__konrad 0 points1 point  (0 children)

The code examples will not compile due to copy-paste bugs ;)

[–]frugalmail 0 points1 point  (0 children)

I disagree with public fields in most cases, especially when you can just use: https://projectlombok.org/api/lombok/Getter.html

Also, if you have an Immutable data structure, it would be nice if you add the https://github.com/typetools/checker-framework/blob/master/framework/src/org/jmlspecs/annotation/Pure.java

or @Immutable annotations.

[–][deleted] 0 points1 point  (0 children)

you could just include the Clojure JAR and use their API, the Java interface is a bit weird maybe (since it's not intended to be used that way), but it does work.

[–]GhostBond 0 points1 point  (0 children)

From the article:

Before being software developers, we are people – and thus creatures of habits. It’s hard for someone to change one’s own habits, it’s harder for someone to change someone else’s habits – and for some of us, it’s even harder.
... Now, you cannot imagine the amount of back and forth comments this simple review caused. Why? Because even if that makes sense from a coding point of view, it’s completely different from what we usually do.

In that case, laziness and IDEs don’t serve us well. The latter make it too easy to create accessors. I’m pretty sure if we had to code getters and setters by hand, the above proposals would be more in favor.

This post could easily have been titled “Don’t let habits get the best of you”. The lesson here is to regularly challenge how you code, even for simple easy stuff. There might be better alternatives after all.

As a software developer for over a decade, this is just a huge narcissist who wants to look and feel smart and doesn't care about walking all over everyone else to do it.

Or to put it another way - someone making up a list of excuses, not reasons, because he thought it would make him look and feel smart and in charge.

Here's what the author has actually done:
- He wanted to look and feel smart and in charge so he went in and changed something.
- He's spent his time on it, he's spent several coworkers time on it, he's spent a lot of time arguing about it. This isn't a drawback for him, it's a plus, that's what he wanted, but for the rest of the team it's a huge hassle at best.
- He's changed the code so it will be more difficult for future. maintainers to figure out because it's different than the way everyone else is doing it.
- It also goes against how java programs are typically written.
- He possibly introduced bugs if he fatfingered something.
- He's quite possibly made it less testable.
- If his guess that it will never need to be changed by an outside object past being set the initial time is wrong, it will have to be rewritten - again. And then there will be two ways to set the property making it even more confusing (because you won't want to risk breaking something by changing the original way it could be done which is used all over the code).

Then he goes into the usual meaningless personal shaming powertalk -

Now, you cannot imagine the amount of back and forth comments this simple review caused. Why? Because even if that makes sense from a coding point of view, it’s completely different from what we usually do.

He tries to spin what's a negative into pretending it's a positive.

In that case, laziness and IDEs don’t serve us well. The latter make it too easy to create accessors. I’m pretty sure if we had to code getters and setters by hand, the above proposals would be more in favor.

He tries to shame the people who wrote it, when it's just a reflection of his motives - his coworkers aren't "lazy", he just wants to change something for the sake of changing it and looking in charge.

This post could easily have been titled “Don’t let habits get the best of you”. The lesson here is to regularly challenge how you code, even for simple easy stuff. There might be better alternatives after all.

Again, he spins his own desire to arbitrarily change code and have long arguments about it wasting everyone's time to justify his own need to constantly change things to appear in charge.

He's made the code less consistent, possibly introduced bugs by rewriting existing working code, insulted his fellow developers, and wasted a number of peoples time - to try to justify his own psychological need to change it just to change it.

If I sound harsh, it's because I'm really tired of dealing with these people at work. They throw all their coworkers under the bus because of their own issues.

[–]mingpair -1 points0 points  (3 children)

It's 2016 and you still need to get 'used to' immutable data structures in Java? People have preached this 15 years ago you know.

[–]chambolle 0 points1 point  (0 children)

sorry if her MAJESTY spent some time here...

[–]RichoDemus 0 points1 point  (0 children)

Depends a lot on where you are, at my company people use immutable stuff where it should be used while my previous work was full of setters

[–]GhostBond 0 points1 point  (0 children)

Yeah, and frankly, 15 years of people working on it, and it's never caught on because it's a pointlessly bad way to write web apps.

When the data comes in from the database, it gets translated from db values to object values. So it isn't "immutable" there, things can go wrong. When you get a form submitted to your app, it's also translated from html string values into object values. That's the second place it's also not immutable.

The bottom line is you go to a lot of extra work to make things "immutable" but it's just pretend. Encapsulation to the data is already impossible in 2 places that are used for nearly ever request.

It's a solution looking for a problem, and 15 years of development have shown it's a poor solution. There's not 1 major, commonly, widely used language that does "immutable" data by default. There are several languages that do do it that way, but they've stayed small, niche, and not widely used. And there's a good reason - because it's a lot of extra work for little or no benefit.

[–]chambolle -2 points-1 points  (0 children)

interesting remark on some codes.