اجعل رمز Delphi أكثر قابلية للقراءة باستخدام مساعدي الفصل:
المكالمة الكلاسيكية:
StoreDataset ( 1 , mysqlDataSet, true);المزيد من المكالمة القابلة للقراءة:
mysqlDataSet.StoreSelected_StopAfterFirstError(
function():boolean
begin
Result := mysqlDataSet.FieldByName( ' Status ' ). Value = ' 1 '
end ), fDataStorer);Tbytes Helper - إنشاء أرقام ، ضغط ZLIB ، 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 : تخزين وتحميل 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 : معلومات حول 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
endالمساعد tstringgrid : املأ وتغيير حجم 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 (اسم الميدان) |
| Helper.tstream | الأساليب التي تسهل قراءة البيانات وكتابةها إلى تدفقات |
مساعدون VCL:
| فئة موسعة | وصف المساعد |
|---|---|
| tapplication | عينة المساعد يحتوي على طريقة تجريبية مثل: InDeveloperMode . |
| tdbgrid | طرق معالجة أعمدة DBGRID ، مثل: AutoSizeColumns - الترتيب تلقائيًا مع كل عمود |
| tform | طرق إدارة الموقتات: setInterval و setTimeout |
| tpicture | السماح لتعيين tbytes و tblobfield إلى tpicture مع التعرف على تنسيق الصور التلقائي |
| tstringgrid | ملء وتكوين التحكم في شبكة السلسلة: تحميل البيانات ، إعداد الأعمدة ، عرض محتوى الخلية أو الصف |
| Twincontrol | طرق الأداة المساعدة للبحث عن عناصر تحكم الطفل حسب النوع أو بالاسم. مرئي لجميع أحفاد التوأم: tform ، tpanel ، إلخ. |
مساعدون آخرون:
| فئة موسعة | وصف المساعد |
|---|---|
| helper.tfdconnection | |
| Helper.tfdCustomManager |
تتمثل اتفاقية التسمية المساعقة في إضافة اللاحقة Helper إلى اسم الفئة الموسعة ، ما الذي يعني أن المساعد الفئة لـ TDataSet Will له اسم TDataSetHelper .
يتم تخزين كل مساعد في ملف منفصل ووحدة اسمه هو Helper.<ExpanedClassName>.pas .
يتم تخزين جميع وحدات المساعدة في المجلد الفرعي src - انتقل إلى هذا الموقع.
examples/01-playground/ - انتقل إلى هذا الموقعHelperPlayground.dprHelper.TStringGrid.pasHelper.TDataSet.pas و Helper.TDBGrid.pasHelper.TBytes.pas و Helper.TStream.pasexamples/02-formhelper/ - انتقل إلى هذا الموقعHelpersMiniDemo.dprHelper.TForm.pas واستخدام مؤقت أساليب المساعديمكن مسح الكمية الضخمة من رمز VCL (FMX) باستخدام مساعدي الفئة ، والتي هي في الواقع تقنية إعادة تهيئة سهلة مع مخاطر منخفضة للمشاريع المعقدة. باستخدام هذه الطريقة ، يمكن للفرق البدء في ترقية مشاريعها القديمة حتى بدون اختبار شبكة الأمان. علاوة على ذلك ، يمكن بسهولة التحقق من المساعدين الذين تم إنشاؤهم حديثًا باستخدام اختبارات الوحدة. يسمح هذا النهج بتعليم المطورين كيفية كتابة اختبارات الوحدة بطريقة صحيحة (تعلم في الممارسة الأولى المبادئ أو غيرها). يمكن للفرق أيضًا تطبيق عملية تطوير TDD بسهولة (كتابة اختبارات أولاً ثم تنفيذ الوظائف) بطريقة ممتعة وغير جراحية.
في بعض الأحيان يمكن أن يكون مساعدو الفصل خطيرًا أيضًا إذا تم استخدامهم بشكل غير صحيح. لهذا السبب ، يتعين على تطبيق تطوير وتسليم أكثر انضباطًا ، يتم تغطية الاقتراحات المرتبطة بهذه المنطقة في الأقسام التالية.
فوائد المساعدين الصف:
منذ البداية (Delphi 2006) حتى إصدار Delphi Berlin / 10.1 كان هناك خطأ شائع جدًا للصف من الدرجة ، والذي يسمح للوصول إلى الحقول الخاصة والأساليب الخاصة باستخدام المساعدين. بسبب هذا الخطأ ، حدد العديد من المطورين امتداد اللغة المثيرة للاهتمام بمثل هذا الاختراق. تسببت سوء استخدام المساعدين في الفصل في أن قيمة هذا الحل القوي الفائق يتم التقليل من شأنها.
أحد الأغراض المهمة لاستخدام مساعدي الفصل هو قدرة استخراج التعليمات البرمجية المفيدة والقابلة لإعادة الاستخدام ، ثم تغطيها مع اختبارات الوحدة. يمكن للمطورين حتى استخدام TDD بسهولة ، واختبار النهج الذي نحتاج فيه أولاً إلى كتابة اختبارات الوحدة ثم تنفيذ المنطق
هذا المستودع يوضح كيفية ممارسة نهج TDD. كل فئة ومساعد سجل لديه اختبار Dunitx. يمكن توسيع مجموعات اختبار الوحدة بسهولة لتوفير تغطية اختبار أفضل. للحصول على تجربة اختبار أفضل للوحدة ، يوصى بتثبيت أفضل TDD Delphi IDE Extension TestInsight - مجاني ومنصة مثمرة للغاية أنشأتها Stefan Glienke. المجد للمؤلف! رابط إلى TestInsight Repo: انتقل إلى موقع Bitbucket
يمكن العثور على اختبار وحدة العينة في مجلد مستودع tests - انتقل إلى هذا الموقع
عينة اختبار TStringGrid CLESS ColsWidth طريقة:
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 ، والذي يسمح بتكوين العمود (الطلب ، تعليق العنوان ، العرض والرؤية) المخزنة في سلسلة JSON. تعريف الميزة مكتوبة في GitHub العدد رقم 21is014-doc-dark-side هو قسم وثائق جديد في ملف README.md الرئيسي.مشروع المساعدين الفئة مشروع Kanban

