3

I have been writing different classes lately, and I have noticed that I have inadvertently been reading / writing to them using both field and property identifiers, and I am wondering what are the pitfalls if any of doing this?

Lets use a basic class as an example:

TMyClass = class
private
  FName: string;
  FID: Integer;
public
  constructor Create(AName: string);
  destructor Destroy; override; 
published
  property Name: string read FName write FName;
  property ID: Integer read FID write FID;
end;

By field identifier I mean, for example FName and FID, and by property identifier I mean Name and ID for example.

The whole purpose of the published property is to be able to access it outside of the unit the class is written in if I am not mistaken. Which surely means the field identifiers should be used in the unit the class is written in, after all you cannot access those field identifiers outside the class.

This is where I have noticed that in some of the procedures (private or protected) I have not been using FName or FID, but instead have used the property equivalent, Name and ID - or sometimes mixed.

So far I have seen no issues, and in fact I normally would use FName and FID but like I say, have inadvertently not done so for some reason.

Is this bad practice or could it lead to something more sinister?

Thanks.

  • 2
    I'd say "bad". It's rather easy to get infinite recursion (leading to real-world stack overflow) if you mix up field values and setters for them (via the properties' names). – MartynA Sep 27 '13 at 19:38
  • It's not clear to me what "this" is that you're asking about being bad practice. Do you mean the practice of using fields exclusively within the class, and properties exclusively outside it? Or the practice of referring to fields *and* properties within a class? Either way, you're misguided about a couple of things. First, external access is not the "whole purpose" of properties. Second, being unable to access fields outside a class doesn't necessarily mean you *should* use them inside the class. – Rob Kennedy Sep 27 '13 at 22:06
  • This question is very clear to me. I understand it as "while coding the implementation of an object, is it okay to read/write private fields which are wrapped behind published properties?" But I do agree this is an opinionated question, and am voting to close as so. – Jerry Dodge Sep 28 '13 at 01:39
  • @JerryDodge I am glad the question is clear, however if you need to vote to close because you feel the question is opinionated then that was not my intention. I was looking for a definitive answer/general consensus as to whether or not referencing to property names rather than the field names is bad. –  Sep 28 '13 at 09:13

1 Answers1

6

The purpose of a property is not to allow access to class data outside of the class per se.
This could be easily done by declaring your member data as public.

The purpose of properties is to facilitate good OOP.
The following points illustrate the concept.

Side effects
The main purpose of properties is to hide the implementation details of your class and allow 'side-effects' when setting properties.
This is obvious in the VCL where changing the height property will automatically change the window's appearance due to the side effects coded in the SetHeight Setter.
This is part of the OOP concept of information hiding.

These side effects are useful whether you are inside you class or not.
The other useful aspect kicks in when your class or one of its descendants changes the behavior of the property; adding a side-effect where there was none before.
If your old code inside the original class fiddles with the fields directly these side-effects will not trigger, breaking the change inside the descendant.

Rule of thumb: side effects
Always use the property, unless you explicitly want to prevent a side-effect from triggering. !!Remember getters can have side-effects as well.

Implementation hiding
Sometimes the fields are not a direct translation of their appearance in the property.
Or you may want to change the implementation under the hood, but keep the properties the same.
Again in this case you may want to hide these details in your own class as well, so that descendant classes do not break.
e.g. if you have your storage implemented as a red/black tree with pointers you want to minimize the impact to the rest of the routine when you decide to switch to an array based offset structure.

Rule of thumb: implementation hiding
Only access the fields directly in these routines that deal directly with the data.
Limit the number of those routines by putting general purpose routines in place, like: locaters, iterators etc.

Johan
  • 74,508
  • 24
  • 191
  • 319
  • Thanks for the clarification and detailed answer. Now I must go back and check I am using field names.. –  Sep 28 '13 at 12:09
  • An easy way to check what you're using: Change the declared name of the field and recompile. The compiler will show you every place you use the old name. Go through the list and change your code to use either the new field name or the property name. When you're finished, use the *rename* refactoring tool to restore the original field name at all the places you're still using the field instead of the property. – Rob Kennedy Oct 01 '13 at 13:58