ทำให้รหัส Delphi อ่านง่ายขึ้นโดยใช้ผู้ช่วยชั้นเรียน:
โทรคลาสสิก:
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) |
| ผู้ช่วย | วิธีการที่อำนวยความสะดวกในการอ่านและเขียนข้อมูลไปยังสตรีม |
ผู้ช่วย VCL:
| ชั้นเรียนขยาย | คำอธิบายผู้ช่วย |
|---|---|
| การใช้ | ผู้ช่วยตัวอย่างที่มีวิธีการทดลองเช่น: InDeveloperMode |
| tdbgrid | วิธีการจัดการคอลัมน์ DBGrid เช่น: AutosizeColumns - จัดเรียงโดยอัตโนมัติในแต่ละคอลัมน์ |
| รูปปั้น | วิธีการจัดการตัวจับเวลา: 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 และ 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 - ไปที่ตำแหน่งนั้น
การทดสอบตัวอย่างของ Helper คลาส TStringGrid วิธี 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 เป็นส่วนเอกสารใหม่ในไฟล์ Main README.mdผู้ช่วยชั้นเรียนโครงการ Kanban Board

Kanban Board และการวางแผนเป็นเทคนิคที่แนะนำเพื่อให้บรรลุ - การส่งมอบที่เพิ่มขึ้น โครงการผู้ช่วยชั้นเรียนไม่สามารถส่งได้บ่อยเกินไปเนื่องจากค่าใช้จ่ายในการรวม (ที่เก็บผู้ช่วยระดับผู้ช่วยรวมกับโครงการ Delphi ขั้นสุดท้าย) และจากการส่งมอบด้านอื่น ๆ ของเวอร์ชันใหม่ไม่ควรใช้เวลานานเกินไปเนื่องจากโครงการทั้งหมดควรใช้ข้อได้เปรียบของผู้ช่วยใหม่ (ความสามารถในการนำกลับมาใช้ใหม่ได้สูง)
ผู้ช่วยชั้นเรียนดูดีมากในการติดต่อครั้งแรก แต่พวกเขามีผลข้างเคียงที่อันตราย ในส่วนนี้คุณสามารถเข้าใจจุดอ่อนของโซลูชันนี้ได้ดีขึ้น หากคุณพยายามกำหนดผู้ช่วยสองชั้นที่ขยายชั้นเรียนพื้นฐานเดียวกันคุณจะเห็นว่ามีเพียงหนึ่งในนั้นเท่านั้นที่จะมองเห็นได้ ยิ่งไปกว่านั้นคุณจะไม่สามารถขยายฟังก์ชั่นผู้ช่วยในชั้นเรียนด้วยการสืบทอด นอกจากนี้คุณไม่สามารถกำหนดหน่วยความจำเพิ่มเติม (ฟิลด์) ในผู้ช่วยชั้นเรียน
คุณสามารถปกป้องโครงการของคุณจากผลกระทบของจุดอ่อนเหล่านี้ ก่อนที่จะกำหนดผู้ช่วยชั้นเรียนใหม่คุณควรถามตัวเองสองสามคำถาม:
TButton ) ไม่ใช่สำหรับทั่วไปมากขึ้น ( TControl , TComponent ฯลฯ )