Jump to content

Stefan Glienke

Members
  • Content Count

    1498
  • Joined

  • Last visited

  • Days Won

    152

Posts posted by Stefan Glienke


  1. I am not going to argue with you why mutable(!) global state is bad because a ton of respected people in the software development community have already proven that.

    As I said a singleton can be the easy solution - that does not make it a good one.

     

    Putting any code into an otherwise no or hard testable software component is only a crutch - there are ways to design software to be testable by default which does not only make it easily testable but also more robust and maintainable.

    Just read "Clean Code" and/or watch "Clean code talks" on Youtube.

     

    Also fwiw there is a difference between Singleton as in the GoF Singleton (ensuring that there is only one instance and preventing everyone from ever instantiating a second instance of that) and "singletoness" (establishing the contract of only having one instance but not preventing anyone from instantiating one on its own and inject it somewhere). Even in DI driven architectures there are singletons, but it is controlled via the DI system that there is only one instance being created and passed around. That decouples any consumer from the actual implementation of that singleton and makes it easily testable/mockable (see "seam")


  2. Googling for this error and drf yields this:

     

    Quote

    Question:
    I just ran in a problem rebuilding the latest version of the TMultiLang package.
    This is done by a batch file which invokes the commandline compiler DCC32.EXE
    I got this error message:

    
    E:\Projects\MultiLang\mle>dcc32 multilang.dpk
    Delphi for Win32 Version 10.0 Copyright (c) 1983,97 Borland International
    MultiLang.dpk(40) Fatal: Could not create output file 'MultiLang.drf'

    What is this DRF file? Why did I get this message?

     

    Answer:
    When you compile with packages, you can specify which packages should be considered for linkage. The package requirements of the project get stored into a temporary Windows resource file with a .DRF extension.

    In my case I got this error message from DCC32 because my environment variable %TEMP% pointed to an not existing directory after I had cleaned up too much 

    Source


  3. It seems indeed as if the TIntfFlag enum was never extended since Delphi6 (I think that was when interface RTTI was introduced) - I can confirm that at least since XE an interface type with $M+ gets a fourth flag (lets call it ifHasMethodInfo) set.

    If the type is an anonymous method type (see https://stackoverflow.com/q/49950534/587106) then there is a 7th enum value in the set. The situations where bit 5 and 6 are set are unknown to me.

     

    You might want to file an issue in QP about this.

     

    @Remy Lebeau Your diagnosis is still wrong - if the debugger shows

    Quote

    [(out of bound) 3]

    then that means it has the 4th bit set.

     

    I can confirm my findings with this code:

     

    uses
      SysUtils,
      Rtti;
    
    type
      TIntfFlagEx = (ifHasGuid, ifDispInterface, ifDispatch, ifMethodInfo, ifUnknown, ifUnknown2, ifAnonymousMethod);
      TIntfFlagsEx = set of TIntfFlagEx;
    
      {$M+}
      IFoo = interface
        ['{35CFB4E2-4A13-48E9-8026-C1558001F4B7}']
        procedure Main;
      end;
      {$M-}
    
      {$M+}
      IBar = interface(TProc)
        ['{AB2FEC1A-339F-4E58-B3DB-EC7B734F461B}']
      end;
      {$M-}
    
      {$M+}
      TMyProc = reference to procedure;
      {$M-}
    
    procedure PrintIntf(typeInfo: Pointer);
    var
      context: TRttiContext;
      rttiInterface: TRttiInterfaceType;
      flags: TIntfFlagsEx;
    begin
      rttiInterface := context.GetType(typeInfo) as TRttiInterfaceType;
      flags := TIntfFlagsEx(rttiInterface.IntfFlags);
      Writeln(rttiInterface.Name, ' ', TValue.From(flags).ToString);
    end;
    
    begin
      PrintIntf(TypeInfo(IInterface));
      PrintIntf(TypeInfo(IInvokable));
      PrintIntf(TypeInfo(IFoo));
      PrintIntf(TypeInfo(TProc));
      PrintIntf(TypeInfo(TFunc<Integer>));
      PrintIntf(TypeInfo(TMyProc));
      PrintIntf(TypeInfo(IBar));
      Readln;
    end.

    prints this:

     

    IInterface [ifHasGuid]
    IInvokable [ifMethodInfo]
    IFoo [ifHasGuid,ifMethodInfo]
    TProc [ifAnonymousMethod]
    TFunc<System.Integer> [ifAnonymousMethod]
    TMyProc [ifMethodInfo,ifAnonymousMethod]
    IBar [ifHasGuid,ifMethodInfo,ifAnonymousMethod]

     


  4. Ah, I see now, they are all hidden in that innocently looking TestParse and TestEmit methods - was expecting to see them more fine grained :)

     

    I have some suggestions for some possible low level optimizations (for example eliminating some unnecessary code from function prologues and epilogues caused by usually not raised exceptions but the fact the exception creation code is directly coded into the methods (and in fact is repeated multiple times) - will file a PR.

    • Like 2
    • Thanks 1

  5. function _GetMem(Size: NativeInt): Pointer;
    begin
      if Size <= 0 then
        Exit(nil);
      Result := MemoryManager.GetMem(Size);
      if Result = nil then
        Error(reOutOfMemory);
    end;
    function GetMemory(Size: NativeInt): Pointer; cdecl;
    begin
      Result := MemoryManager.GetMem(Size);
    end;

    Do you see the difference?

     

    Also GetMem is an intrinsic that maps to System._GetMem 


  6. uses
      Spring.VirtualClass;
    
    procedure NotifyFree(const Self: TObject);
    var
      freeInstance: TFreeInstance;
    begin
      freeInstance := GetClassData(Self.ClassParent).FreeInstance;
      Writeln('Object of class ', Self.ClassName, ' destroyed');
      freeInstance(Self);
    end;
    
    var
      vc: TVirtualClasses;
      o: TObject;
    begin
      vc := TVirtualClasses.Create;
      try
        o := TObject.Create;
        try
          vc.Proxify(o);
          GetClassData(o.ClassType).FreeInstance := NotifyFree;
        finally
          o.Free;
        end;
      finally
        vc.Free;
      end;
    end.

     

    • Like 2
    • Thanks 3

  7. I know the repositories get maintenance and update for new Delphi releases but I wonder if there is actually a release planned.

    Last JCL release is 2.7 from september 2015 which probably does not support any Delphi version after that - last JVCL release is 3.49 also from september 2015.

     

    Since then we are in limbo state working with some master state - this is kinda far from optimal.


  8. Anonymous methods normally don't appear in the procedure list (which I don't mind - so even if you decide to list them in the future, please make that optional).

    However when you have a function/procedure does not have any arguments and you don't write () they appear in the list:

     

    procedure Main;
    var
      f: TFunc<Integer>;
      p: TProc;
      f2: TFunc<Integer,Integer>;
      p2: TProc<Integer>;
    begin
      f := function: Integer begin end; // appears as empty entry in procedure list
      f := function(): Integer begin end; // does not appear
    
      p := procedure begin end; // appears as "begin end" in procedure list
      p := procedure() begin end; // does not appear
    
      p2 := procedure(x: Integer) begin end; // does not appear
    
      f2 := function(x: Integer): Integer begin end; // does not appear
    end;


     


  9. Slap your coworker because he obviously did not resolve a conflict and just commited this (this is git 101).

    This is how git annotates the code when there is a conflict and usually you then call git mergetool (or similar) or just use the resolve conflict button in whatever git ui client you are using.

     

    Remove lines 2, 4 and 6 and decide if you want to keep 3 or 5

×