Jump to content
Ian Branch

Getters & Settters??

Recommended Posts

21 minutes ago, Ian Branch said:

Why??

I mean, is this just fancy code for the sake of it?? 

Dalija explained why. So that there's no scope for essential arguments not to be set. To make it clear to the caller what must be provided by them. 

Share this post


Link to post
24 minutes ago, Attila Kovacs said:

case TSomeValueReturningForm.Create(Self).ShowForm(lStringVar) of mrOk: DoSomething(lStringVar); else Whatever... end;

This leaks the instance 

Share this post


Link to post
3 hours ago, Attila Kovacs said:

bullshit

The form isn't destroyed until Self is. But once ShowModal has returned the form can never be seen again. That's a leak. 

 

Share this post


Link to post
6 hours ago, David Heffernan said:

The form isn't destroyed until Self is. But once ShowModal has returned the form can never be seen again. That's a leak. 

 

We are not discussing here how to free a form, I'm always using caFree which is not part of the question.

Share this post


Link to post

Constructor approach is more error-proof (you unlikely forget to assign some necessary arguments as you can with properties) but is very non-extendable. If there could appear new values to set, argument list grows and becomes ugly, just like WinAPI's CreateProcess

Share this post


Link to post
4 hours ago, Fr0sT.Brutal said:

but is very non-extendable

Just add more arguments. If they need to be provided, then there's no shortcut.

 

You could make the point that when looking at the arguments at the call site you don't see the name of the parameter, but that's something that the tooling should provide you.

Share this post


Link to post
var  Sform, RForm: TfrmView;

procedure TfrmMain.btnPutMemoClick(Sender: TObject);
begin
  TfrmView.ianShowMessage(SForm, Messages.Lines, Formclick);
  LogForm(Sender);
end;

procedure TfrmMain.btnPutListClick(Sender: TObject);
begin
  TfrmView.ianShowMessage(RForm, listbox1.Items, LogForm);
end;

///    showmessage only
procedure TfrmMain.Button2Click(Sender: TObject);
begin
  TfrmView.ianShowMessage(RForm, listbox1.Items, nil);
end;

///   singleton
procedure TfrmMain.Button4Click(Sender: TObject);
begin
  TfrmView.ianShowMessageSI(Messages.Lines,button3click)
end;

   I noticed that prefacing var for the form argument helps out.  This code also shows a "callback" being passed,

   Adding a FMX style list box and a que should make nice media player.

         

 

class procedure TfrmView.ianShowMessage(var auxForm: TfrmView;
                                 Strs: TStrings; CallBacK: TnotifyEvent);