يتم اقتراح تقنيات مجلس إدارة Kanban - تقنيات لتحقيقها - التسليم التدريجي. لا يمكن تسليم مشروع المساعدين في الفصل في كثير من الأحيان ، بسبب تكلفة التكامل (مستودع المساعد للتكامل مع مشاريع دلفي النهائية). ومن بين الجانبية الأخرى ، يجب ألا يستغرق التسليم الجانبي للنسخة الجديدة وقتًا طويلاً ، لأن جميع المشاريع يجب أن تستخدم مزايا المساعدين الجدد (قابلية إعادة الاستخدام العالية).
يبدو أن مساعدي الفصل طيفين حقًا على الاتصال الأول ، لكن لديهم بعض الآثار الجانبية الخطرة. في هذا القسم ، يمكنك فهم نقاط ضعف هذا الحل بشكل أفضل. إذا حاولت تحديد مساعدين في الفصل يوسعان نفس الفصل الأساسي ، فسترى أن واحدًا منهم فقط سيكون مرئيًا. أكثر من ذلك أنت غير قادر على توسيع وظائف مساعد الصف مع الميراث. كما أنك غير قادر على تحديد ذاكرة إضافية (الحقول) في مساعد الفصل.
يمكنك حماية مشروعك من آثار نقاط الضعف هذه. قبل تحديد مساعد صف جديد ، يجب أن تسأل نفسك بعض الأسئلة:
TButton ) ليس أكثر عمومية ( TControl ، TComponent ، إلخ).