Jump to content
Rollo62

Class properties: Wins prettyness over functionality ?

Recommended Posts

Hi there,

 

sorry for the exiting question above, but this article leads me to this question,

what is grumbling deep in my guts for quite some time now.

 

There are some fractions of people, also in other languages, that think properties are superfluous.

Not that I am thinking like that, but I really would like to point out the special usefulness, and to ask the language experts what the advantages of properties really are.

 

Properties: Advantages

 - prettiness, looks nice and clean in the caller (not so much in the called )

 - Shorter names

 - Can be assigned to

 - Can be used in boolean operations, without the brackets ()

 - Can be used on fields directly, without getter/setter                             ( this is their biggest advantage, IMHO )

 - Encapsules internal implementation, by a well defined interface          ( this is no advantage, it is true for every method too )

 

Properties: Disadvantages

 - More overhead to maintain the property

 - Changing names, needs changing in 3 places

 - Separates getter/setter (private) and property (public) into different sections of the class interface position, must jump there to edit

 - Cannot be used in nested calls, for setting all, like  FMyOne.DoOne( FMyTwo.DoTwo( FMyThree.DoThree( True ) ) );

    ( OK, this also not works with separated setter/getter, but I could do that )

   While properties cannot FMyOne.One := FMyTwo.Two := FMyThree.Three := True;  ( which could be the only real advantage of properties, IMHO )

 - Encapsulates internal implementation, by a well defined interface         ( same true, as above )

 - When used in Interfaces, I also must define setter/getter, so no advantage over functions, by saving setter/getter 

 - When used in Interfaces, I cannot use them with pure fields, but I'm forced to define setter/getter     ( this could be a second advantage of properties, IMHO, if that could be possible )

 

Is there something I overlook here ?

To me it seems there is no real technical argument that speaks pro properties at all, beside their "prettiness", am I right ?

I hope you can show me situations where I really need them, or where they have huge performance advantages.

 

Edited by Rollo62

Share this post


Link to post

Other advantages:

  • Properties can be read-only.
  • Since you can opt to have methods for the setter and getter of a property, you also have a place to monitor the activity of the said property - with a breakpoint that simply counts accesses, a method that logs the accesses, or an actual breakpoint
  • Using the get method, a property can allow for lazy instance generation, so that if it is never used, the connected instance is never instantiated
  • Using the set method - the validity of a property value can be decided on assignment, without needing that validation to be spread around on the calling code

 

  • Like 4

Share this post


Link to post

I recently stumbled upon QT API where there's no properties and it looks REALLY awful. Instead of Class.FooProp they have Class.getFooProp and Class.setFooProp. API size is doubled with no real necessity. So properties are awesome. Drawback is that they sometimes do too good job hiding implementation details so a user utilizes them with huge perf impact (Memo.Text := Memo.Text + s - this looks too simple but contains pretty heavy code underneath).

Moreover, mechanism of published properties allows automatic (de)serialization - DFM, JSON, XML to and from object could only be done via properties

Edited by Fr0sT.Brutal
  • Like 1

Share this post


Link to post

My first "serious" languages were C++, then Java. They both do not have properties. Maybe I'm biased.

 

My brutally honest opinion: No one needs properties, especially with how limited they are in Delphi. Disadvantages include

  • You cannot fine-grain access (public read access, protected write access)
  • Delphi's code completion does not even show you if a property is writeable or not.
  • You cannot pass them by reference (var or out parameters) like you can with fields
  • It hides performance impacts. Is it just syntax sugar for directly reading a field? Or is it using a getter method that first locks something, then accesses a resource, calculates it, and then finally returns it? When performance matters, I do not know. I have to look at the implementation.
  • They can do nothing a regular getter/setter cannot. Which you will have to write anyway.

Tl;dr: Lose some advantages of using fields, lose some advantages of using getters/setters. Gain nothing, except saving three letters for "get" or "set".

 

  • Like 1

Share this post


Link to post
2 hours ago, Rollo62 said:

 - Changing names, needs changing in 3 places

