Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 12/02/20 in all areas

  1. Stefan Glienke

    Is someone using MVVM?

    Best since sliced bread ... if you're not in Delphi
  2. Vincent Parrett

    DPM Package Manager - presentation

    Hi All A few weeks ago I did a zoom presentation about DPM to the Australian Delphi User Group (Melbourne branch, but anyone could attend). A link to the recording of that presentation is available on the ADUG website - https://www.adug.org.au/meetings/melbourne-meeting-november-2020/ along with some notes about dpm The video is nearly 2hrs long, but the presentation part is only the first 50 min or so (the rest is q&a/discussion). If you want to skip past the boring slides to the demo it starts at 24:40 😉
  3. Remy Lebeau

    TIDMessage extract RFT body

    The entire email. That is why a TNEF is parsed into a new TIdMessage. Yes. Typically no, those are the filename forms that Microsoft uses for TNEF. But the filename is technically under the control of the sender and COULD be different if a non-Microsoft client is sending a TNEF attachment. So you should pay more attention to the attachment's Content-Type rather than its filename.
  4. These temporary component inclusions of EMBT are bullshit. Free and included, my rear end...
  5. Uwe Raabe

    DPM Package Manager - presentation

    "DOPE" for Delphi Organizer for Packaged Externals
  6. David Champion

    DPM Package Manager - presentation

    I'm guessing close to the english idiom "smoke and mirrors"
  7. Vincent Parrett

    DPM Package Manager - presentation

    🤣 - I would hope that this project won't just be my personal package manager that only I use - that said, VPAM sounds like a kind of missile or weapon!
  8. Lars Fosdal

    Enumeration Type as Parameter

    I am still not sure what you want to achieve or what it is that is the actual problem? Do you need to validate that the second parameter is valid for the first parameter? Or is it converting to/from an integer? if it compiles, aValue is a member of T function TFoo.IsMember<T>(const aValue:T): Boolean; begin Result := True; end; Convert it to an integer? function TFoo.ToInteger<T>(const aValue:T): Integer var V: TValue; begin V := TValue.From<T>(aValue); Result := V.AsOrdinal; end;
  9. FPiette

    Enumeration Type as Parameter

    I don't see any generics here. Not sure I fully understand what you need. Anyway here is what I think is a solution: type TSet1 = (a11, a12, a13); TSet2 = (a21, a22, a23, a33); TFoo<T: record> = class public class procedure Foo(ADefault : Integer); end; implementation class procedure TFoo<T>.Foo(ADefault: Integer); var Info : PTypeInfo; NumberOfElement : Integer; begin Info := TypeInfo(T); NumberOfElement := Info.TypeData.MaxValue - Info.TypeData.MinValue + 1; Form1.Memo1.Lines.Add(NumberOfElement.ToString); end; // Example use procedure TForm1.Button1Click(Sender: TObject); begin TFoo<TSet1>.Foo(123); TFoo<TSet2>.Foo(456); end;
  10. Stefan Glienke

    Manage overloaded IfThen functions

    That or something like this.
  11. aehimself

    Database app good practice

    I started actively using databases in the past couple of years in my applications, and these are the things I wished to know from the beginning: - Every SQL thing should be in a separate thread. If connection takes 20 seconds or you are downloading a very large dataset over a slow connection, your application will be frozen. Publish important data or the complete dataset objects as properties. Just make sure you disconnect all datasources before any operation and reconnect them after, as data events will start to fire off in an inconsistent state causing AVs most probably. - When it comes to threads, a golden rule is that each thread should have it's own connection to the database. You also want to make sure that threads are working with different tables or you should have correct transaction isolation set up. - For service applications I wrote my own "ORM", which is basically a wrapper for a TQuery. Each field the query returns are published as typed properties. So instead of query.Edit; query.FieldByName('field').AsString := 'Hello, world'; query.Post; I simply can say: myTable.Field := 'Hello, world'; and myTable takes care of everything else. I took this one step further after a couple of DB changes and wrote my own planner. I tell it what kind of tables and fields I want, and it generates MySQL and MSSQL create and delta scripts AND all the myTable classes as Delphi source files. I make a change, I have all the SQL scripts ready to ship with the update and I already can use the new fields in all of MyTable objects... you get the point. - Depending on the component you use (and how they access the databases) client libraries might not be thread safe or requiring special parameters upon establishing the connection to be thread safe! I found it as a best practice for example to have a critical section when connecting as I had strange access violations when 7 worker threads tried to connect using the same library at the same time. - If performance is critical, do not use TQuery.FieldByName. That's all I can think of for now but I'm sure I missed a few. If anything else pops up, I'll try to remember to update this thread.
  12. Anders Melander

    Large project does not start

    Yes. I usually use a simple factory pattern. It briefly goes like this (view = frame): Create a "view registry" class. This class wraps a dictionaly that maps between a view interface and a class type. Move all your stuff into frames. For each frame assign them an interface and register the interface and the view class in the view registry. Create a "view manager" class. This class wraps a TDictionary<TGUID, TView> that contains the currently active view instances and is also responsible for creating new views. So something like: View (i.e. frame) abstract base class and API: unit Foo.Views.API; interface type IView = interface ['{4057A1F4-F22C-4CCF-89DE-9F4AE2E790DE}'] procedure Initialize; end; type // Abstract base class of your views. TView = class abstract(TFrame, IView) protected // IView procedure Initialize; virtual; end; TViewClass = class of TView; type IViewRegistry = interface ['{B4EC0F81-24DF-41D9-BF8A-CE0D9958C9A9}'] procedure RegisterView(const GUID: TGUID; ViewClass: TViewClass); procedure UnregisterView(const GUID: TGUID); function FindView(const GUID: TGUID): TViewClass; end; type IViewManager = interface ['{B4EC0F81-24DF-41D9-BF8A-CE0D9958C9A9}'] function OpenView(const GUID: TGUID): IView; procedure CloseView(const GUID: TGUID); function FindView(const GUID: TGUID): IView; end; implementation ... end. The API of a single view: unit Foo.Views.MyView.API; interface type IMyView = interface ['{063646E3-FB0D-4B8C-984A-A5E54F543651}'] procedure FooBar; end; implementation end. The implementation of a single view: unit Foo.Views.MyView; interface uses Foo.Views.API, Foo.Views.MyView.API; type // Trick to get the IDE to behave without registering the frame in a package TFrame = TView; TMyView = class(TFrame, IMyView) protected // IView procedure Initialize; override; // IMyView procedure FooBar; end; implementation ... intialization // Register our implementation of the IMyView interface ViewRegistry.RegisterView(IMyView, TMyView); end; and then you "just" have to Implement IViewRegistry and IViewManager unit Foo.Views.Manager; interface uses Foo.Views.API; function ViewRegistry: IViewRegistry; function ViewManager: IViewManager; implementation type TViewRegistry = class(TInterfacedObject, IViewRegistry) private FRegistry: TDictionary<TGUID, TViewClass>; protected // IViewRegistry procedure RegisterView(const GUID: TGUID; ViewClass: TViewClass); procedure UnregisterView(const GUID: TGUID); function FindView(const GUID: TGUID): TViewClass; end; var FViewRegistry: TViewRegistry; function ViewRegistry: IViewRegistry; begin if (FViewRegistry = nil) then FViewRegistry := TViewRegistry.Create Result := FViewRegistry; end; procedure TViewRegistry.RegisterView(const GUID: TGUID; ViewClass: TViewClass); begin FRegistry.Add(GUID, ViewClass); end; procedure TViewRegistry.UnregisterView(const GUID: TGUID); begin FRegistry.Remove(GUID, ViewClass); end; function TViewRegistry.FindView(const GUID: TGUID): TViewClass; begin if (not FRegistry.TryGetValue(GUID, Result)) then Result := nil; end; type TViewManager = class(TInterfacedObject, IViewManager) private FViews: TDictionary<TGUID, IView>; protected // IViewManager function OpenView(const GUID: TGUID): IView; procedure CloseView(const GUID: TGUID); function FindView(const GUID: TGUID): IView; end; function TViewManager.OpenView(const GUID: TGUID): IView; begin if (FViews.TryGetValue(GUID, Result) then Exit; var ViewClass := ViewRegistry.FindView(GUID); if (ViewClass = nil) then Boom! Result := ViewClass.Create; FViews.Add(Result); Result.Initialize; end; ...etc. etc... end.
  13. DelphiMT

    Is someone using MVVM?

    I've had good luck using it to write a GUI in Delphi which interacts with another program that was written in Python. I use sockets to communicate between the two processes, which has the added benefit of allowing the GUI to run on a different machine if needed, it could even be on a different platform. I've used this same architecture even when the program(s) are written in the same language. The MVVM structure works well for this -- I generally have the View (the GUI) send messages over the socket to the ViewModel, which then dispatches them to the appropriate Model. I use thread-safe queues and background threads for all the I/O so that the GUI is never blocked.
  14. I'm deeply interested on this, and would like if anyone here is using/used homegrown MVVM implementations, and wich was/is your experience. Works fine? Is not woth the effort? Is the best since sliced bread? Please, share your experience Thank you!
  15. Javier Tarí

    Is someone using MVVM?

    Could you expand that a bit? Do you mean in Delphi we don't need it? If that's what you mean, wich would be in Delphi the pattern that gives us the same as MVVM in other platforms?
  16. Wloochacz

    Database app good practice

    I'm sorry, do you know this project? https://github.com/grijjy/MvvmStarterKit It is not pure MVC, but MVVM Here full approval, DMVC (https://github.com/danieleteti/delphimvcframework) is not a project for VCL/FMX applications. And yes and no. Please note that FMX is also not TDataSource oriented, it does not have DBAware controls known from VCL (e.g. TDBEdit) and instead LiveBinding mechanism is used. And in case of MVVM it can work very similarly. In my opinion, RAD is no one's friend and this friendship turns into hatred when the project is bigger and bigger... And it gets older and older, and it needs to be developed. After all, for decades we have been convinced that RAD is great! For everything! Just, it's bullshit.
  17. Javier Tarí

    Database app good practice

    There are no MVC or MVVM frameworks on Delphi, other than the DMVCframework, wich I believe is not thought for Windows UI apps And anyway, that kind of frameworks are not oriented to let a form use a TDataset or a TDatasource So IMHO, as of today, RAD and MVC/MVVM are not friends
  18. BruceTTTT

    Ole DB (Ado) for MSSQL un-deprecated by Microsoft

    There are no "problems" with the native client except for compatibility with versions of SQL Server. Depending on which version of the server you are running (including with Express), you have to pick the correct native client. There are times my software has had to support 5 different versions of the server (2008 all the way through 2019), and supporting a different driver each time gets annoying fast. So far with my testing, the msoledbsql ("Driver", not "Provider") and the related ODBC 17 driver just released by Microsoft are compatible with all versions of SQL Server. This is really helpful when the app or client needs to access different versions. And as mentioned above, ODBC 17 is slower. Bottom line for me right now, dbGo using this new driver is still the fastest and most agile solution. Supporting ODBC 17 as a choice is great for options, but in all my testing, there is still overhead vs. using the OLE DB "Driver" directly. https://docs.microsoft.com/en-us/sql/connect/oledb/oledb-driver-for-sql-server?view=sql-server-2017 In their words: ... SQL Server Native Client OLE DB provider (SQLNCLI) remains deprecated and it is not recommended to use either for new development work.
  19. bobD

    Database app good practice

    From the description of where you are ("click on button perform queries and display results"), this is an immense topic. Probably the classic intro to object oriented design is Object-Oriented Software Construction by Bertrand Meyer For a simpler approach (and with the benefit of being written for Delphi), try NIck Hodges' books on coding in Delphi. They're straightforward and very approachable. Bit more detail in Hands-On Design Patterns with Delphi by Primoz Gabrijelcic These will get you started with OO thinking--the prerequisite to architectural layering. In the mean time, how to refactor your current code to make it more maintainable? I'd suggest trying this: New rule: no data access objects on forms. Those belong in data modules. Organize the modules into groups of logically related queries. That will start to separate out your code by 'topic of concern' so you can start grouping logically related code. bobD
  20. Stano

    Database app good practice

    I would also like to know how MVC is implemented in Delphi in practice. General discussions on the issue did not help me. I couldn't find an example.
  21. Interface-oriented development is an awesome tool, and the ARC memory management that usually comes with it can be great as well. But in our beloved Delphi, interfaces are not full citizens. Working with Delphi interfaces becomes soon troublesome; the way they have been implemented makes impossible some of the common stuff we do in our daily programming As an example, you can't use an interface method as an event handler. You can't use anything that expects a "procedure of object" or "function of object", nor use generics or other modern features. Why? Because the interfaces we have in Delphi were introduced just and only to achieve COM integration. So, the interfaces don't know they always have an object (delphi class) behind them So we need a remake of Delphi interfaces, but we can't break the software already using them Here comes the "native interface": probably they should have a distinction on their declaration, so the compiler knows to handle them And the big difference using them, is that native interface methods are object methods, so the compiler would know how to handle them. I would like this post to serve as brainstorming for those of you who have ideas about how to enable this division of the com-based interface and a possible new native implementation, implementation of which there may also be proposals for improvement. For example, at least for me, it would be nice if interfaces (at least the native ones) could have multiple inheritance of interfaces: InterfaceTest = ninterface(Interface1, Interface2, Interface3) procedure Test; end; Feel free to comment in any direction.
×