Leaderboard
Popular Content
Showing content with the highest reputation on 12/02/20 in Posts
-
Is someone using MVVM?
Stefan Glienke replied to Javier Tarí's topic in Algorithms, Data Structures and Class Design
Best since sliced bread ... if you're not in Delphi -
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 😉
-
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.
-
QuickBooks API getting Access Token with OAuth2
Lars Fosdal replied to CliveMM's topic in Network, Cloud and Web
These temporary component inclusions of EMBT are bullshit. Free and included, my rear end... -
DPM Package Manager - presentation
Uwe Raabe replied to Vincent Parrett's topic in Delphi Third-Party
"DOPE" for Delphi Organizer for Packaged Externals -
DPM Package Manager - presentation
David Champion replied to Vincent Parrett's topic in Delphi Third-Party
I'm guessing close to the english idiom "smoke and mirrors" -
DPM Package Manager - presentation
Vincent Parrett replied to Vincent Parrett's topic in Delphi Third-Party
🤣 - 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! -
Enumeration Type as Parameter
Lars Fosdal replied to chkaufmann's topic in RTL and Delphi Object Pascal
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; -
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;
-
Manage overloaded IfThen functions
Stefan Glienke replied to Mike Torrettinni's topic in General Help
That or something like this. -
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.
-
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.
-
Is someone using MVVM?
DelphiMT replied to Javier Tarí's topic in Algorithms, Data Structures and Class Design
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. -
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!
-
Is someone using MVVM?
Javier Tarí replied to Javier Tarí's topic in Algorithms, Data Structures and Class Design
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? -
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.
-
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
-
Ole DB (Ado) for MSSQL un-deprecated by Microsoft
BruceTTTT replied to A.M. Hoornweg's topic in Databases
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. -
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
-
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.
-
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.