Machen Sie den Delphi -Code mit Klassenhelfern lesbarer:
Klassischer Anruf:
StoreDataset ( 1 , mysqlDataSet, true);Mehr lesbarer Anruf:
mysqlDataSet.StoreSelected_StopAfterFirstError(
function():boolean
begin
Result := mysqlDataSet.FieldByName( ' Status ' ). Value = ' 1 '
end ), fDataStorer);TBYTES HELPER - Zahlen erzeugen, ZLIB -Kompress, Base64 codieren, Calc CRC32
uses
Helpers.TBytes;
type
TUploadImageCommand = record
Image: string;
ControlSum: integer;
end ;
procedure SendCommandToRestServer ( const aCommand: TUploadImageCommand);
begin
writeln( ' Use RestClient or IdHttpClient to send POST request ' );
writeln( ' POST /rest/upload-image/ TUploadImageCommand ' );
writeln( ' TUploadImageCommand: ' );
writeln( ' ControlSum = ' , aCommand.ControlSum);
writeln( ' Image Length = ' , Length(aCommand.Image));
writeln( ' Image = ' , aCommand.Image);
end ;
var
bytes: TBytes;
idx: integer;
memoryStream: TMemoryStream;
command := TUploadImageCommand;
begin
bytes.Size := 1000 ;
for idx := 0 to bytes.Size- 1 do
bytes[idx] := idx div 10 ;
memoryStream := TMemoryStream.Create();
bytes := CompressToStream(memoryStream);
command.Image := bytes.GenerateBase64Code();
command.ControlSum := bytes.GetSectorCRC32( 0 , bytes.Size);
SendCommandToRestServer(command);
end .TBYTES HELPER : Speichern und laden Sie TBYTes aus Stream oder Datei. Laden und überprüfen Sie das PNG -Bild
uses
Helpers.TBytes;
var
bytes: TBytes;
idx: integer;
memoryStream: TMemoryStream;
command := TUploadImageCommand;
begin
bytes.InitialiseFromBase64String( ' U2FtcGxlIHRleHQ= ' );
bytes.SaveToFile( ' notes.txt ' ); // save: Sample text
memoryStream:= bytes.CreateStream();
// memoryStream.Size = 11
memoryStream.Free;
// -----------------
s := bytes.GetSectorAsString( 0 , 6 ); // ASCII only text
bytes := [ 0 , 0 , 15 , 16 , $A0, 255 , 0 , 0 , 0 , 0 , 1 ];
if bytes.GetSectorAsHex( 2 , 4 ) = ' 0F 10 A0 FF ' then
begin
memoryStream := TMemoryStream.Create();
memoryStream.LoadFromFile( ' small.png ' );
memoryStream.Position := 0 ;
signature.LoadFromStream(memoryStream, 8 );
if (signature.GetSectorAsHex = ' 89 50 4E 47 0D 0A 1A 0A ' ) and
(signature.GetSectorAsString( 1 , 3 ) = ' PNG ' ) then
begin
memoryStream.Position := 0 ;
pngImage := TPngImage.Create;
pngImage.LoadFromStream(memoryStream);
// Image1.Picture := pngImage;
pngImage.Free;
end ;
memoryStream.Free;
end ;
end ;TDATETIME HELPER : Informationen über Tdatetime
uses
Helpers.TDateTime;
var
date: TDateTime;
begin
date := EncodeDate( 1989 , 06 , 04 );
writeln(date.AsYear); // 1989
writeln(date.AsMonth); // 06
writeln(date); // 06/04/1989
writeln(EncodeDate( 2017 , 10 , 24 ).DayOfWeek); // 3
writeln(date.IncMonth( 5 ).ToString( ' yyyy-mm-dd ' ); // 1989-11-04
writeln(date.AsStringDateISO); // 1989-06-04
date := EncodeDate( 2019 , 10 , 24 ) + EncodeTime( 18 , 45 , 12 , 0 );
writeln(date.AsStringDateISO); // 2019-10-24T18:45:12.000Z
end .Tdataset helfer : foreachrow, loaddata <>, savedata <>
uses
Helpers.TDataSet;
type
TCity = class
public
id: Integer;
City: string;
Rank: Variant;
visited: Variant;
end ;
var
dataset: TDataSet;
cityNames: TArray<string>;
idx: integer;
cities: TObjectList<TCityForDataset>;
begin
dataset := GivenDataSet(fOwner, [
{ } [ 1 , ' Edinburgh ' , 5.5 , EncodeDate( 2018 , 05 , 28 )],
{ } [ 2 , ' Glassgow ' , 4.5 , EncodeDate( 2015 , 09 , 13 )],
{ } [ 3 , ' Cracow ' , 6.0 , EncodeDate( 2019 , 01 , 01 )],
{ } [ 4 , ' Prague ' , 4.9 , EncodeDate( 2013 , 06 , 21 )]]);
SetLength(cityNames, dataset.RecordCount);
idx := 0 ;
dataset.ForEachRow(
procedure
begin
cityNames[idx] := dataset.FieldByName( ' city ' ).AsString;
inc(idx);
end );
writeln(string.Join( ' , ' , citiecityNamess));
cities := dataset.LoadData<TCityForDataset>();
witeln(cities.Count); // 4
witeln(cities[ 0 ].City); // Edinburgh
witeln(cities[ 3 ].Rank); // 4.9
cities[ 2 ].Rank := 5.8 ;
cities[ 2 ].visited := EncodeDate( 2020 , 7 , 22 );
cities.Add(TCity.Create());
cities[ 4 ].id := 5 ;
cities[ 4 ].City := ' Warsaw ' ;
dataset.SaveData<TCity>(cities);
// SaveData updated Cracow record and added Warsaw
endTstringGrid Helper : Füllen und ändern Sie die Größe des Tstringgrids
// StringGrid1: TStringGrid;
// StringGrid2: TStringGrid;
procedure TForm1.Button1Click (Sender: TObject);
var
structure, rows: string;
begin
StringGrid1.ColCount := 4 ;
StringGrid1.RowCount := 3 ;
StringGrid1.ColsWidth([ 40 , 100 , 90 , 110 , 80 ]);
StringGrid1.FillCells([
[ ' 1 ' , ' Jonh Black ' , ' U21 ' , ' 34 ' ],
[ ' 2 ' , ' Bogdan Polak ' , ' N47 ' , ' 28 ' ]]);
structure :=
' {"column": "no", "caption": "No.", "width": 30}, ' +
' {"column": "mesure", "caption": "Mesure description", "width": 200}, ' +
' {"column": "value", "caption": "Value", "width": 60} ' ;
rows :=
' {"no": 1, "mesure": "Number of DI Containers", "value": 120}, ' +
' {"no": 2, "mesure": "Maximum ctor injection", "value": 56} ' ;
data
jsData := TJSONObject.ParseJSONValue(Format(
' {"structure": [%s], "data": [%s]} ' , [structure, rows])
) as TJSONObject;
StringGrid2.FillWithJson(jsData);
end ;RTL -Helfer:
| Einheit | Helferbeschreibung |
|---|---|
| Helper.tBytes | Ermöglicht es, Arrays von Bytes zu manipulieren: Größe, Laden und Speichern, Getter & Setzer |
| Helper.tdataset | Zusätzliche Tdataset -Funktionalität wie: Iterieren durch Datensatz oder loadData / spartedata - ermöglicht es, eine Liste von Objekten dem Datensatz zuzuordnen |
| Helper.tdatetime | Methoden, die es leicht manipulieren lassen, Datum und Uhrzeit zu manipulieren |
| Helper.tfield | Ermöglicht das Laden von Base64 -Daten in das BLOB -Feld oder die Überprüfung der Signatur der gespeicherten Daten |
| Helper.tjsonObject | Methoden lesen Daten oder Speichern in der JSON -Dom -Struktur wie Isvalidisodat (Feldname) |
| Helper.tstream | Methoden, die das Lesen und Schreiben von Daten in Streams erleichtern |
VCL -Helfer:
| Erweiterte Klasse | Helferbeschreibung |
|---|---|
| Tapplikation | Probenhelfer mit experimenteller Methode wie: InDeveloperMode . |
| Tdbgrid | Methoden manipulieren DBGrid -Spalten wie: AutoSizeColumns - automatisch mit jeder Spalte anordnen |
| Tform | METHODEN DER TIMERUNGEN: SETInterval und SetTimeout |
| TPicture | Erlauben Sie TBOBField TBICTure mit automatischer Bildformaterkennung zuzuweisen |
| Tstringgrid | Füllen und Konfigurieren von String Grid Control: Laden von Daten, Einstellungsspalten Breite einstellen, Inhalt von Zellen oder Zeile löschen |
| Twincontrol | Versorgungsmethoden zur Suche nach untergeordneten Steuerelementen nach Typ oder Namen. Für alle Twincontrol -Nachkommen sichtbar: tform, tpanel usw. |
Andere Helfer:
| Erweiterte Klasse | Helferbeschreibung |
|---|---|
| Helper.tfdConnection | |
| Helper.tfdcustommanager |
Helfer -Namenskonvention besteht darin, Suffix Helper zum Namen der erweiterten Klasse hinzuzufügen, was bedeutet, dass der Klassenhelfer für TDataSet einen Namen TDataSetHelper hat.
Jeder Helfer wird in einer separaten Datei gespeichert und ist Helper.<ExpanedClassName>.pas .
Alle Helfereinheiten werden im src -Unterordner gespeichert - gehen Sie zu diesem Ort.
examples/01-playground/ - Gehen Sie zu diesem OrtHelperPlayground.dprHelper.TStringGrid.pasHelper.TDataSet.pas und Helper.TDBGrid.pasHelper.TBytes.pas und Helper.TStream.pasexamples/02-formhelper/ - Gehen Sie zu diesem OrtHelpersMiniDemo.dprHelper.TForm.pas und Verwendung von Timer A Helper -MethodenDer riesige VCL -Code (FMX) kann mit Klassenhelfern gelöscht werden, was tatsächlich eine einfache Wiederaufbauungstechnik mit geringem Risiko für komplexe Projekte darstellt. Mit dieser Methode können Teams ihre Legacy -Projekte auch ohne Sicherheitsnetz der Unit -Tests mit der Aktualisierung ihrer Legacy -Projekte beginnen. Darüber hinaus kann die Überprüfung neu erstellter Helfer einfach mit Unit -Tests durchgeführt werden. Mit diesem Ansatz ermöglichen es den Entwicklern beizubringen, wie man Unit -Tests korrekt schreibt (in der Praxis lernen die ersten Grundsätze oder andere). Teams können auch den TDD-Entwicklungsprozess (zuerst schreiben und dann Funktionen schreiben) auf unterhaltsame und nicht-invasive Weise anwenden.
Manchmal können Klassenhelfer auch gefährlich sein, wenn sie nicht ordnungsgemäß eingesetzt werden. Aus diesem Grund ist es erforderlich, etwas mehr disziplinierter Entwicklungs- und Lieferprozess anzuwenden. In den folgenden Abschnitten werden Vorschläge in Verbindung gebracht.
Klassenhelfer Vorteile:
Von Anfang an (Delphi 2006) bis zur Delphi Berlin / 10.1 -Version gab es ein beliebter Klassenhelferfehler, mit dem auf private Felder und private Methoden mithilfe von Helfern zugreifen kann. Aufgrund dieses Fehlers identifizierten viele Entwickler diese interessante Spracherweiterung mit einem solchen Hack. Der Missbrauch von Klassenhelfern hat dazu geführt, dass dieser Wert dieser supermächtigen Lösung unterschätzt wird.
Einer der wichtigsten Zwecke für die Verwendung von Klassenhelfern ist die Fähigkeit, nützlichen und wiederverwendbaren Code zu extrahieren und sie dann mit Einheitstests abzudecken. Entwickler können sogar problemlos TDD, Testgetriebenen Ansatz verwenden, bei dem wir zuerst Unit -Tests schreiben und dann die Logik implementieren müssen
Dieses Repository zeigt, wie man den TDD -Ansatz übt. Jede Klasse und jede Aufzeichnungshelfer hat einen Dunitx -Test. Unit -Testsätze können leicht erweitert werden, um eine bessere Testabdeckung zu erzielen. Um ein besseres Erlebnis der Unit -Tests zu erzielen, wird empfohlen, die beste TDD Delphi IDE Extension TestInsight zu installieren - kostenlos und eine sehr produktive Plattform, die von Stefan Glienke erstellt wurde. Ruhm dem Autor! Link zum TestInsight Repo: Gehen Sie zur Bitbucket -Site
Der Test -Unit -Test finden Sie in tests Repository -Ordner - Gehen Sie zu diesem Speicherort
Probentest der TStringGrid -Klasse Helper ColsWidth -Methode:
procedure TestTStringGridHelper.FiveColumns_ColsWidth ;
begin
fGrid.ColCount := 5 ;
fGrid.ColsWidth([ 50 , 100 , 90 , 110 , 80 ]);
Assert.AreEqual( 110 , fGrid.ColWidths[ 3 ]);
Assert.AreEqual( 80 , fGrid.ColWidths[ 4 ]);
end ;Klassenhelfer sehen im Betteln sehr vielversprechend aus und tatsächlich gibt es eine großartige Lösung, aber wenn Sie immer mehr von ihnen erstellen und verwenden, werden Sie einige Hindernisse bemerken. Aus diesem Grund sollten gute Praktiken von Anfang an angepasst werden, um potenzielle Probleme zu vermeiden.
Eine der empfohlenen Praktiken bei der Verwendung von Klassenhelfern ist die Planung einer guten Projektwartung, einschließlich der Versionskontrolle und des Freigabemanagements. Nachgewiesene Schritte einschließlich zwei wichtiger Punkte:
Dieses GitHub -Projekt ist ein Live -Beispiel für solche Bereitstellungstechniken. Wir verwenden das von Vincent Driessen Blog Post inspirierte Verzweigungsmodell: ein erfolgreiches Git -Verzweigungsmodell zusammen mit dem Planing- und Liefermodell, das von der Kanban -Methode inspiriert ist.
Klassenhelfer Projektzweigungsmodell

is021-grid-column-restore ist für neue Funktionen: Methode LoadColumnsFromJsonString in TDBGrid-Klasse-Helfer, mit der die in JSON String gespeicherte Spaltenkonfiguration (Auftrag, Titelbeschreibung, Breite und Sichtbarkeit) wiederhergestellt werden kann. Die Feature -Definition wird in GitHub Ausgabe #21 geschriebenis014-doc-dark-side ist ein neuer Dokumentationsabschnitt in der Hauptdatei main README.md .Klassenhelfer projizieren Kanban Board

Kanban Board- und Planungssitzungen werden vorgeschlagene Techniken zur Erzielung einer inkrementellen Lieferung vorgeschlagen. Das Projekt für Klassenhelfer kann aufgrund von Integrationskosten (Integration Class -Helfer -Repository mit endgültigen Delphi -Projekten) nicht zu oft geliefert werden. Und von der anderen Seitenübergabe der neuen Version sollte nicht zu lange dauern, da alle Projekte Vorteile neuer Helfer nutzen sollten (hohe Wiederverwendbarkeit).
Klassenhelfer sehen im ersten Kontakt sehr gut aus, haben aber einige gefährliche Nebenwirkungen. In diesem Abschnitt können Sie die Schwächen dieser Lösung besser verstehen. Wenn Sie versuchen, zwei Klassenhelfer zu definieren, die dieselbe Basisklasse erweitern, werden Sie feststellen, dass nur einer von ihnen sichtbar ist. Mehr dazu können Sie nicht in der Lage sein, die Erbschaftsfunktionalität der Klassenhelfer zu erweitern. Sie können auch keinen zusätzlichen Speicher (Felder) im Klassenhelfer definieren.
Sie können Ihr Projekt vor den Auswirkungen dieser Schwächen schützen. Bevor Sie einen neuen Klassenhelfer definieren, sollten Sie sich ein paar Fragen stellen:
TButton ) nicht für allgemeine ( TControl , TComponent usw.).