Nur eine kurze Erinnerung: CodeRage 2018 am 26.06.18.
Meine Session ist 18:00 Uhr - 18:45 Uhr
Fluiddesign und andere Techniken um sich den Programmieralltag zu erleichtern.
Ab 18:45 Uhr bin ich für FAQ's online!
Hier der Youtube-Link.
Monday, June 25, 2018
Sunday, May 20, 2018
Formatting Sourcecode
Formatting Delphi/Pascal Sourcecode is an interesting topic.
You disagree?
Take 10 developers and let them all hand-formatter some sample source-codes and you will get 10 different results.
You disagree?
Most developers have developed their own style in formatting source code because they are working alone and nobody else would see the code. Perhaps you are new to Delphi and used another programming language for many years. I can not remember what Delphi version was this first with an included formatter CTRL+D. Perhaps before that, you are using an IDE plugin or external program.
If you are working alone - do whatever you like with your source-code, but if you have to work together with other developers in a team - it's time to think about "your" formatting.
Some developers like many empty lines and indent nearly everything or want to have a description with a Date, Name, and Copyright over every method. Other developers hate empty lines and only ident one space.
Perhaps you have the "begin" at the end of the line and the "end" at the first position like:
if A > B then begin
foo(42);
end;
But since the IDE has Castalia or perhaps you are using a third-party-tool you got the funny colored helper-lines to show the corresponding begin-end's, it is better that begin-end has the same ident.
Is there a right way to format your source-code? You may have the standpoint - only the default formatter-settings are the right way.
Keep in mind - if you are writing a program, you will read more source code then you write or in other words writing source code is not the trick, writing source code that could be read easily and by other developers too, is the goal.
Of course, the formatting is just the start, the next topics are caps, spaces and naming. There are so many rules out in the field.
Class fields have an "F" at the beginning, parameters an "A", local var's an "L". Perhaps you like to mix your local language with English (better not). Are you rename all your visual controls?
Label1 -> lbName
Edit1 -> edName
Edit1 -> edName
Edit1 -> NameEdit
Do you like long var-names "Name_of_the_person" ( hope not with "_" )
So where to start?
In the next day's I will try to introduce some of these rules to a team of four very different developers. Let's see if I can create a set of rules that everyone can live with.
But that will eventually be a topic for another blog post.
Thursday, April 26, 2018
MVVM 2.0 - I did it my way.
If you like, you can compare this with one of my older posts from 2016: MVVM - Or what I think MVVM is. (Translated)
Why MVVM?
- Because it’s cool and I’m a geek
- to show – I’m better than other developers
- so nobody else could maintain the code
no – perhaps – NO!!! Just joking!
Because we like to
- separate forms from code
- to get better maintainable code
- have less-hardcoded dependencies
- to be able to test the business logic
- to test the workflow
Sure? Are you writing tests? If not – stop reading…
But perhaps you like to develop code you can use again in other applications…
Ask 10 developers to explain MVVM – at first; you will get a picture from dotnetpattern.com, msdn.microsoft.com or wikipedia.org, then everybody tells you: “This is the pattern and “so” it has to be implemented”
OT: Like many other patterns… You have to follow the rules of these 4 guys and the book from 1994! More than 500.000 copies of the book have been sold – not so bad at all…
Back to MVVM - If you ask for the details, you will get 10 ideas on how to implement it.
But… We are Delphi developer – why should we try to implement things as Microsoft did in .net? Because this is the right way?
Let us dive into:
The core elements are View, ViewModel, and Model. In the beginning, you could trade a TForm as the View, but this is not the same. A TFrom could be the container for many views at the same time. For the moment, we say TForm = View – the key things of MVVM are the bindings or better, the communication from ViewModel to View and back. (And perhaps to the Model)
If we follow the rules – the view should have no logic, the ViewModel is responsible for handling the view-logic and converting the data to the View and the Model contains the data. (hope this is right) I never took this approach.
Our view is not a stupid XML-only-description of visual controls. Our controls always have their own logic, we have styles and animations, able to do onMouseover/down/up things. Trigger doing fancy stuff.
The Model is dealing with the data and the Database, too? I don’t think so. What is a database?
Neither my ViewModel nor my Model knows what a database is. The Models get an interface to store or load data – without knowing where it ends.
How does communication work?
The Model changes some data and now the ViewModel wants to inform the View or perhaps all Views, about this change.
At first, we need a Multicast event to inform more than one View about the new data. So every view has to sign in for the event. Now the ViewModel could send a PropertyChanged Event like:
PropertyChanged(PersonNameProperty);
Every view – that is able to show the change, gets the Event and could ask the ViewModels Property PersonName.
What?
PersonNameProperty is defined as:
Const PersonNameProperty : String = 'PersonName';
Use Consts and no magic String so we always have the right typo. OK…That is good, but:
In the View, we end up in a
procedure PropertyChanged ( Const APropertyChanged : String);
Comparing with many If then else constructions (first bad thing) and because we have a const in the ViewModel, the reference is not the same so the string-compare must compare all chars. (second bad thing).
If we have a huge view (yes we could perhaps split it) we and up with a too-long comparing procedure.
Since Windows 3.1 - in the early days – Messages are sent with the content or at least with a pointer to the content.
So why are we just sending change “hints”? This is like sending an SMS – I have news call me back, instead of “I will be late, arriving at 8pm”.
Sending Strings is good for testing. Eg: A property change of PersonName := 'NewName'; should fire 'PersonName' – I tried Const ID’s like Const idPersonName : Integer = 42; Not so good for testing but you can use a case at the View.
I don’t like to repeat on every Property:
begin
if FPersonName <> AValue then
begin
FPersonName := AValue;
PropertyChanged(PersonNameProperty);
end;
end;
Same in every setter.
Then to the View:
if APropertyChanged = TPersonViewModel.PersonNameProperty then
PersonName.Text := FViewModel.PersonName;
I first implement the MVVM Pattern the MS-way, but if you think – “Too much writing” or “I did not test my code” – you are right and of course, debugging is not so easy, too…
In fact, development time takes a bit longer. This extra time cut’s down my Test-writing-Time… (Bad thing three), because I love TDD.
We have attributes and the RTTI!
It is faster if you could use the same Model or perhaps the ViewModel in another project, but that is another story.
These problems lead me to “my way” MVVM 2.0…
We have attributes and the RTTI!
I think: The best way to use a pattern is if the pattern is not so far from your normal workflow.
I like to design my Forms and so my Views as Forms, too – Frames are bad and often lead to problems with the IDE. So SubViews are Forms with a TLayout-Container that parent is mapped to the target-parent at runtime.
My new workflow is:
- Create a Form/View
- Change Class(TFrom) to Class (TMVVMForm) / or Frame for SubViews
- Put attributes at FormControls like [ViewModelLink] PersonName : TEdit;
- Create Procedures with attributes like [PropertyChange]Procedure PersonNameChanged(Const AValue : String);
- Register the Form at the ViewLocator with the necessary ViewModel
- That’s it.
In your NavigationService you could get the View from the ViewLocator for a given ViewModel and an optional Name. On Creation the View connects all bindings and propertyChanges.
You like to change Names? All attributes take optional name parameters. For:
[ViewModelLink(TPersonViewModel.PersonNameProperty]
Edit1: TEdit; // Better rename this!
Now to the ViewModel:
- Create a class TPersonViewModel = Class(TRootViewModel)
I don’t like ViewModelBase as Name – it sounds like a database for ViewModels…
All my DBClasses ends with Base – PersonBase not DBPerson! - Define your private Fields as
FPersonName : autochange<string> // FPersonName : String - Property PersonName : String : read GetPersonName write SetPersonName;
- Procedure SetPersonName(Const AValue : String);
begin // Auto-PropertyChanged if different.
FPersonName.Value := AValue;
end; - That’s it.
Most of the stupid code writing is not necessary anymore and done in the background over the RTTI.
Of course, this is only a small part of this pattern, but now I can point my focus on the more advanced parts.
You like this approach? – Please leave a comment – if not…;-)
Wednesday, March 14, 2018
Neural Network
Neural Network or Neuronal Network... Whatever...
For many years I want to test this kind of programming... But never had time for this.
You can find many videos on YouTube, but "all" are full of math or full of the wrong programming language. ( or both )
You can find some source files, but what is the minimum of LOC's you need?
For now: Less the 300 LOC in Delphi for a working network.
At the moment I have many ideas about what I can do with this... But perhaps first dig into the next step:
Genetic algorithm.
I will include this in the FDK, if ready...
Best video I found:
https://youtu.be/-zT1Zi_ukSk (C#)
https://youtu.be/KkwX7FkLfug
This, I take to just live to code this - with many modifications - in Delphi - a little bit of debugging and it works. ( not much longer than it takes to look the video)
Tuesday, February 20, 2018
FDK XE8 - 10.2
Hello!
I've already found the time to compile my FDK for XE8 up to 10.2.2!
I finally found the F2018 error so XE8 and Seattle are working again.
So starting at this point I'll prepare the next update.
I've already found the time to compile my FDK for XE8 up to 10.2.2!
I finally found the F2018 error so XE8 and Seattle are working again.
So starting at this point I'll prepare the next update.
Wednesday, December 6, 2017
Delphi Entwickler (m/w) gesucht!
Programmierer (m/w) für Delphi 2007 und XE 10.x.x!
Für die Weiterentwicklung einer Software für Gerichtsvollzieher in Deutschland suchen wir Programmierer mit hervorragenden Delphi Kenntnissen.
Unser Unternehmen ist der Marktführer im Bereich Gerichtsvollziehersoftware und seit über 30 Jahren auf dem Markt. Mehr als 2.200 Gerichtsvollzieher im Bundesgebiet zählen zu den Kunden. Die Software hat einen enormen Funktionsumfang und der Aufgabenbereich der Gerichtsvollzieher ist ausgesprochen groß.
Ihre Aufgaben:
- Weiterentwicklung einer umfangreichen Software für Gerichtsvollzieher sowie einiger Nebenprodukte
- Fehleranalyse und Optimierung
- Unsere Anforderungen:
- Hervorragende Kenntnisse in Delphi
- Fähigkeit, sich in mehrere Millionen Zeilen Sourcecode einzuarbeiten
- Optional: Erfahrung mit FireMonkey zur Entwicklung von Apple sowie Android Apps
- Hohe Lernbereitschaft, da Sie viele Arbeitsabläufe eines Gerichtsvollziehers und der Justiz nebst zahlreicher Fachbegriffe erlernen müssen
- Geduld, Freundlichkeit und eigenständiges Arbeiten
- Gute Ausdrucksweise, einwandfreies Deutsch in Wort und Schrift
Wir bieten:
- Sehr sicherer Arbeitsplatz und unbefristete Einstellung beim Marktführer
- Langfristiges Beschäftigungsverhältnis
- gute Aufstiegsmöglichkeiten.
- Nur Festanstellung, kein Heimarbeitsplatz, kein Außendienst, gutes Arbeitsgerät – z.B. nutzen die Programmierer bis zu sechs 40“ UHD Bildschirme gleichzeitig.
- Stetig neue Herausforderungen und Veränderungen
- 3 im Thema eingearbeitete Programmierer sowie einige Gerichtsvollzieher zur Unterstützung
- Ggf. Ausweitung Ihrer Tätigkeit (mehr Verantwortung, eigenständige Entwicklung, Schulungen, Präsentationen)
- Kleines Unternehmen mit momentan 9 Angestellten
- Ggf. Unterstützung bei einem notwendigen Umzug
- Über Ihre aussagekräftigen Bewerbungsunterlagen, mit Beschreibung Ihrer Programmiererfahrung/–kenntnisse, Angabe Ihrer Gehaltsvorstellung und Nennung des frühestmöglichen Arbeitsbeginns freuen wir uns.
Für Rückfragen stehen wir gerne zur Verfügung.
Einen kleinen Einblick über unsere Produkte erhalten Sie auf unserer Webseite www.gerichtsvollzieher-software.de.
Baqué & Lauter GmbH
Flamersheimer Weg 3
53881 Euskirchen Palmersheim
fl@gvinfo.de
Monday, November 27, 2017
Back in my office.
Hi!
After 19 days of workshops with nearly 1600 customer and more than 7000km on the road, I'm back in the office. So I need some time to look through the stacks of Paper on my desk, but after that I will do the FDK update before the end of the year.
After 19 days of workshops with nearly 1600 customer and more than 7000km on the road, I'm back in the office. So I need some time to look through the stacks of Paper on my desk, but after that I will do the FDK update before the end of the year.
Monday, October 2, 2017
Facebook?
Using Facebook or this blog?
OK - Perhaps technical Infos in this blog and Funstuff on Facebook...
I have to look for a cat using my FDK for the best Facebook user experience...
btw: https://www.facebook.com/delphiprofi.de/
OK - Perhaps technical Infos in this blog and Funstuff on Facebook...
I have to look for a cat using my FDK for the best Facebook user experience...
btw: https://www.facebook.com/delphiprofi.de/
Sunday, September 24, 2017
Forentage 2017 - Sonderaktion
Hallo Zusammen!
Leider hatte ich die Bestellformulare mit einem Sonderpreis für mein FDK - im Auto - im Kofferraum - im Saturnparkhaus vergessen.
Natürlich hätte es eine Sonderpreis für Bestellung auf den ForenTagen gegeben!
Also: Befristet bis zum 15.10.2017 gibt es mein FDK für 349,- € (statt 399,- €)
Einfach das Setup downloaden und registrieren!!
Infos unter : http://delphiprofi.blogspot.de/2016/05/fdk-das-firemonkey-development-kit.html
Die nächste Version ist in Vorbereitung.
INFO: Die MVVM-Teile sind zur Zeit noch nicht enthalten!
Leider hatte ich die Bestellformulare mit einem Sonderpreis für mein FDK - im Auto - im Kofferraum - im Saturnparkhaus vergessen.
Natürlich hätte es eine Sonderpreis für Bestellung auf den ForenTagen gegeben!
Also: Befristet bis zum 15.10.2017 gibt es mein FDK für 349,- € (statt 399,- €)
Einfach das Setup downloaden und registrieren!!
Infos unter : http://delphiprofi.blogspot.de/2016/05/fdk-das-firemonkey-development-kit.html
Die nächste Version ist in Vorbereitung.
INFO: Die MVVM-Teile sind zur Zeit noch nicht enthalten!
Tuesday, September 5, 2017
Scanning barcodes the FDK-way
You like to scan barcodes in your app?
Of course, there are solutions for both platforms, but for free?
And how long does it take to integrate this into your app?
Perhaps you consider the FDK approach:
Uses
Delphiprofi.FDK.AnyFactory,
Delphiprofi.FDK.Barcode;
var
FScanbarcodes : ICanScanBarcodes;
procedure TFormMain.ScanClick(Sender: TObject);
begin
FScanbarcodes := TAnyFactory.Factory.CreateObj<ICanScanBarcodes>;
FScanBarcodes.ScanResult(Procedure (AResult : String)
begin
LBLScanResult.Text := AResult;
FScanbarcodes := NIL;
end).Scan;
end;
Internal I'm using the ZXING Source for Android. For iOS you can choose between the ZBar or the ZXING version. ZBar ist based on the TMSWrapper for ZBar!
The ZXING Version is inspired by MVP Andrea Magni but without the FrameStand and other overhead.
Ok, you probably googled this topic! But you will find solutions only for iOS or solutions only for Android. Perhaps a preinstalled third-party app must be installed.
Of course, there are solutions for both platforms, but for free?
And how long does it take to integrate this into your app?
Perhaps you consider the FDK approach:
Uses
Delphiprofi.FDK.AnyFactory,
Delphiprofi.FDK.Barcode;
var
FScanbarcodes : ICanScanBarcodes;
procedure TFormMain.ScanClick(Sender: TObject);
begin
FScanbarcodes := TAnyFactory.Factory.CreateObj<ICanScanBarcodes>;
FScanBarcodes.ScanResult(Procedure (AResult : String)
begin
LBLScanResult.Text := AResult;
FScanbarcodes := NIL;
end).Scan;
end;
Internal I'm using the ZXING Source for Android. For iOS you can choose between the ZBar or the ZXING version. ZBar ist based on the TMSWrapper for ZBar!
The ZXING Version is inspired by MVP Andrea Magni but without the FrameStand and other overhead.
Threading is done with my TAnyCommandProcessor, which can queue the workflow for the Bitmaps, that are captured with the TCameraComponent!
Tuesday, August 15, 2017
#WhyIChooseDelphi
Why I Choose Delphi?
Starting with UCSD-Pascal in school on Apple II. I used my Sharp MZ-800 (Z80 CPU) with CP/M and Turbo Pascal 1.0. I had a special utility to write IBM-Disks on MZ-800. So I was able to transfer my “homework” to the IBM XT, to show my work in school, with Turbo Pascal 1.0, too.
At this point, I got an offer to do a business application. This application was my first real Pascal application, too.
Before that, all my programs were programmed in Z80 assemblers, like my own 1000 byte Disk-Operating-System - FL-DOS from 1986.
To keep the necessary procedures together, I collected procedures in “one” Pas File called Runtime.pas.
“Yes”, this unit is still alive today but called Basis.pas and wBasis.pas for Windows-Stuff. I collected a million lines of source-code and unites over the years. Some have changed but many are still in use.
Starting with e.g. C# would take me month or years to reproduce my “runtime” core procedures.
That is the practical side. Besides this, for me, a compiler has to produce an exe…
No P-Code, no script no runtime interpretation. “My” compiler has to produce a standalone application that brings everything with it. No runtime stuff that had to be prior installed.
Ok, .NET was a “not so bad idea”. To have code that could be optimized for the given CPU at first run. Do we have this kind of “run on RISC-CPU” environment?
So let’s compare:
#C could be a choice because the code is like Pascal or not so far away!
C / C++, source code looks like someone had rolled an Armadillo over the keyboard.
End of List…
Yes, you can do everything in Delphi! However, If you are looking for some special things, you always find the source in C* but not in Delphi. For these small parts. Compile with C* link an object or use a DLL, done.
Have I tried to switch to C#? Yes but, I’m so much faster in writing Delphi… It was a waste of time and btw. I hate MS-IDE. (I still use the original WordStar key mapping from my early days on CP/M).
Remember the famous words: “The clueless people shall spend their time reinventing the wheel, while the elite merely uses the WordStar key mappings”.
Let us not talk about Pascal / Delphi as a source-code. One of the big things is productivity. The IDE and the compilation speed. Turn cycles are a major point in development.
Set Breakpoint, F9 to compile and start, debug, STRG-F2 to stop, change something and hit F9 again…. If you like, you can do this thousand times in an hour.
For many years I took the RAD approach – button on the Form -> double-Click -> and go with the code… Why not!
This was the time where nobody talked about design patterns, separation of form and code or other things. Why? No Internet…
Yes, I know the Internet starts on 1989/1991 and my Application was for Win95. However, when did you start your first AOL Internet over Hayes-Modem “You have new Mail” – Client?
We don’t talk about Borland-Pascal for Windows – But I had a small working Demo of my Software, simulating the DOS-Screen in a Windows-Frame… (If you ask me, I’ve never done this).
My Company depends on Delphi and I have no problem with this…
Because Delphi is the best development tool, I’ve ever seen.
Sunday, July 30, 2017
SQL, how do you write your queries?
OK - I know there are many ways to do a simple SQL Query... Like:
Query.SQL.Text := 'SELECT * FROM PersonDB where LastName LIKE "'+ALastName+'%" order by LastName,FirstName ASC LIMIT 50';
of course using Parameter is a better way, like:
Query.SQL.Text := 'SELECT * FROM PersonDB where LastName LIKE :0 order by LastName,FirstName ASC LIMIT 50';
Query.SQL.Params[0].AsString := ALastName+'%';
Perhaps you set you statements in the ObjectInspector or you copy the statement from an other tool.
But what if you are new to SQL?
What kind of errors happens in your SQLQuery?
Misspelled fieldname? Missing brackets, missing space or ",".
The problem is,- normally - you can only find this errors by executing the statement...
var
FirstName,
LastName : String;
P : Integer;
begin
LastName := ASearchFor.Trim+'%';
P := Pos(',',ASearchFor);
if P > 0
then begin
FirstName := Copy(LastName,succ(P),
Length(LastName));
Delete(LastName,P,Length(FirstName));
end
else FirstName := '';
// Normally
if FirstName.Trim = ''
then Query.SQL.Text := 'SELECT ...'// Without FirstName
else Query.SQL.Text := 'SELECT ...';// With FirstName
end;
But I don't like this untestable SQL in this procedure. So I came up with this:
procedure TPersonViewModel.Search(Const ASearchFor : String);
var
SearchResult : ICanCRUDSearch; // from my CRUD-Framework
// .. Same as above
begin
// .. Same as above and then
TCRUDSearch.&For(FPerson).
{} Where('LASTNAME').LIKE(LastName.Trim).
{} begin_Optional(FirstName.Trim <> '').
{} _AND.Where('FIRSTNAME').LIKE(FirstName.Trim).
{} end_Optional.
{} OrderBy('LASTNAME').OrderBy('FIRSTNAME ASC').
{} Limit(100).
{} Start(SearchResult);
if SearchResult.SyntaxOnly then
exit;
// Perform UserIO on SearchResult
end;
And for Unit-Testing you can just call this same procedure and "Start" performs a systaxcheck only.
Perhaps you call it "Over Engineering" - I call it helpful. And more:
The Fluid-Interface helps you to build your statement - of course you should know a little bit of SQL, but...e.g.
After "Where" you can only use a comparer "LIKE, EQUAL, GREATER...". That's why "Where" is defined as
ICanCRUDWhere = Interface
Function Where(Const AName : String) : ICanCRUDCompare;
end;
ICanCRUDCompare = Interface
Function LIKE(Const AValue : String) : ICanCRUDSearch;
Function EQUALS(Const AValue : String) : ICanCRUDSearch;
// more...
end;
The SearchResult stores the Data and you can iterate through it.
My FDK.FMXGridHelper can take this SearchResult and could direct perform the UserIO.
The CleanUp is done by RefCounting automatically.
Stay tuned for the next FDK update... More is coming...
Query.SQL.Text := 'SELECT * FROM PersonDB where LastName LIKE "'+ALastName+'%" order by LastName,FirstName ASC LIMIT 50';
of course using Parameter is a better way, like:
Query.SQL.Text := 'SELECT * FROM PersonDB where LastName LIKE :0 order by LastName,FirstName ASC LIMIT 50';
Query.SQL.Params[0].AsString := ALastName+'%';
Perhaps you set you statements in the ObjectInspector or you copy the statement from an other tool.
But what if you are new to SQL?
What kind of errors happens in your SQLQuery?
Misspelled fieldname? Missing brackets, missing space or ",".
The problem is,- normally - you can only find this errors by executing the statement...
In my FDK I have all database definition in my sourcecode. All fields can easily checked against this definition.
If I do a search for a Person in my PersonDB, I like to shorten the search result by typing not only the Lastname... I like a search of both Firstname and Lastname.
If I search for my name in this database I can put "Lau,Fr" into the Searchedit and I get the result of all Person starting with the Lastname LIKE "Lau%" and FirstName LIKE "Fr%".
Perhaps you do other combinations.
In this case you always have an If or Case statement to select the right SQL, - or - to Ignore NULL DB Fields.
In my latest development of my ORM/CRUD DB Interface, I tried to include this expectations in my FDK.
For the given search problem I have this solution in every application:
procedure TPersonViewModel.Search(Const ASearchFor : String);If I do a search for a Person in my PersonDB, I like to shorten the search result by typing not only the Lastname... I like a search of both Firstname and Lastname.
If I search for my name in this database I can put "Lau,Fr" into the Searchedit and I get the result of all Person starting with the Lastname LIKE "Lau%" and FirstName LIKE "Fr%".
Perhaps you do other combinations.
In this case you always have an If or Case statement to select the right SQL, - or - to Ignore NULL DB Fields.
In my latest development of my ORM/CRUD DB Interface, I tried to include this expectations in my FDK.
For the given search problem I have this solution in every application:
var
FirstName,
LastName : String;
P : Integer;
begin
LastName := ASearchFor.Trim+'%';
P := Pos(',',ASearchFor);
if P > 0
then begin
FirstName := Copy(LastName,succ(P),
Length(LastName));
Delete(LastName,P,Length(FirstName));
end
else FirstName := '';
// Normally
if FirstName.Trim = ''
then Query.SQL.Text := 'SELECT ...'// Without FirstName
else Query.SQL.Text := 'SELECT ...';// With FirstName
end;
But I don't like this untestable SQL in this procedure. So I came up with this:
procedure TPersonViewModel.Search(Const ASearchFor : String);
var
SearchResult : ICanCRUDSearch; // from my CRUD-Framework
// .. Same as above
begin
// .. Same as above and then
TCRUDSearch.&For(FPerson).
{} Where('LASTNAME').LIKE(LastName.Trim).
{} begin_Optional(FirstName.Trim <> '').
{} _AND.Where('FIRSTNAME').LIKE(FirstName.Trim).
{} end_Optional.
{} OrderBy('LASTNAME').OrderBy('FIRSTNAME ASC').
{} Limit(100).
{} Start(SearchResult);
if SearchResult.SyntaxOnly then
exit;
// Perform UserIO on SearchResult
end;
And for Unit-Testing you can just call this same procedure and "Start" performs a systaxcheck only.
Perhaps you call it "Over Engineering" - I call it helpful. And more:
I love this kind of fluid-source-code. It's so easy to read and understandable.
The {} in front of each line are only to prevent the sourcecode formatter to kill my structure.
The Fluid-Interface helps you to build your statement - of course you should know a little bit of SQL, but...e.g.
After "Where" you can only use a comparer "LIKE, EQUAL, GREATER...". That's why "Where" is defined as
ICanCRUDWhere = Interface
Function Where(Const AName : String) : ICanCRUDCompare;
end;
ICanCRUDCompare = Interface
Function LIKE(Const AValue : String) : ICanCRUDSearch;
Function EQUALS(Const AValue : String) : ICanCRUDSearch;
// more...
end;
The SearchResult stores the Data and you can iterate through it.
My FDK.FMXGridHelper can take this SearchResult and could direct perform the UserIO.
The CleanUp is done by RefCounting automatically.
Stay tuned for the next FDK update... More is coming...
Subscribe to:
Posts (Atom)