pcoder 5 Posted August 16 procedure TObj.run; var r: TRecord; begin ...; processRecord( r); ...; end; ProcessRecord is a method and contains many nested calls (more methods). The issue is that many methods would need an additional parameter (very cumbersome). Therefore an alternative is wanted. Object-field FR (PRecord) is a pointer (rather than record) to reduce memory outside of runs. is there any preference for one of them? procedure TObj.run2; begin new( FR); ...; processRecord; ...; dispose(FR); FR := nil; end; procedure TObj.run3; var r: TRecord; begin FR := @r; ...; processRecord; ...; FR := nil; end; Share this post Link to post
Remy Lebeau 1642 Posted August 16 (edited) I would choose the latter. No need to allocate memory dynamically unless the record instance needs to live after TObj.run3() exits. But, if you have a lot of methods of TObj that are acting on the record then they should instead be methods of TRecord itself. Consider refactoring your code to make it cleaner. Edited August 16 by Remy Lebeau 1 Share this post Link to post
A.M. Hoornweg 159 Posted Thursday at 07:37 AM (edited) May I suggest "fluent interfaces" as an alternative to nested calls. Instead of using a record like a dumb data store that is only manipulated from the outside, you can put the methods that fiddle with the record's contents directly into the record itself and thus keep the code and the data closely together. Also, this enables one to use a so-called "fluent interface". Example: This is an example of a record that contains just one integer member, "data". In real life, you can make the record as complex as you want. type pMyrecord=^tMyRecord; tMyRecord=Record data:integer; Function Reset:pMyrecord; Function Add (x:integer):pMyrecord; Function Multiply (x:integer):pMyrecord; Function Divide (x:integer):pMyrecord; End; As you can see, all the methods in this record return a pointer, which simply points to the record itself. That is the "secret sauce" one needs to implement fluent interfaces. function tMyRecord.Add(x: integer): pMyrecord; begin data:=data+x; result:=@self; end; function tMyRecord.Divide(x: integer): pMyrecord; begin data:=data div x; result:=@self; end; function tMyRecord.Multiply(x: integer): pMyrecord; begin data:=data*x; result:=@self; end; function tMyRecord.Reset: pMyrecord; begin data:=0; result:=@self; end; Now the cool thing: All these methods can be concatenated and will be processed left-to-right. This produces very legible and compact code: procedure Test; var x:tmyrecord; begin x.reset.add(12).multiply(4).divide(2); end; (edit) Note that I didn't do a single heap allocation here, never manually passed the record as a parameter and never did a nested call. The data lives on the stack. If the record contains managed objects such as strings, these are disposed of automatically. Edited Thursday at 07:48 AM by A.M. Hoornweg 2 Share this post Link to post