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.
Monday, November 27, 2017
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...
Friday, July 14, 2017
Which Delphi Language Features are necessary?
Long time ago I was very satisfied with (Turbo)-Pascal.
Everything was fine! My world full of Records, (Fixed)Arrays and Shortstring has made me happy.
There was no need for a Database - I could read and write my Records - as easy as it could be - with blockread and blockwrite...
At this time I was able to write any program I wanted. (for the Kids: Program was the name in these days, today you would call it App)
Then "suddenly" records where bad and I "had to" use classes...
Too Bad... No block-read/write any more.. At this time you had to use Streams... (It finally leads to the same call, but "nobody" knows this...)
Next Step: You could do fancy things with class operators and implicit. So back to Records?
Then, "suddenly" classes are bad and you have to code against Interfaces to decouple things for Unittests. Have you ever done Unittest in these "old" days?
As time goes by, new compilers were ignored... Delphi 2007 could be used for everything... Windows, Windows-Server(ISAPI.DLL) and ASP.NET...
Sometimes I took a look at new compilers, but without ASP.NET and this new very bad thing called Unicode, I ignored them.
So let's jump a few years into mobile development... Many new stuff...
Zero based Unicode Strings - no more Ansi- or Shortstrings, ARC, ARM, 64 Bit, Attributes, Generics, TPL and more...
After 6 years of development - using "new" language features - this features become so handy that I hate every hour of programming old apps with Delphi 2007.
Unbelievable, have you tried "cool stuff" without Generics, lately? Not using generics is like doing the same stuff over and over again. In the old day's we called it copy&paste (OK, Generics is doing copy&paste internally, but it feels better).
And what's about Unit-Test? Are you still using a Hello-World-One-Button-Apps with a Button labeled "Button1" on it to test new Source-Code?
Testdriven-Development - That is the right workflow to speed up development. Of course with Testinsight as you can read in my blogpost from April.
Do you want to see the power of Testdriven-Development - visit my Session at Forentage 2017.
Do you want to see the power of Testdriven-Development - visit my Session at Forentage 2017.
Using new language features? All I can get...
Forentage 2017 - Meine Session.
Hallo zusammen!
(English text below)
Ich nenne sie:
Eine Voraussetzung für die Testbarkeit von Programmen ist die Trennung von UI und Logik, diese Session zeigt, wie dies - ohne die Verwendung eines Framework - mit den einfachsten Möglichkeiten unter VCL & FMX erreichen kann.
Um eine schnellere Entwicklung zu erreichen, werde ich diese Session als Testdriven-Development zeigen.
I just got the confirmation of my session on the Forentage 2017.
I call it:
To achieve a faster development, I will show this session as Testdriven-development.
Lesson is in German language. If I find the time I will do an english video later...
Ich habe gerade die Bestätigung für meine Session auf den Forentage 2017 erhalten.
Ich nenne sie:
MVVM-Lite oder wie man eine Trennung von Form (View) und Logik (ViewModel) mit ein paar Zeilen Code erreichen kann!
Eine Voraussetzung für die Testbarkeit von Programmen ist die Trennung von UI und Logik, diese Session zeigt, wie dies - ohne die Verwendung eines Framework - mit den einfachsten Möglichkeiten unter VCL & FMX erreichen kann.
Um eine schnellere Entwicklung zu erreichen, werde ich diese Session als Testdriven-Development zeigen.
Hello Everybody!
I call it:
MVVM-Lite or how to achieve a separation of form (View) and logic (ViewModel) with a few lines of code!
A prerequisite for the testability of programs is the separation of UI and logic, this session shows how to do this without using a framework - with the simplest possibilities under VCL & FMX.
To achieve a faster development, I will show this session as Testdriven-development.
Lesson is in German language. If I find the time I will do an english video later...
Tuesday, July 11, 2017
Are you using Attributes?
Why not? Too complicate? Not needed?
Let's take a look at this little stupid class:
[ Bar(42) ]
[ FooBar('Test') ]
TFoo = class
private
[ FieldName('StringField') ]
[ FieldLength(30) ]
FField1 : String;
[ FieldName('IntegerField') ]
FField2 : Integer;
end;
How can we get this Attribute-Values?
Over the RTTI of course...
What do you think about this approach:
TRTTIHelper.OnClassHasAttributes( TFoo )
{} .OnAttribute< BarAttribute >(
procedure( Bar : BarAttribute )
begin
_Result1 := Bar.IntValue;
end )
{} .OnAttribute< FooBarAttribute >(
procedure( FooBar : FooBarAttribute )
begin
_Result2 := FooBar.StrValue;
end );
And the fields? Perhaps you prefer this:
TRTTIHelper.OnFieldsHaveAttribute<FieldNameAttribute,FieldLengthAttribute>(TFoo,
Procedure (Field : TRttiField; Attr : FieldNameAttribute)
begin
if Field.Name = 'FField2' then
_Result2 := Attr.Value;
end,
Procedure (Field : TRttiField; Attr : FieldLengthAttribute)
begin
if Field.Name = 'FField1' then
_Result1 := Attr.Value;
end);
This Helper has many overloads like TProc<T1,T2,T3> from System.Sysutils,
Stay tuned for the next update of my FDK and just write:
Uses
Delphiprofi.FDK.RTTI;
Remember:
Let's take a look at this little stupid class:
[ Bar(42) ]
[ FooBar('Test') ]
TFoo = class
private
[ FieldName('StringField') ]
[ FieldLength(30) ]
FField1 : String;
[ FieldName('IntegerField') ]
FField2 : Integer;
end;
How can we get this Attribute-Values?
Over the RTTI of course...
What do you think about this approach:
TRTTIHelper.OnClassHasAttributes( TFoo )
{} .OnAttribute< BarAttribute >(
procedure( Bar : BarAttribute )
begin
_Result1 := Bar.IntValue;
end )
{} .OnAttribute< FooBarAttribute >(
procedure( FooBar : FooBarAttribute )
begin
_Result2 := FooBar.StrValue;
end );
And the fields? Perhaps you prefer this:
TRTTIHelper.OnFieldsHaveAttribute<FieldNameAttribute,FieldLengthAttribute>(TFoo,
Procedure (Field : TRttiField; Attr : FieldNameAttribute)
begin
if Field.Name = 'FField2' then
_Result2 := Attr.Value;
end,
Procedure (Field : TRttiField; Attr : FieldLengthAttribute)
begin
if Field.Name = 'FField1' then
_Result1 := Attr.Value;
end);
This Helper has many overloads like TProc<T1,T2,T3> from System.Sysutils,
Stay tuned for the next update of my FDK and just write:
Uses
Delphiprofi.FDK.RTTI;
Remember:
Rule of Thumb: „Uses is faster than self-typing“!
Friday, June 23, 2017
Delphi hat einen Fehler...?
(Oder wie verbringe ich einen halben Tag mit Fehlannahmen...)
Klar, nicht nur einen, aber so ist das eben mit Software...
Da es keine fehlerfreie Software gibt, kann man diese Frage getrost mit ja beantworten. Aber wie suchen "wir" den Fehler?
Natürlich am besten mit Unit-Tests... Aber UI? OK...Ein anderes Thema
Workflow:
<F9> Testen -> Exception
Exception position ist nicht im eigenen Source, sondern tief in der RTL. Auch noch in einen Assembler-Teil.
OK - Kann nur die Liste nicht initialisiert sein...
Also Breakpoint setzen und nochmal...
<F9> Testen -> Debugger hält brav am Breakpoint an...
FListe in die Watchvariablen übernehmen... Nöö geht nicht... Und dann fängt es an falsch zu laufen...
1. Fehlannahme : OMG, Die IDE kann schon wieder eine Variable nicht anzeigen...
also fix ne lokale Variable "LListe" und mit der arbeiten...
<F9> Testen -> Debugger hält brav am Breakpoint an...
<F7>, <F7>,<F7> - Prima alles richtig... <F7> FListe := LListe;
Bang - Exception;
OK - Logger anwerfen... Geht ja dank FDK mit einer Zeile...
Das Log sieht gut aus... Oberflächlich betrachten... Alles wird schön erzeugt.... Alles Prima!
Aber:
<F9> Testen -> Debugger hält brav am Breakpoint an...
<F7>, <F7>,<F7> - Prima alles richtig... <F7> FListe := LListe;
Bang - Exception;
2. Fehlannahme : Shit, ich Idiot, greife von einem Thread aus auf eine Liste in der Klasse zu...
FListe ist kein Object, aber
kein Thema Uses Delphiprofi.FDK.Classes;
Class -> Class(TClassWithSync) // Erzeugt eine FSync : TObject für einen TMonitor...
TMonitor.Enter(FSync);
try
FListe := LListe;
finally
TMonitor.Exit(FSync);
end;
Jetzt aber....Breakpoint auf die Zuweisung...
<F9> Testen - Exception... What... Der ist gar nicht bis zum BreakPoint gekommen... Nochmal durch steppen...
<F9> Testen - <F7>, <F7>,<F7> - Prima alles richtig... <F7> TMonitor.Enter(FSync) - Bang...
Exception...
Das gibt es doch gar nicht, ich bin doch lokal in der Klasse wieso kann er nicht auf FSync zugreifen...
3. Fehlannahme : Ich habe einen Fehler in 10.2 gefunden... Ich kann aus einem Thread nicht mehr auf private Felder eine einer Klasse zugreifen...(Kaum zu glauben, ist aber so {nicht})
Also das Ganze mit 10.1
<F9> usw... Bang... gleicher Fehler...
Das ist jetzt aber doof... Also schnell den Browser mit dem "System Dashboard" wieder zu machen...
OK.. Dann mal ohne Thread...
Ups... Jetzt geht es... Wieso das den?
Also wieder mit Thread - Am Thread kann es auf keinen Fall liegen, das mache ich immer so... erstmal ein Paar Logeinträge mehr erzeugen...
<F9> Log... Bla, Bla Bla... TMainViewModel.BeforeDestruction - WTF... Wer war das.... Ist doch kein Interface... Also kein Problem mit dem REFCount... Hätte ich doch besser mein MVVM-Framework genommen, aber nein für so einen kleine App...
Breakpoint setzen...
Wird von der MainView aufgerufen mit FreeAndNIL(FViewModel) aber wieso?
Wer lesen kann ist klar im Vorteil... Finde den Fehler...
procedure TFormMain.FormDeactivate(Sender: TObject);
begin
FreeAndNIL(FViewModel);
end;
begin
FreeAndNIL(FViewModel);
end;
Das kommt davon, wenn man auf die schnelle mit der IDE etwas zusammen klicken will... Einfach eine Zeile zu hoch im Objektinspektor....
procedure TFormMain.FormDestroy(Sender: TObject);
begin
FreeAndNIL(FViewModel);
end;
begin
FreeAndNIL(FViewModel);
end;
Wäre besser gewesen...
Ohne den gelernten Workflow -> Ich sehe meinen Fehler nicht - muss am Delphi liegen... Was leider hin und wieder mal vor kommt... Wäre das nicht passiert...
Logisch - und um es richtig zu stellen...
Natürlich geht es jetzt auch mit 10.2 und aus dem Thread...
Kaum macht man es richtig, schon funktioniert es...
Wednesday, June 14, 2017
Schulungs- & Consulting-Termine 2017
Die Nachfrage bezüglich Consulting vor Ort und andere "Programmierhilfen" steigt momentan fast Täglich - was mich sehr freut!
Hierbei geht es von kurzer Hilfe per Skype & TeamViewer bis zu mehrtägigen Schulungen oder Programmieraufträgen.
Vielleicht liegt es an der neue Delphi-Version oder an den kommenden Veränderungen. (iOS 11)
Ich würde daher im 3. oder 4. Quartal - bei einer entsprechenden Teilnehmeranzahl - jeweils eine mehrtägige Schulung anbieten.
Selbstverständlich - wie man es von Mir mittlerweile erwartet - dreht es sich hierbei um Firemonkey.
Aber was ist mit der VCL?
Sourcecode welcher "für" VCL geschrieben ist, wird in der Regel nicht Plattform unabhängig sein, Sourcecode der jedoch für "FMX" geschrieben ist, kann normalerweise ohne Veränderungen auch für VCL-Programme compiliert werden.
Daher braucht man bei non-UI Dingen eigentlich keinen Unterschied machen... Um soliden, testbaren Sourcecode zu schreiben braucht man eigentlich nur folgendes Handwerkszeug: Linken gegen Interfaces, untereinander nicht verlinkte Units und Unittest...
daher:
daher:
Die Themen sind die üblichen Verdächtigen:
- Designpattern- Interfaces
- Unit-Test.
- Threading
- REST / JSON
Darüber hinaus wird immer wieder gefragt:
- Wie mache ich was?
- Mache ich das eigentlich richtig?
- Geht das nicht einfacher?
- MVVM oder Klick-aufs-Form
Frei nach dem Motto: "Usen ist schneller als coden" erhält jeder Teilnehmer mein FDK.
Termine und der Veranstaltungsort stehen noch nicht fest, aber bei Interesse bitte unbedingt vorab schon mal eine E-Mail an mich schreiben mit dem Betreff "Schulungstermine"
Monday, May 22, 2017
Hype Driven Development.
Wer kennt das nicht? Man(n) kommt von einer Tagung oder hat ein cooles YouTube Video gesehen. Dann passiert es - Das muss ich auch machen...
Gut oder schlecht... (Wenn man einige Blogs zu diesem Thema liest ist die Meinung: eher schlecht)
Klar kann man noch mit Delphi 7 mit dem Sprachumfang von UCSD-Pascal programmieren. Eigentlich spricht da nix gegen, oder?
Hey, die Programme laufen und machen das, was die Kunden wünschen - also alles bestens, oder? Viele betreiben so die eigene Firma und verdienen ihr Geld... Also kann es ja nicht schlecht sein!
Aber sollte man nicht hin und wieder über den Tellerrand schauen? Der Satz: "Wir haben das doch immer so gemacht.", wird oft benutzt.
Eigentlich sind doch Programme nie fertig. Es immer mal ein neues Feature eingefügt oder eine Funktionalität verbessert. I.d.R. alles single-Thread, Main-Thread...
Ist das Programm überhaupt noch wartbar? Sollte man mal das Layout überarbeiten, vielleicht das Menü auf Ribbon umstellen oder eine Datenbank verwenden? Die Geschwindigkeit mit Threads verbessern?
Vielleicht hilft ein Hype den Sprung zu schaffen... Klar gibt es dann immer eine Lernkurve, aber ist das den so tragisch? Den alten Kopf mal wieder auf "Klassenarbeit steht an", Niveau bringen...
Oft habe ich bei Schulungen oder Tagungen diese Sätze gehört:
- Interfaces - Ja hab ich schon mal gehört, nutzen wir aber nicht.
- Threads - ja das macht bei uns der Peter, aber der ist seit 4 Wochen krank, wenn der wieder da ist, Frag ich Ihn mal.
- Factory's - brauche ich nicht, es geht auch so.
- Dependency Injection - Du immer mit Deinem neumodischen Zeug.
- Unit Tests - Wollten wir auch mal machen, steht ganz oben auf meiner Liste, aber ich bin bisher nicht dazu gekommen mir das mal an zu sehen.
- Generics - Hab ich schon mal gehört, das ist doch das Ding mit den spitzen Klammer, oder? Ich nehme für sowas immer einen Pointer.
- Git/Mercurial - Ist mir zu kompliziert ich zippe meinen Source einfach zusammen.
- MVVM - Brauch ich nicht, ich kopiere den Source von einem Form in das nächste. Ich will ja auch beim Debuggen sehen, was passiert wenn ich den Button-Klicke.
- JSON - Hab ich noch nie gebraucht, was macht man damit?
Vielleicht wäre hier ein bisschen Hype-Driven-Development angesagt...
Aber warum das Ganze? Wofür soll ich getrennte testbare Units programmieren, wenn ich sowieso keine Unit-Test mache? Sicherlich kann man sich "zu Tode entkoppeln". Ab wann ist zuviel des Guten eigentlich zuviel?
Mit MVVM, Factories und nur gegen Interfaces linken, kann schnell zu einer Sucht werden und die IDE findet bei einem Klick auf die Variable immer nur die Factory oder das Interface, leider NIE die gerade aktuelle Implementierung. Was macht ein Klick auf den Button? Das steht da leider nur dann richtig lesbar, wenn man seine Proceduren wirklich gut benennt. Aber auch dann muss man erstmal die entsprechende Unit (ViewModel) finden, die in dieser Implementierung für diese Plattform verwendet wird.
Eine Interfacevariable wir immer nur mit dem Typen und der Adresse angezeigt - ich sehe im Debugger nicht die Belegung. (Vielleicht mal einen Visualizer programmieren?)
Einfacher wird es nicht und wenn man(n) dann noch unstrukturiert auf neue Techniken los geht - dann ist man(n) schnell in einer Falle die alles noch viel schlimmer macht, als es vorher schon war.
Wäre das der Moment auf meine Schulungs- und Consultingangebote hin zu weisen?
Also doch nicht jeden Hype mit machen, aber sich die "neuen" Techniken rauspicken, die eine bessere Source-Code-Übersicht, besseres Laufzeitverhalten oder höhere Kundenzufriedenheit ermöglichen!
Ich muss nicht jeden Hype mitmachen - nur die Guten...
Subscribe to:
Posts (Atom)