So considering you can just generate and forget why is it tedious?
So considering you can just generate and forget why is it tedious?
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.
I guarantee you that you will deal with way more uncertainties than Java.
This getter/setter is a micro-issue/insignificant.
Let's remove them and go back to IDE generated goto's !
private(set) var foo: Int
Int foo { get }
etc.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.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.