Jump to content

Lars Fosdal

Administrators
  • Content Count

    3539
  • Joined

  • Last visited

  • Days Won

    118

Everything posted by Lars Fosdal

  1. Can't you create a view that do the convert for you, so that you don't have to fiddle with the conversions in that SQL?
  2. https://stackoverflow.com/questions/38394002/how-to-format-date-on-ms-sql-server-2008
  3. Lars Fosdal

    procedure of class

    @Kas Ob. I agree on splitting the devices into separate units, but for sake of the example to a minimum, I didn't show that. Ref 1) - Master in TBaseController is in principle the core factory, but could be separate. Ref 4) - Multiple interfaces is defintively an option. A capability discovery mechanism is a good idea. The main point of my example was to show a method for avoiding passing unsafe pointers to methods. That said, passing objects is only safe as long as you are in full control of the lifespan of, and access to, said objects. Using class types (TMyClassType = class of TMyType) and encapsulation is a good way of handling polymorphic instantiation in a reasonably tidy way. Using libs like f.x. Primož Gabrijelčič's OmniThreadLibrary really helps solving common threading challenges. Gotta love thread safe queues.
  4. Lars Fosdal

    procedure of class

    @JackT - I've attempted an over-simplified draft of how I would envision doing this. It allows multiple communication methods, and multiple controllers, but I've left out the configuration loading and command/result passing. I'd use input/output "mailbox queues" as those are the simplest to make thread safe. program DynamicCommsClass; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Generics.Defaults, Generics.Collections; type TSignature = string; IDeviceInterface = interface(IInterface) ['{C8D5A4A7-A153-4962-8F89-980825B0E503}'] function FetchSignature: TSignature; function Verb1: integer; function Verb2: integer; end; TDeviceObject = class(TInterfacedObject, IDeviceInterface) // contains relevant comms class (serial, tcp, REST, etc) function FetchSignature: TSignature; virtual; function Verb1: Integer; virtual; function Verb2: Integer; virtual; end; TBaseController = class(TObject) type TBaseControllerType = class of TBaseController; TControllerDictionary = class(TDictionary<TSignature, TBaseControllerType>); class var Master: TControllerDictionary; // a complete master list of known controllers protected Device: IDeviceInterface; public class constructor InitClass; class destructor UnInitClass; class function Signature: TSignature; virtual; class procedure RegisterControllers(const aControllerList: Array of TBaseControllerType); class function FindController(const aSignature: TSignature): TBaseControllerType; function Connect: TBaseController; virtual; constructor Create; virtual; procedure CreateDeviceObject; virtual; procedure LoadConfiguration; virtual; function Verb1: Integer; virtual; function Verb2: Integer; virtual; end; TThisController = class(TBaseController) public constructor Create; override; class function Signature: TSignature; override; end; TThatController = class(TBaseController) constructor Create; override; class function Signature: TSignature; override; end; { TDeviceObject } function TDeviceObject.FetchSignature: TSignature; begin // Get the signature from the device end; function TDeviceObject.Verb1: Integer; begin // exect command 1 on the device end; function TDeviceObject.Verb2: Integer; begin // exect command 2 on the device end; { TBaseController } constructor TBaseController.Create; begin Inherited; CreateDeviceObject; LoadConfiguration; end; procedure TBaseController.CreateDeviceObject; begin Device := TDeviceObject.Create; end; class destructor TBaseController.UnInitClass; begin Master.Free; end; class constructor TBaseController.InitClass; begin Master := TControllerDictionary.Create(11); // or whatever prime size needed end; class procedure TBaseController.RegisterControllers( const aControllerList: Array of TBaseControllerType); begin for var Controller in aControllerList do Master.TryAdd(Controller.Signature, Controller); end; class function TBaseController.FindController( const aSignature: TSignature): TBaseControllerType; begin if not Master.TryGetValue(aSignature, Result) then raise Exception.Create(Format('Signature %s not recognized.', [aSignature])); end; class function TBaseController.Signature: string; begin Result := 'Default'; end; function TBaseController.Connect: TBaseController; var Sig: TSignature; begin Sig := Device.FetchSignature; if Sig = Self.Signature then Result := Self else begin var ControllerType := FindController(Sig); Result := ControllerType.Create; end; end; procedure TBaseController.LoadConfiguration; begin // from somewhere end; function TBaseController.Verb1: Integer; begin Result := Device.Verb1; end; function TBaseController.Verb2: Integer; begin Result := Device.Verb2; end; { TThisController } constructor TThisController.Create; begin inherited; end; class function TThisController.Signature: TSignature; begin Result := 'ThisControllerSign'; end; { TThatController } constructor TThatController.Create; begin inherited; end; class function TThatController.Signature: TSignature; begin Result := 'ThatControllerSign'; end; // ------- procedure ThreadExecute; var InitialController, Controller: TBaseController; begin InitialController := TBaseController.Create; Controller := InitialController.Connect; if InitialController <> Controller then InitialController.Free; try // while not Terminated // do begin // Overly simplified - but basically fetch from input queue to decide what to process // Controller.Verb1; // Controller.Verb2; // Sleep(1000); // end; finally Controller.Free; end; end; begin TBaseController.RegisterControllers([TThisController, TThatController]); try ThreadExecute; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
  5. Lars Fosdal

    Using "Claude Code" with Delphi

    Translation to Delphi might work - as long as the AI knows enough Delphi syntax, conventions and libs. Based on what people say about AI code gen "inventing" non-existant functions, I am not so sure it does. RACs are one of the suggested next step paradigms. Even RACs are quite limited, being based on a library of known algorithms - which of course may not be all-encompassing.
  6. Lars Fosdal

    Using "Claude Code" with Delphi

    I've tried MS CoPilot and Google Gemini. Both are good for condensing documentation and explaining code. Writing code - not so much. I had a couple of PS scripts that I Gemini if it could optimize them to improve performance, and it sort of did, but it also changed the output from the script significantly . What helped the most, is that it showed me a bag of tricks for creating and updating structures that I didn't know of, and some new PS functions I had never used, which I could easily adopt to improve performance all over. To me, AI can be a sidekick for improving code, but I would not lean on it for creating new code yet. The amount of Delphi material available for it to learn from, is quite small compared to modern web stuff - hence I don't expect it to improve until the algorithms that AI picks up become actual abstract algorithm models in its "mind" and those models can be applied to various output languages, instead of just parroting of code it gleaned elsewhere. The way I see it, AI needs to mature past VLLMs+RAGs and use RACs (or whatever is next) to achieve algorithmic understanding before it can produce quality code. We are not there yet.
  7. The SoftaCom posts appear to be purely marketing 😞
  8. Using AI from Delphi IDE or a Delphi app is a general or third party component thing. Tag posts with AIUsage and ComponentName. Same for using AI for coding with various agents. Tag posts with AICoding and AgentName.
  9. Lars Fosdal

    procedure of class

    @JackT So you retrieve a signature from the hardware, and want to have custom classes, either descending from a single parent (with children overriding virtual methods) - or - implementing a common interface (if the classes need to have different parents) - and create device specific class instances that do the appropriate software operations on specific hardware? Sounds to me that you need a Factory that produces your class depending on the signature - where each class register itself with the corresponding signature(s). It would be safer to pass an instance of the class, than a reference to a function of the class.
  10. Lars Fosdal

    Minimum Viable Product (MVP)

    The legal parts consists among other things, the requirement to keep an archive of issued invoices, shipping notifications, delivery receipts, etc. The period of time the documents need to be kept is dependant on national law requirements. Then there is the hell that is tax rules that change over time and the chores of keeping up with the changes. In most situations, I'd say you would be better off buying an existing solution that covers your requirements as well as legal requirements, rather than trying to create a solution yourself, especially if you intend to sell the solution.
  11. @Darian Miller unearthed the following https://www.embarcadero.com/resources/development-jobs/ which allows you to post your "looking for work" requests as well as "looking for developer" posts
  12. Lars Fosdal

    Freeeee

    @Freeeee FYI, TextPad does cut/copy/paste of columns. Notepad++ and VS Code also.
  13. I have the weirdest issue. I just installed a fresh Delphi 11.1 + patches on a new, fully patched Windows 10 Enterprise laptop. For some weird reason - I can't debug. Breakpoints don't break. Exceptions break shows assembly code, says it is mixed mode, but no source lines show, and I can't trace to next sourceline. Yes, I am in 32-bit debug mode. Yes, the project has the debug settings and debug info included. Yes, the output folders have full access for the current user. Yes, there is only one set of DCUs in the path. Yes, there is only one .EXE file. Edit: Yes, they are debug DCUs Yes, line endings are CRLF Yes, current user has local admin rights As soon as my app starts, the breakpoints are grayed out. Edit 2: It does not happen to all apps. The problem app is about 600k lines. Tiny apps and a larger 1100k line app - no problems. What am I missing? Update - Possible causes? A developer on a non-corporate laptop does not have this problem. Another developer on corporate laptops have the same problem as me on both new and old laptops. That seems to indicate a Windows policy may be a factor here. Anyways - workaround: Project | Options | Linking | Include remote debug symbols: A tick here gave working breakpoints for us.
  14. Lars Fosdal

    RESTDebugger fails where Postman succeeds

    I've used https://www.charlesproxy.com/ with success for seing exactly what is sent/received in a REST API. You can also inject it into a https connection as it acts as a proxy.
  15. Lars Fosdal

    RESTDebugger fails where Postman succeeds

    Bruno looks quite interesting! And, it's open source!
  16. Ref. the above mentioned leak. Does it occur if you set ListView.OwnerData to true? There is BeginUpdate/EndUpdate on ListView.Items, but not sure that would suppress item events.
  17. Lars Fosdal

    THintWindow; exposing the WMLButtonDown event

    Did you override the HintWindowClass before Application.Run is executed? https://docwiki.embarcadero.com/Libraries/Athens/en/Vcl.Controls.THintWindowClass
  18. Short answer: Yes Long answer: Yes, but don't! It would put your SQL database at risk. Instead, build a proper REST API as - it hides the underlying database - it allows you to change the underlying database operations without changing the client A REST API done right is far more secure and robust.
  19. Lars Fosdal

    Is it possible to implement floating/fully custom Dropdown Menus?

    TMS has a new customizable context menu which is cross platform. https://www.tmssoftware.com/site/blog.asp?post=2364
  20. Lars Fosdal

    Share a data between two units in dynamic loaded BPL.

    Isolate your business logic from the UI. Use an intermediate class to pass the data around.
  21. Lars Fosdal

    Delphi 13 beta

    If you currently are a Delphi/RAD Studio subscriber, you can request access to the beta if you didn't already get an invite. As per the link in the starting post of this thread: Closing this thread.
  22. Lars Fosdal

    Share a data between two units in dynamic loaded BPL.

    I would decouple the action by having a handler. unit Druga; interface uses Dialogs; function Demo:boolean; type TOnShowMessage = reference to procedure; var OnShowMessage: TOnShowMessage; implementation // No circular ref here function demo: boolean; begin if Assigned(OnShowMessage) then OnShowMessage else raise Exception.Create('Someone forgot to set the OnShowMessage handler'); end; initalization OnShowMessage := nil; end. In Prva, I'd connected the handler in f.x. FormCreate; procedure TForm1.FormCreate(sender: TObject); begin Druga.OnShowMessage(Self.MyShowMessage); end; procedure TForm1.MyShowMessage; begin ShowMessage(Form1.Edit1.Text); end; This avoids the circular unit ref, and since you initialize the handler from the main form, it shouldn't matter if the bpl is dynamically loaded? If you want to, you can of course also add parameters to the handler to display a text generated in unit Druga or have multiple handlers for different uses.
  23. @dmitrybv I assume that in your real code, you retrieve the correct installation paths from registry? Edit: Also, see this for executing shell commands:
  24. Lars Fosdal

    Delphi 13 beta

    @RDP1974 Dave is correct. Please remove your comment.
  25. It is possible to add a comment to the issue, but not sure if that would be more hurtful than helpful.
×