5 ms·
The one thing keeping me away from Java still is the awful experience around modeling data. Compared to something like a case class in Scala or even autoproper
by ubercow 11y ago
The one thing keeping me away from Java still is the awful experience around modeling data.
Compared to something like a case class in Scala or even autoproperties in C#, writing classes with a bunch of getter and setter methods just to keep state is really tedious.
- LoneWolf 11y agoI'm seriously tired of this argument against getters and setters, just generate them with the IDE some also support collapsible regions with a start and end comment, and forget about them. So considering you can just generate and forget why is it tedious?
- cballard 11y agoIf it can be generated, why doesn't the compiler do it for you? This shouldn't be done at the IDE level.
- zo1 11y agoBecause it's not about tooling, it's about being explicit vs implicit. Though, there is something to be said about having a nice default that you can easily invoke at the code-level.
- raphaelj 11y agoYeah, and loops are just (less powerful) syntactic sugars over jump instructions, too. Let's remove them and go back to IDE generated goto's !
- cballard 11y agoMany modern-ish languages with OO features (Swift, C#) let you declare that a thing has a getter without having to actually write boilerplate, i.e.: private(set) var foo: Int Int foo { get } etc.
- wtetzner 11y agoHaving the ID generate getters and setters makes it difficult read your data types, and adds additional work when modifying them.
- adrusi 11y agoThe best argument is that the compiler doing it add complexity to the language. One might say adding complexity to the language is justified if it means removing complexity from the programmer's workload, but in many languages that attempt to solve this problem that's not how it works out. Most solutions to this amount to allowing programmers to intercept field access via getters/setters. This way they can just use public fields and switch to getters/setters when they need to add special behavior without breaking the interface. Pseudocode: // using methods; no special behavior class Foo { private bar public get_bar() { return bar } public set_bar(_bar) { bar = _bar } } // using methods; special behavior class Foo { private bar public get_bar() { return decode(bar) } public set_bar(_bar) { bar = encode(_bar) } } // using getters/setters; no special behavior class Foo { public bar } // using methods; special behavior class Foo { public get bar { return decode(bar) } public set bar(_bar) { bar = encode(_bar) } } Rather than eliminate complexity from the programmer's workload, this just moves it elsewhere. Instead of tedium, which is something that can be alleviated by simple tooling (copy/paste, editor macros, templated code snippets), you get a constant concern over whether a field access will have unexpected behavior, which is something that can only be alleviated by complex tooling (semantic code analysis). So ultimately this approach adds complexity to the language/compiler, adds complexity to the tooling, and has no effect on the programmer's workload. I'm trying to think of a better approach and the best I can come up with right now is a macro system in the language (one that makes it very clear where a macro is being expanded, to avoid the same problem of "constant concern"). For example: macro #generate_accessors(field) { let paramname = unique_identifier() return #[ public #[ identifier_from_string("get_" + field.as_string()) ]() { return #[ field ] } public #[ identifier_from_string("set_" + field.as_string()) ](#[ paramname ]) { #[ field ] = #[ paramname ] } ] } // no special behavior class Foo { private bar #generate_accessors(bar) } // special behavior class Foo { private bar public get_bar() { return decode(bar) } public set_bar(_bar) { bar = encode(_bar) } } But I haven't seen any language where this is the canonical approach.
- cballard 11y agoYou also have that problem in a language with non-synthesized setters, because there's no guarantee that they don't do anything - and people avoid permitting direct field access, so you'll be going through a setter with unknown behavior. That being said, if you're throwing off side-effects like mad in setters, short of prohibiting either mutability or side-effects, there's not much the language can do to prevent that.
- rakoo 11y agoBecause it's actually useless, having the work been done by someone else or something else means the work is still done, and you still depend on that 3rd-party.
- hodwik 11y agoBetter program in Assembly then.
- rakoo 11y agoI was strictly speaking about getters and setters, and I do maintain that they are completely stupid and useless. If you're writing your 10 kLOC side-project, then sure, just use them and take comfort in knowing that there's a tool out there that you can just add to the toolset. You're (almost) the only one working on this project, there are no clear steps for how to setup a working environment because you gradually built it along the road. But when you're on a 10 MLOC projects that's been touched by hundreds of people for decades, most of which just can't program and aren't there anymore to fix the mess they left, with untouched original parts still being the core of your system, with nobody having a clear picture of how the whole thing works because it's been divided in so many parts that interact through a poorly-defined, undocumented interface, then you become extremely wary of adding anything because you don't want to complicate things further, but you still have to make it work, because it actually solves a problem for the customer. The more you can remove, and the less you need, the happier you will be. Using lombok or having the IDE do it may solve the problem, but there is a much better alternative: remove the problem altogether.
- edwinnathaniel 11y agoTry 1 MLoC project written in dynamic programming language (in this case: javascript) and touched by hundreds developers for 3 years. I guarantee you that you will deal with way more uncertainties than Java. This getter/setter is a micro-issue/insignificant.
- mgkimsal 11y agoI really prefer Groovy's approach - default get/set behaviour is provided at compile time, but you can override in code with explicit getter/setter methods. Really seems to be the best of both worlds.
- encinarus 11y agoOne thing to look at for Java would be auto/value (Immutable value-type code generation for Java 1.6+ by Google) https://github.com/google/auto/tree/master/value https://github.com/google/auto/tree/master/value Not the same as what you reference in the other languages, but useful if you find yourself dealing with it in java.
- ubercow 11y agoThis is really cool! I had no idea something like this existed.
- opmac 11y agoUse `public final` fields and put them in the constructor. Use builder classes to handle optional parameters.
- Hermel 11y agoThat's because Java is object-oriented. Data and the functions that operate on that data are not supposed to be separated. A clean object-oriented design has no plain getters and setters.
- Retric 11y agoA point (x,y) or (x,y,z) class seems to be the obvious exception. Anonymous objects can also be really useful.
- pzone 11y agoThat's because Java is pedantically and obsessively object-oriented
- hodwik 11y agoI've found that most people who think Java is overly OO are actually writing procedural programmers, who use objects as ornamentation. It is fundamental to OO that implementation details are not exposed. Accessor methods are, by their very definition, not Object Oriented. It's okay to use them, but you're not doing OO, and you very likely shouldn't be using Java if that's the case.
- wtetzner 11y agoExcept that encapsulation doesn't make a lot of sense when you're just modelling information. For example, suppose you have an Employee class that contains the employee ID, name, birth day, etc. Employee records don't do anything. They're just data. Hiding that data makes no sense if the point of their existence is just to hold the data.
- hodwik 11y agoYou don't simply model information in an OO language, everything is an object, you're supposed to model your domain. I don't reach into the employee class and "get" the employee ID so I can do something with it. The employee class knows what to do with their own ID. Just like a cashier doesn't reach into a Person's brain for their debit code. The cashier asks them to type it into the keypad, and points them where to do it if it isn't obvious. Low-level accessors to an "object's" state are almost never an accurate representation of the domain you are modeling -- they're bad design. If you need them, you've probably missed a piece of the puzzle. That being said, most programmers don't need to be doing OO at all. The level of guarantee it provides is, for most people, not worth the cost. In those cases, don't use Java. We will all be having this same argument about functional languages in 10 years. Mutability is not functional, if you're relying on mutability you're probably just doing procedural code wrapped up in functional decorations.
- elchief 11y agolombok
- deleted 11y ago[deleted]
- zo1 11y agoOr just use public instance variables, really. Unless you plan on explicitly specifying how your internal variables are going to be used and accessed, you don't get a free-lunch.
- agumonkey 11y agoMeijer or Oderski advised to use Kotlin / Ceylon to lift the burden of Java POJO. They have enough syntactic sugar and type niceties to make you happy again. Probably Meijer ...
- astral303 11y agoDon't use setters and getters in your models. Use public fields, add getters and setters if you have to. Serialize your POJOs using Jackson. All modern data frameworks can deal with public fields just as well as getter/setter combinations. (Unless you are publishing a public API. In that case, you can't easily convert a public field to a private field/getter/setter setup if needed, as the cat is out of the bag and clients have code against the public field.) Do I wish there were auto properties like C#? Oh yeah, I'd love that. But I do find modeling fairly easy. I also lament having to manually maintain equals/compare/hashCode/toString implementations. However, with IDE auto-generation of code (using IntelliJ) makes this merely noisy and annoying, and not a time sink or a constant source of dumb errors.
- cgs1019 11y agoGoogle's auto library, auto/value in particular, is worth a look: https://github.com/google/auto/tree/master/value https://github.com/google/auto/tree/master/value
- wtetzner 11y agoYes, in the Java projects I work on we use Lombok [1], which is nice, but is also a hack around the fact that Java makes these things hard. https://projectlombok.org/features/index.html https://projectlombok.org/features/index.html