David Heffernan 2345 Posted November 6, 2022 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
David Heffernan 2345 Posted November 6, 2022 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
Attila Kovacs 629 Posted November 6, 2022 Just now, David Heffernan said: This leaks the instance bullshit Share this post Link to post
David Heffernan 2345 Posted November 7, 2022 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
Attila Kovacs 629 Posted November 7, 2022 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
Fr0sT.Brutal 900 Posted November 7, 2022 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
David Heffernan 2345 Posted November 7, 2022 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
Pat Foley 51 Posted November 7, 2022 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
Fr0sT.Brutal 900 Posted November 8, 2022 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
David Heffernan 2345 Posted November 8, 2022 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. 2 Share this post Link to post
Fr0sT.Brutal 900 Posted November 8, 2022 (edited) 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 November 8, 2022 by Fr0sT.Brutal Share this post Link to post
Lars Fosdal 1791 Posted November 8, 2022 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
Stano 143 Posted November 8, 2022 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
David Heffernan 2345 Posted November 8, 2022 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
David Heffernan 2345 Posted November 8, 2022 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
Lars Fosdal 1791 Posted November 8, 2022 @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. 1 Share this post Link to post
Dalija Prasnikar 1396 Posted November 8, 2022 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. 1 Share this post Link to post
Fr0sT.Brutal 900 Posted November 8, 2022 (edited) 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 November 8, 2022 by Fr0sT.Brutal Share this post Link to post
Dalija Prasnikar 1396 Posted November 8, 2022 (edited) 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 November 8, 2022 by Dalija Prasnikar Share this post Link to post
David Heffernan 2345 Posted November 8, 2022 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. 1 Share this post Link to post
David Heffernan 2345 Posted November 8, 2022 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
Lars Fosdal 1791 Posted November 8, 2022 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? 1 Share this post Link to post
David Heffernan 2345 Posted November 8, 2022 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
Lars Fosdal 1791 Posted November 8, 2022 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
David Heffernan 2345 Posted November 8, 2022 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