Сделайте Delphi Code более читабельным, используя помощники класса:
Классический звонок:
StoreDataset ( 1 , mysqlDataSet, true);Более читаемый звонок:
mysqlDataSet.StoreSelected_StopAfterFirstError(
function():boolean
begin
Result := mysqlDataSet.FieldByName( ' Status ' ). Value = ' 1 '
end ), fDataStorer);TBYTES Helper - генерировать числа, Zlib Compress, Base64 Encode, 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 : хранить и загружать tbytes из потока или файла. Загрузить и проверить изображение PNG
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 : информация о 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 Helper : 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 : заполните и изменяйте размер TStringGrid
// 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:
| Единица | Помощное описание |
|---|---|
| Helper.tbytes | Позволяет манипулировать массивами байтов: размер, загрузка и сохранение, Getter & Setters |
| Helper.tdataset | Дополнительная функциональность tdataset, такая как: итерация через набор данных или LoadData / SaveData - позволяет составить список объектов в набор данных |
| Helper.tdateTime | Методы, которые позволяют легко манипулировать датой и временем |
| Helper.tfield | Позволяет загружать данные Base64 в поле Blob или проверять подпись хранимых данных |
| Helper.tjsonObject | Методы чтения данных или хранения в структуре JSON DOM, как и ISVALIDISODATE (FieldName) |
| Helper.tstream | Методы, которые облегчают чтение и написание данных в потоках |
Помощники VCL:
| Расширенный класс | Помощное описание |
|---|---|
| TAPPLICATION | Образец помощника, содержащего экспериментальный метод, такой как: InDeveloperMode . |
| Tdbgrid | Методы, манипулирующие столбцами DBGRID, такие как: AutoSizeColumns - автоматически расположены с каждой столбцей |
| Tform | Методы Управление таймерами: setInterval и settimeout |
| Tpicture | Разрешить назначать TBYTES и TBLOBFIELD TPICTURE с автоматическим распознаванием формата изображений |
| Tstringgrid | Заполнение и настройка управления строковой сеткой: загрузка данных, установка ширины столбцов, очистка содержимого ячейки или строки |
| Twincontrol | Методы полезности для поиска управления дочерними управлением по типу или по имени. Видимо для всех потомков Twincontrol: Tform, Tpanel и т. Д. |
Другие помощники:
| Расширенный класс | Помощное описание |
|---|---|
| Helper.tfdconnection | |
| Helper.tfdcustommanager |
Пользовательская конвенция о именовании состоит в том, чтобы добавить Helper суффикса к названию расширенного класса, что означает этот класс -помощник для TDataSet будет иметь имя TDataSetHelper .
Каждый помощник хранится в отдельном файле, а его имя - Helper.<ExpanedClassName>.pas
Все вспомогательные подразделения хранятся в подпапке src - перейдите в это место.
examples/01-playground/ - Перейдите в это местоHelperPlayground.dprHelper.TStringGrid.pasHelper.TDataSet.pas и Helper.TDBGrid.pasHelper.TBytes.pas and Helper.TStream.pasexamples/02-formhelper/HelpersMiniDemo.dprHelper.TForm.pas и использование таймера вспомогательные методыОгромное количество кода VCL (FMX) может быть очищено с использованием помощников класса, которые на самом деле являются легким методом рефакторинга с низким риском для сложных проектов. Используя этот метод, команды могут начать обновлять свои устаревшие проекты даже без модульных тестов безопасности. Более того, проверка недавно созданных помощников может быть легко сделана с помощью модульных тестов. Этот подход позволяет научить разработчиков правильно писать модульные тесты (учиться на практике первыми принципами или другими). Команды также могут легко применять процесс разработки TDD (сначала записать тесты, а затем реализовать функциональность) в веселом и неинвазивном способе.
Иногда помощники класса также могут быть опасными, если они используются неправильно. По этой причине необходимо применить немного более дисциплинированного процесса разработки и доставки, предложения, связанные с этой областью, рассматриваются в следующих разделах.
Пользователи класса: преимущества:
С самого начала (Delphi 2006) до версии Delphi Berlin / 10.1 была довольно популярная Helper Class Helper, которая позволяет получить доступ к частным полям и частным методам с использованием помощников. Из -за этой ошибки многие разработчики определили это интересное расширение языка с таким взломом. Неправомерное использование помощников классов вызвало недооценку, что ценность этого супер мощного решения.
Одной из важных целей использования помощников класса является способность извлечь полезный и многократный код, а затем покрывать их модульными тестами. Разработчики могут даже легко использовать TDD, тестовый подход, в котором сначала нам нужно написать модульные тесты, а затем реализовать логику
Этот репозиторий демонстрирует, как практиковать подход TDD. Каждый класс и вспомогательный помощник имеет тест DUNITX. Модельные испытательные наборы могут быть легко расширены, чтобы обеспечить лучшие тестовые покрытия. Чтобы иметь лучший опыт работы с модуль, рекомендуется установить лучшую TDD Delphi IDE Extension Testinsight - бесплатная и очень продуктивная платформа, созданная Stefan Glienke. Слава автору! Ссылка на Testinsight Repo: перейдите на сайт Bitbucket
Образец единичного теста можно найти в папке репозитории tests - перейдите в это место
Образец испытания метода Helper ColsWidth TStringGrid Class Tstringgrid:
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 ;Помощники класса выглядят действительно многообещающими в попрошайничестве, и на самом деле есть отличное решение, но, когда вы создаете и используете все больше и больше из них, вы начнете замечать некоторые препятствия. По этой причине перед началом должна быть адаптирована надлежащая практика, чтобы помочь избежать потенциальных проблем.
Одной из рекомендуемых практик при использовании помощников класса является планирование хорошего обслуживания проекта, включая управление версиями и управление выпуском. Проверенные шаги, включая два важных момента:
Этот проект GitHub является живым примером таких методов развертывания. Мы используем модель ветвления, вдохновленную в блоге Vincent Driessen: успешная модель ветвления GIT вместе с моделью планирования и доставки, вдохновленной методом Kanban.
Классовые помощники проекта

is021-grid-column-restore предназначен для новой функции: Method LoadColumnsFromJsonString в TDBGrid Class Helper, который позволяет восстановить конфигурацию столбца (порядок, заголовок, ширина и видимость), хранящиеся в строке JSON. Определение функции написано в выпуске № 21 GitHubis014-doc-dark-side является новым разделом документации в основном файле README.md .Классовые помощники проекта Канбан

Канбанский совет и сессии планирования являются предлагаемыми методами для достижения - постепенной доставки. Проект помощников класса не может быть доставлен слишком часто, из -за стоимости интеграции (Helper Repository Class Class с окончательными проектами Delphi). А с другой стороны доставки новой версии не должна занять слишком много времени, потому что все проекты должны использовать преимущества новых помощников (высокая повторная возможность).
Помощники класса выглядят очень красиво в первом контакте, но они имеют некоторые опасные побочные эффекты. В этом разделе вы можете лучше понять слабости этого решения. Если вы попытаетесь определить двух помощников класса, расширяющих тот же базовый класс, вы увидите, что будет видна только один из них. Более того, вы не можете расширить функциональность классов помощников с наследством. Также вы не можете определить дополнительную память (поля) у помощника класса.
Вы можете защитить свой проект от последствий этих слабостей. Перед определением нового помощника класса вы должны задать себе несколько вопросов:
TButton ) не для более общего ( TControl , TComponent и т. Д.).