That has never been necessary using MMX. Renaming the property automatically renames the field, getter, setter and optionally all references to the property in the current unit.

 

Also related to MMX: Using read/write properties allows to make use of the reverse assignment tool.

28-01-2022_10-35-07.thumb.gif.051bb6405fe59e1192f80e3a4f9511f0.gif

 

  • Like 2

Share this post


Link to post
1 hour ago, Der schöne Günther said:
  • You cannot fine-grain access (public read access, protected write access)

However I disagree with the opinion that properties are useless, but the above is driving me nuts, too. To be able to achieve this, I have a public, readonly ex. Status property, and a protected writeable InternalStatus property, which point to the same variable. It works, but I hate even to look at it.

Maybe this could be solved if internally we refer to Self as an interface... idk.

Share this post


Link to post

Different languages have different set of features and also differ in implementations of those features.

 

Properties in general are a tool that provides additional level of abstraction around encapsulation and enables future implementation changes while preserving stable public API.

 

Some of the benefits are more visible in some languages than the others. For instance, if you have public field Name and you want to add some code around retrieving that field is easy to do in Delphi. You can rename field and move it to private section and declare public function Name to retrieve it. I Java, you cannot do such thing because calling method must include brackets. This requires refactoring all code that uses such field. If you want to add setter, you will break the code in any language.

 

This is where using properties helps with encapsulation. They hide unnecessary implementation details and give implementing class to ability to change those without breaking user code. You can start with simple field backed property, which from performance aspect is no different than public field and you can add getters and setters as needed without breaking code. Without properties, you can also maintain stable API, but the cost is having getters and setters for everything and paying the price in performance. No matter how small it is, eventually it can add up. 

 

Additionally, code with simple assignment is easier to read than setter method.

 

There are some parts of general properties functionality that Delphi does not implement, like different access levels for reading and writing, or some additional ceremony when declaring properties, especially in interfaces. Some of those could be improved to make properties more flexible, but lacking them is poor argument against using properties. In situations where you really need some functionality properties don't provide, you can use other ways to achieve what you need, but not using properties everywhere else because you cannot do something in rare occasions is also not very convincing argument.

 

Arguments around name refactoring are not very convincing either. They compare name refactoring, where there is a bit more renaming in declaration. Now, compare that single place where you need to make additional rename, to refactoring all code in case where you need to replace public fields with accessor methods. 

 

When it comes to extra declaration code needed for properties with accessor methods comparing to only having accessor methods, think how much unnecessary getters and setter methods you need to write in cases where you could use field backed property declaration. 

 

Overall using properties results with cleaner code and having more functionality than you can have with simple fields or just accessor methods. The little bit of ceremony around the declaration is price I am more than willing to pay, to get all other benefits.

  • Like 11

Share this post


Link to post
1 hour ago, Der schöne Günther said:

They can do nothing a regular getter/setter cannot. Which you will have to write anyway.

they have index

you can inherit the accessors

they have nice RTTI support, can be decorated

1 hour ago, Der schöne Günther said:

It hides performance impacts. Is it just syntax sugar for directly reading a field? Or is it using a getter method that first locks something, then accesses a resource, calculates it, and then finally returns it? When performance matters, I do not know. I have to look at the implementation.

the h*ll are you talking about, how should be a GetThis() more verbose about its implementation as a property?

 

Edited by Attila Kovacs
  • Like 2

Share this post


Link to post
3 hours ago, Rollo62 said:

Is there something I overlook here ? 

To me it seems there is no real technical argument that speaks pro properties at all, beside their "prettiness", am I right ?

I hope you can show me situations where I really need them, or where they have huge performance advantages.

Stop being lazy. Properties are not there to make your job easier or make you code faster. They're there to make your code better. They enable you to better express the API of your code by encapsulating and hiding the internals of objects.

It's true that they're just syntactic sugar, if we disregard the design time aspect then everything a property can do can also be done with functions and procedure, but so what? That doesn't take anything away from the cases where properties have justification.

Share this post