begin
  if not assigned(callBack) then
     begin
      ShowMessage(Strs.text + #13#10);
      exit;
    end;

  if not assigned(auxForm) then
    begin
      auxForm := TfrmView.Create(Application); //
      auxform.cursor := crCross;
      auxform.Button1.onClick := CallBack;
    end;

  with auxForm do
    begin
      Memo1.Lines.SetStrings(Strs);
      {
        Enhanced ShowMessage gives console operators a 'log view'
         case
           xxx: sms Ian please open old DB for
           xxx: note this report only covers today
           xxx: note that xxxx again
           xxx: Showmodal;
          }
      Show;
    end;
end;

var SMlogger: TfrmView;
class procedure TfrmView.ianShowMessageSI(Strs: TStrings;
  CallBacK: TnotifyEvent);
begin
  ianShowMessage(SMlogger, Strs, CallBacK);
end;

  

Share this post


Link to post
13 hours ago, David Heffernan said:

Just add more arguments.

Many style guides advice against more than 3 arguments. My personal limit is, I think, 5 args.

Share this post


Link to post
31 minutes ago, Fr0sT.Brutal said:

Many style guides advice against more than 3 arguments. My personal limit is, I think, 5 args.

Seems like dogma to me. 

 

Are you really saying that if a method uses more than 5 values of input data then it needs to be passed via properties rather than arguments? Many problems with that. Let's consider just one, thread safety. 

  • Like 2

Share this post


Link to post
9 minutes ago, David Heffernan said:

Seems like dogma to me. 

No, just a personal preference. Of course I always try to find balance between object creation atomicity and c-tor complexity. On the one side is an object requiring many properties assigned just to act properly, on the other is CreateProcess. Anyway it's a question of coding style.

9 minutes ago, David Heffernan said:

Are you really saying that if a method uses more than 5 values of input data then it needs to be passed via properties rather than arguments?

Style guides recommend wrapping values into a record. However I don't like it much because Pascal's record filling is too verbose compared to, say, JS

 

Edited by Fr0sT.Brutal

Share this post


Link to post

I prefer my constructors without arguments.

More abstract / generics friendly.

 

Ref. an earlier comment - I am not so fond of the (ab)use of overload either.  It is great for dealing with type translation methods - but multiple overloaded constructors could be very confusing before LSP and inline documentation actually became helpful again.

 

As for number of arguments to a method - as many as it takes, but more than five is pretty rare.

Share this post


Link to post

I am a layman. I remember that the number of arguments 3 is related to memory management. I hope I'm not wrong. It is one "block".
I don't know if this argument is still relevant today. I would like to know the answer, the opinion.
Such a VirtualStringTree usually has functions with 7 parameters. All static analyzers (FixInsight, PAL) screamed at them. So I turned off this check.

Share this post


Link to post
35 minutes ago, Stano said:

I am a layman. I remember that the number of arguments 3 is related to memory management. I hope I'm not wrong. It is one "block".

No, I don't think so.

Share this post


Link to post
36 minutes ago, Lars Fosdal said:

I prefer my constructors without arguments.

More abstract / generics friendly.

I don't really understand this. If you need to make multiple instances of the same class that are to be initialised with different values, how are you going to do that? Why does doing that initilisation in a separate stage help? 

Share this post


Link to post

@David Heffernan - I rarely make classes that have so few fields that they are passed in the constructor. Most of my instance data are retrieved from database tables, and each class knows what fields to retrieve (or store).  The generic container instantiates the class, the instances fill themselves from the db query.  

 

I also have polymorphic classes where each element requires different initializations, which firstly are done by default initializations in the class create, and then secondarily from attributes before the declaration of the class instance reference field. 

I use this mechanism to build grids in code - and not in design mode. Again, the inits and attributes are the defaults.  Overrides are then applied from stored settings.

  • Like 1

Share this post


Link to post
1 hour ago, Stano said:

I am a layman. I remember that the number of arguments 3 is related to memory management.

Memory management has nothing to do with number of parameters in constructors.

 

There are other reasons why having too many parameters is considered "bad", but those are all in line that having too many parameters can be indication that your class is doing too much - violates Single Responsibility Principle.

 

In real life, having classes and functions that require a lot of parameters and that are not in violation of SRP, nor can be adequately split, are quite common, and often workarounds for solving such "issues" are more convoluted than having few parameters over the top.

 

If there is really a need to have class fully initialized during construction and too many parameters poses an issue that cannot be meaningfully solved by splitting the class, then Builder pattern can be suitable solution. There is usually a lot of repetitive code involved in writing a Builder class, so it is useful only if you need to construct particular class in plenty of places across your application.

 

The main problem with many parameters, especially when they are of same type, is that you can easily pass the wrong data to wrong parameter. This could be solved on IDE level, by showing names of the parameters as hints within code - not visible outside the IDE,, so calling the constructor or function would look like 

 

TPerson.Create(AFirstName: 'John', ALastName: 'Doe');

Another similar feature on language level are named parameters, where you can or must explicitly write parameter name in the code, similar to the above.

 

  • Like 1

Share this post


Link to post
39 minutes ago, Dalija Prasnikar said:

Memory management has nothing to do with number of parameters in constructors.

Probably he meant that in case of many parameters they are pushed to stack not to registers. Stack is somewhat related to memory 🙂

Edited by Fr0sT.Brutal

Share this post


Link to post
1 hour ago, Fr0sT.Brutal said:

Probably he meant that in case of many parameters they are pushed to stack not to registers. Stack is somewhat related to memory 🙂

Uh.... this is such far fetched speed optimization that it is not even worth thinking about.

 

And if you start measuring particular solutions, you may easily find that you will not get very far with them.

Edited by Dalija Prasnikar

Share this post


Link to post
2 hours ago, Fr0sT.Brutal said:

Probably he meant that in case of many parameters they are pushed to stack not to registers. Stack is somewhat related to memory

If the information needs to be transmitted, it has to get there somehow.

  • Like 1

Share this post


Link to post
3 hours ago, Lars Fosdal said:

I rarely make classes that have so few fields that they are passed in the constructor. Most of my instance data are retrieved from database tables, and each class knows what fields to retrieve (or store).  The generic container instantiates the class, the instances fill themselves from the db query.  

 

5 hours ago, Lars Fosdal said:

I prefer my constructors without arguments.

More abstract / generics friendly.

 

Hmm, not quite the same thing

Share this post


Link to post
4 minutes ago, David Heffernan said:

Hmm, not quite the same thing

True.  But if I need multiple constructors with different arguments to set up a class before use - is that class overly complicated and should it be broken down into a hierarchy?

  • Like 1

Share this post


Link to post
14 minutes ago, Lars Fosdal said:

True.  But if I need multiple constructors with different arguments to set up a class before use - is that class overly complicated and should it be broken down into a hierarchy?

Who said anything about needing multiple overloaded constructors? 

Share this post


Link to post

Look further back in the thread for constructor overloading.

 

It seems like I didn't understand your "not quite the same thing" comment. Care to elaborate?

Share this post


Link to post
14 minutes ago, Lars Fosdal said:

Look further back in the thread for constructor overloading.

 

It seems like I didn't understand your "not quite the same thing" comment. Care to elaborate?

The original question concerned code that called a constructor, then set a bunch of properties. I said, it may be better to pass that information as arguments to the constructor. I'm not proposing overloading anything.

 

I feel that you are using a specific code style from your code base to make a general point that is not valid. I understand why you might have written a bunch of classes to be parameterless and then read state from a DB.  But that's really specific to your code base.  Why is it bad to pass arguments to constructors?  I see absolutely no reason at all to make a blanket recommendation that constructors should not have parameters.

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

×