There's more to properties than just syntax-sugar as I initially said (such as being a single unit), and I think I've built more of a case for why using property-based getters/setters over fields are better that working with fields directly. If the syntax sugar isn't your cup of tea but you agree with using methods over fields, I think that's the limit of my argument here.
A tricky one, saying something as tidy as no side effects clearly doesn't work; anything we do has to be a side effect, as our hands are tried regarding return values. I don't think it would be practical to come up with perfectly precise rules for what is appropriate, only guidelines. Even never throw an exception seems too strong, as you might want to do range checks. Never block would complicate logging.
> If the syntax sugar isn't your cup of tea but you agree with using methods over fields
Yes, I think that's where I'm going with this. The advantages of avoiding public fields seem clear enough, we just disagree about the merits of properties.
I don't think Ada supports arbitrary user-specified constraints, but I'm no expert.
[0] https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gnat_ugn/Run-Time-...
[1] https://docs.adacore.com/spark2014-docs/html/ug/en/usage_sce...
Ada has Dynamic_Predicate(s) which "can be any Boolean expression". [0] So, I'm guessing, you can write a pointless Predicate which does not terminate in some cases or takes unreasonably long.
[0] http://www.ada-auth.org/standards/12rat/html/Rat12-2-5.html
> In the case of Dynamic_Predicate, the expression can be any Boolean expression.
Ada functions are permitted to have side-effects (although this is disallowed in SPARK), so I imagine it would be possible to make a real mess if you wanted to.
If you follow standard naming practices in C#, properties are distinct from fields, which means they do "look like" computation once you're used to it.
Add null-conditional operators and null-coalescing ones, and you can get code that is overall much more readable and easy to reason about.
But I agree with you on the Kotlin examples in the article. Even though it's been a while since I last did Java, my gut reaction is that it looks wrong, because it looks like I'm directly accessing a field.
So you need a little bit more than just the feature itself, you need something to distinguish them from fields when you're looking at code, or you're gonna run into surprises. Whether that is casing or syntax highlighting or naming conventions, I don't care very much, as long as there's something.
Of course, lack of discipline can screw it up, but you could name the getter for x "setY()", and make it delete the entire filesystem when you call it. You can't guard against stupidity like that...
The ambiguity is between properties and fields, not between properties and methods. Looking at the style guide, I don't think there's any difference between how public fields and public properties are styled in .Net. [0]
> Whether that is casing or syntax highlighting or naming conventions, I don't care very much, as long as there's something.
Ideally it shouldn't rely on fancy tooling. I'd rather it be clear in the plain text of the source.
> you could name the getter for x "setY()", and make it delete the entire filesystem when you call it. You can't guard against stupidity like that
It's true, we don't yet have a language that prevents poor choice of identifiers.
[0] https://docs.microsoft.com/en-us/dotnet/standard/design-guid...
Personally I don't like them, for the reason labelled in the article as Problem 2: Arbitrary Computation. Computation should look like computation. I like it to be perfectly clear which statements can throw, and which cannot. I prefer List.getSize() over List.size precisely because the implementation should be permitted to perform computation, and it looks wrong when the code implies otherwise. I like to know that after executing Universe myUniverse; myUniverse.answer = 42; the value of myUniverse.answer really is 42. edit Ignoring the slim possibility of overflowing the integer type of myUniverse.answer.
Properties make it harder to reason about these things. Similar madness is possible in languages that allow overloading the assignment operator, such as C++. Come to think of it, you could probably 'fake' properties in C++ this way.
I accept that properties can make for slightly tidier expressions. I also like the point that properties are a single unit, tidily united in a way that getter/setter pairs aren't. Overall though I value 'honesty', and the ability to reason clearly about code, over these things.
I can't imagine Ada ever supporting properties, for the same reasons.