Link to post
27 minutes ago, aehimself said:

I have a public, readonly ex. Status property, and a protected writeable InternalStatus property, which point to the same variable

Quite acceptable solution IMHO. I've never had a need for different access levels to properties though. In rare cases of protected setters that must be called from outside I just execute these setters.

Edited by Fr0sT.Brutal

Share this post


Link to post

For me properties are beautiful - they make clear and explicit how items of an interface can be used and, as Anders Melanders states, they hide the internals. And the way the VCL or FMX design time component system works (which relies on properties) is beautiful too.

Share this post


Link to post
5 hours ago, Attila Kovacs said:

how should be a GetThis() more verbose about its implementation as a property?

If you just get a value, you call it getX(). If you retrieve a value from somewhere, it's called retrieveX(). If you calculate something, it's calcX().

 

That's the convention we've been using. I'm always glad I directly know, just by the name of it, whether it's a potentially blocking call, a simple getter or resource intensive calculation. A simple property X tells me nothing.

Edited by Der schöne Günther

Share this post


Link to post
5 hours ago, Anders Melander said:

Stop being lazy. ... They're there to make your code better.

I'm not beeing lazy, I use them heavily, even I rarely use them with public fields alone, but initially gave them getter/setter ( so I'm overdoing more often than I should ).

The question was: Are they worth the efford, how exactly do they make code better ?

From above arguments I'm already convinced, and my gut feeling gets more towards seeing their advantages.

 

 

5 hours ago, Dalija Prasnikar said:

Additionally, code with simple assignment is easier to read than setter method

Agree to all your points, beside that.

What I really dislike is when mixing both concepts, that is ugly to me, not beatiful.

FThing.Enable := True;
FThing.Execute(  1   );
//vs
FThing.Enable(  True );
FThing.Execute( 1    );

I would say the latter is better readable, but we could argue the whole night about that :classic_biggrin:

 

But your discussions brought two real advantages to my mind:

- Performance by using direct field access vs. function calls

- When published, can be used in Designers, which would be nit possible by get/set that elegant

 

 

5 hours ago, Attila Kovacs said:

they have index

you can inherit the accessors

they have nice RTTI support, can be decorated

the h*ll are you talking about, how should be a GetThis() more verbose about its implementation as a property?

 

Good point too ...

 

I think I have to update my list

 

Properties: Advantages

 - prettiness, looks nice and clean in the caller (not so much in the called )

 - Shorter names

 - Can be assigned to

 - Can be used in boolean operations, without the brackets ()

 - Can be used on fields directly, without getter/setter                             ( this is their biggest advantage, IMHO )

 - Can have better performance with private field access

 - Can be used as published properties, in designers

 - Supports indexes

 - Supports array-style access

 - Have good RTTI support

 - Supports decorations/attributes

 - Encapsules internal implementation, by a well defined interface          ( this is no advantage, it is true for every method too )

 

Properties: Disadvantages

 - More overhead to maintain the property

 - Changing names, needs changing in 3 places

 - Separates getter/setter (private) and property (public) into different sections of the class interface position, must jump there to edit

 - Cannot be used in nested calls, for setting all, like  FMyOne.DoOne( FMyTwo.DoTwo( FMyThree.DoThree( True ) ) );

    ( OK, this also not works with separated setter/getter, but I could do that )

   While properties cannot FMyOne.One := FMyTwo.Two := FMyThree.Three := True;  ( which could be the only real advantage of properties, IMHO )

 - Encapsulates internal implementation, by a well defined interface         ( same true, as above )

 - When used in Interfaces, I also must define setter/getter, so no advantage over functions, by saving setter/getter 

 - When used in Interfaces, I cannot use them with pure fields, but I'm forced to define setter/getter     ( this could be a second advantage of properties, IMHO, if that could be possible )

 

Well that are enough good arguments on the PRO side for me, thanks for pointing that out.

Its worth the efford to use them, my daily workflow doesn't need to be corrected.

 

 

Edited by Rollo62

Share this post


Link to post
1 hour ago, Der schöne Günther said:

