Great Video On Delphi Form/Code Separation

Great Video On Delphi Form/Code Separation
Code Rage9 Video by David Schwartz
http://bit.ly/1xG7NQC
#delphi

Comments

  1. Schrott!

    all is string?!?


    a type, is a type, is a type!

    ReplyDelete
  2. Nice articles. Hadn't seen those.
    One question, Gunny - why the bit.ly link, and not just the actual link? That would give a nice preview in the post as well.

    ReplyDelete
  3. I just started using twitter and it's become a habit. I'll keep that in mind going forward. Thanks Lars.

    ReplyDelete
  4. Ah, that explains it :)
    I do have a Twitter account as well, but I largely find Twitter to have an intolerable content to noise ratio :P

    ReplyDelete
  5. Twitter probably does. However, I keep coming back to...
    "The unexamined life is not worth living."
    Socrates 469 BC-399 BC

    ReplyDelete
  6. In his times, people gathered to "tweet" :)

    ReplyDelete
  7. Hey, thanks guys! What did you find most informative about it? Anything you'd like to see elaborated upon?

    ReplyDelete
  8. David Schwartz I'd like to know what you mean by Lamdas and Closures in simple terms that Forrest Gump would understand.

    ReplyDelete

  9. There's some debate on the distinction between lambdas and closures, even though there appears to be lots of clear academic distinctions. It's the general concept that's most important here, not the more subtle differences.

    Basically, what I'm pointing at in the presentation is the use of anonymous methods passed as parameters to other methods. Call-backs as it were.

    It's easier to pass them as parameters inline than to declare them separately then pass them by reference. And it's easier to read the code that way as well.

    They can feel a little awkward when you first start using them. It helped me a lot to read several books on Java 8 to get the gist of how broadly they can be used. Delphi's libraries don't do squat with them. You need to look elsewhere for examples. (Frankly, I don't know what possessed the Delphi language team to add them to the language, because they don't seem to be leveraged at all, at least in the public RTL interfaces. Maybe inside where they're not visible without a lot of digging.)

    ReplyDelete
  10. Lambda

    From Wikipedia: In computer programming, an anonymous function (also function literal or lambda abstraction) is a function definition that is not bound to an identifier.

    That's a solid definition for lambda.

    Closure

    From Wikipedia: In programming languages, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non-local variables (also called free variables or upvalues) of that function.[1] A closure—unlike a plain function pointer—enables a function to access those non-local variables even when invoked outside its immediate lexical scope.

    Again, a pretty solid definition.

    ReplyDelete
  11. This is nice, but it's not terribly helpful for people who are just trying to get the gist of why you'd use anonymous methods as inline "parameters" to other method calls in Delphi rather than declare them separately and pass them as method pointers the way standard event handling works.

    The subtlety is in how you access variables from inside the bodies of the anonymous call-back methods on the client side, and has nothing to do with WHY or HOW you'd use inline call-back methods in the first place. It's irrelevant in the context of call-back methods that follow the pattern of standard event handlers, which can be confusing to people who think it's just a simple matter of substituting an out-of-line method for an in-line method.

    Honestly, I learned more reading about this topic in a couple of Java 8 books than anything I found discussing Delphi. It's sad that we have to go to a third-party source to learn details about how things work in Delphi.

    ReplyDelete
  12. David Schwartz Michael asked what they were.

    ReplyDelete
  13. It seems you mostly can find anonymous methods in the newer parts of the XE7 lib sources, but there is a few in the modernized rtl/common units as well.

    type = reference to function - 59 occurrences
    data\datasnap\Datasnap.DSClientRest.pas
    data\datasnap\Datasnap.DSSession.pas
    data\dbx\Data.DBXJSONReflect.pas
    data\rest\REST.JsonReflect.pas
    databinding\components\Data.Bind.Components.pas
    databinding\components\Data.Bind.ObjectScope.pas
    databinding\engine\System.Bindings.EvalProtocol.pas
    databinding\engine\System.Bindings.EvalSys.pas
    databinding\engine\System.Bindings.Methods.pas
    databinding\engine\System.Bindings.Outputs.pas
    databinding\graph\GraphView.pas
    fmx\FMX.Dialogs.pas
    fmx\FMX.Types.pas
    internet\Web.WebFileDispatcher.pas
    rtl\common\System.Classes.pas
    rtl\common\System.Generics.Collections.pas
    rtl\common\System.Generics.Defaults.pas
    rtl\common\System.IOUtils.pas
    rtl\common\System.Sensors.pas
    rtl\common\System.Zip.pas
    rtl\sys\System.SysUtils.pas
    vcl\Vcl.Dialogs.pas


    type = reference to procedure - 81 occurrences
    Experts\ExpertsModuleCreators.pas
    data\cloud\DSAzDlgPutBlockList.pas
    data\cloud\DSAzure.pas
    data\cloud\DSAzureBlob.pas
    data\cloud\de\DSAzDlgPutBlockList.pas
    data\cloud\fr\DSAzDlgPutBlockList.pas
    data\cloud\ja\DSAzDlgPutBlockList.pas
    data\datasnap\Datasnap.DSClientRest.pas
    data\datasnap\Datasnap.DSCommon.pas
    data\datasnap\Datasnap.DSServer.pas
    data\datasnap\Datasnap.DSService.pas
    data\datasnap\Datasnap.DSSession.pas
    data\dbx\Data.DBXCommon.pas
    data\dbx\Data.DBXJSONReflect.pas
    data\ems\EMS.ResourceTypes.pas
    data\rest\REST.Backend.EMSApi.pas
    data\rest\REST.Backend.KinveyApi.pas
    data\rest\REST.Backend.ParseAPI.pas
    data\rest\REST.Backend.ServiceTypes.pas
    data\rest\REST.JsonReflect.pas
    databinding\components\Data.Bind.Components.pas
    databinding\engine\System.Bindings.CustomScope.pas
    databinding\engine\System.Bindings.EvalProtocol.pas
    databinding\engine\System.Bindings.Outputs.pas
    fmx\FMX.Controls.pas
    fmx\FMX.Dialogs.pas
    fmx\FMX.Helpers.Android.pas
    fmx\FMX.Platform.pas
    rtl\common\System.Actions.pas
    rtl\common\System.Classes.pas
    rtl\common\System.Messaging.pas
    rtl\common\System.Rtti.pas
    rtl\common\System.Threading.pas
    rtl\common\System.Win.ComObj.pas
    rtl\sys\System.SysUtils.pas
    vcl\Vcl.Touch.GestureCtrls.pas

    ReplyDelete
  14. An example of when anonymous methods can be better than procedure of object:

    I was cussing at some TFDScript FireDAC event handlers the other day - which are procedure of object - as I didn't want to create an event handler in my FireDAC wrapper base class, as it only would be used by a single specific method, related to running scripts.  The event handler in question captures spool output from the "db console" when running a script.

    I ended up creating a proxy object in the descendent class, which had an anon method property, which I could pass along with the descendent class.  If the handler had been reference to procedure, I wouldn't have had to do this proxying.

    (The code is abbreviated)

      TScriptIntercept = class
      private
        FOnOutput: TAnonParamProc;
      public
         procedure OnScriptSpoolPut(AEngine: TFDScript; const AMessage: string;  AKind: TFDScriptOuputKind);
         property OnOutput: TAnonParamProc read FOnOutput write SetOnOutput;
      end;

    procedure TScriptIntercept.OnScriptSpoolPut(AEngine: TFDScript;
      const AMessage: string; AKind: TFDScriptOuputKind);
    begin
      FOnOutput(AMessage);
    end;

    function TPSDDatabase_FD.ExecuteScript(const aSQL: TStrings;
      const aOnOutput: TAnonParamProc): Integer;
    var
      rc : Integer;
      Script: TFDScript;
      ScriptInterceptor : TScriptIntercept;
    begin
      Script := CreateScript;
      ScriptInterceptor := TScriptIntercept.Create;
      ScriptInterceptor.OnOutput := aOnOutput;
      Script.OnSpoolPut := ScriptInterceptor.OnScriptSpoolPut;
    ...

    ReplyDelete

Post a Comment