If you just get a value, you call it getX(). If you retrieve a value from somewhere, it's called retrieveX(). If you calculate something, it's calcX().

 

these are just your own patterns, no guarantee, it's just made up, also, calcX can be a one liner or a power-plant burner 🙂

Share this post


Link to post

Just more of the same debate about how many angels can dance on the head of a pin, and the debate either devolves into what the angels are wearing or how big the head of the pin is.

 

If you don't like using properties, don't use them. It's that simple. 

 

If you think having functions called by a property adds more overhead than calling a function yourself (as if that's a big deal) then just put "inline" after the function declaration.

 

If you'd rather have longer, more descriptive names, then just give them longer more descriptive names: 

 

property GetThisViaRESTService : integer read gtvrs;

 

I find far more advantage to using properties than not using them. And for every (infrequent) instance where there's a limitation, it's easy to get around it.

 

I only wish it were easier to type in a bunch of property declarations that follow a simple pattern: a popup box that asks for the property name, its type, checkbox for read and write and whether they're a local var or a method. Is there anything that simple that doesn't require me to install a huge amount of other stuff at the same time?

 

The most frequent problem I have is when I try to pass one into a var or out parameter in a method call. Thankfully those are not very common.

  • Like 1

Share this post


Link to post
2 hours ago, David Schwartz said:

I only wish it were easier to type in a bunch of property declarations that follow a simple pattern: a popup box that asks for the property name, its type, checkbox for read and write and whether they're a local var or a method. Is there anything that simple that doesn't require me to install a huge amount of other stuff at the same time? 

Modelmaker CodeExplorer (MMX) offers that, and a lot of similar stuff for quickly adding methods etc. And it's free now. Could not live without it...

  • Like 2

Share this post


Link to post
On 1/29/2022 at 11:04 AM, David Schwartz said:

I only wish it were easier to type in a bunch of property declarations that follow a simple pattern: a popup box that asks for the property name, its type, checkbox for read and write and whether they're a local var or a method. Is there anything that simple that doesn't require me to install a huge amount of other stuff at the same time?

Live templates work well for me

image.thumb.png.ea8b4f1e786ab50db82578076e96edf0.png

 

On 1/28/2022 at 7:05 PM, Der schöne Günther said:

If you just get a value, you call it getX(). If you retrieve a value from somewhere, it's called retrieveX(). If you calculate something, it's calcX().

So all users must remember which properties are retrieved and which are calc'ed? And code insight becomes almost useless?

  • Like 1
  • Thanks 1

Share this post


Link to post
On 1/28/2022 at 5:27 PM, Rollo62 said:

FThing.Enable := True;
FThing.Execute(  1   );
//vs
FThing.Enable(  True );
FThing.Execute( 1    );

I would say the latter is better readable, but we could argue the whole night about that :classic_biggrin:

Just a minor detail, based on the wisdom in the Framework Design Guidelines book:

 

I would call the property Enabled, and not Enable.

 

Enabled is a state.

Enable is an operator.

 

Also - I would not use FThing - but Thing.  

If it is publicly accessible as a property, I'd use the prop ref, not the field ref, unless the FThing getter did lazy initialization.

If it is not for public use, I'd place it under private or strict private and not use the F prefix.

 

Avoiding prefixes also helps for readability.

 

Thing.Enabled := True;
Thing.Execute( 1 );

// or

Thing.Enable;
Thing.Execute( 1 );

// or - Enable could be a function to set Enabled to true, that returns true if it succeeded.

if Thing.Enable
 then Thing.Execute( 1 );

 

Share this post


Link to post

I agree, Enable(True) is just bad. It is either Enabled := True and Enabled := False or Enable and Disable; It is quite similar to TDataSet having Active, Open and Close.

 

Side note: we can see a problem here where Open can bei either a state or an operator. Thus I prefer the Is prefix for states: IsOpen, IsEnabled for clarity. (Is only serves as a placeholder here for syntactical equivalents appropriate for the used wording and intention).

  • Like 2

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×