بعد قراءة كتاب "إنشاء كود جيد التصميم (استنادًا إلى دلفي/VCL)" الذي كتبته آخر مرة، أخبرني العديد من الأصدقاء أنني شعرت أنني أستطيع قبول وجهات النظر الواردة فيه، ولكن يبدو أنه بسيط جدًا وغير محدد بدرجة كافية؛ كما أعرب بعض الأصدقاء عن شكوكهم حول هذا الموضوع، وهو مثال صغير على بعض الاعتراضات. ومن هنا هذه المقالة.
في المرة الأخيرة، كان المثال الذي قدمته هو هذا: لنفترض أنك تريد الحصول على قائمة من السلاسل من مكان ما ثم عرضها في TListBox، الكود الذي أوصي به هو:
ObjectXXX := TObjectXXX.Create;
ListBox1.Items := ObjectXXX.GetStringList;
ObjectXXX.Free;
في الواقع، أعترف أنه انطلاقًا من هذه الأسطر الثلاثة من التعليمات البرمجية وحدها، يبدو أنها مشتبه بها في "إساءة استخدام الكائن". ربما يكون المثال بسيطًا جدًا، مما يعطي الانطباع بأن TObjectXXX لديه وظيفة عضو عام واحدة فقط، وهي GetStringList. إذا كان هذا صحيحًا، فهذا في الواقع "إساءة استخدام للكائن". الفئة عبارة عن تجريد لكائن ما، ويتكون الكائن من مجموعة من الحالات والعمليات (أي البيانات والعمليات على البيانات). لذلك، فإن الكائن الذي ليس له حالة ليس كائنًا! تصميم فئة بدون أعضاء بيانات خاصة هو تصميم فاشل (هذا ليس فئة، بل واجهة).
حسنًا، دعني أعطيك مثالاً تفصيليًا لتوضيح كيفية فصل رمز الواجهة ورمز الوظيفة.
لنفترض أنني أريد إنشاء برنامج بسيط لإدارة دفتر العناوين الشخصي. من الواضح أن البرنامج بأكمله مقسم إلى جزأين: جزء واحد موجه نحو المستخدم، وهو ما يسمى بجزء الواجهة الذي يمكنني توفيره بأربعة أزرار (على التوالي "إضافة"). "، يتم استخدام "الحذف" و"التعديل" و"البحث") ومربع التحرير (عرض معلومات دفتر العناوين وقبول إدخال المستخدم) للتفاعل مع المستخدم؛ أما الجزء الآخر فهو وظيفي، أي عملية الوصول إلى دفتر العناوين داخل البرنامج.
لذلك، هناك فئة TAddrBook، وهي عبارة عن تجريد للجزء الوظيفي.
TAddrBook = class
خاص
// بعض الأعضاء الخاصين
عام
إنشاء المنشئ؛
تدمير المدمر؛ تجاوز؛
GetCount: عدد صحيح؛
FindRecord(strString): عدد صحيح؛
GetRecord(nIndex:Integer): String;
SetRecord(nIndex:integer; strRec:String): Boolean;
AddRecord(strRec:String): Boolean;
DelRecord(nIndex): منطقي؛
// وظائف الأعضاء المشتركة الأخرى
نهاية؛
يعتمد سبب عدم إمكانية تحديد الأعضاء الخاصين بشكل أساسي على تطبيق هذه الفئة.
وبهذه الطريقة، يمكن تغليف منطق عمليات الوصول إلى دفتر العناوين. لن يتضمن الكود الموجود في جزء الواجهة منطق الوصول هذا. رمز جزء الواجهة كما يلي:
فار
Form1: TForm1؛
أددربوك: تادربوك؛
nCurRec: عدد صحيح؛
تطبيق
الإجراء TForm1.FormCreate(Sender: TObject);
يبدأ
AddrBook := TAddrBook.Create;
nCurRec := AddrBook.GetCount;
نهاية؛
الإجراء TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
يبدأ
AddrBook.Free;
نهاية؛
// إضافة زر
الإجراء TForm1.Button1Click(Sender: TObject);
يبدأ
إذا لم يكن AddrBook.AddRecord(memo1.Text) ثم
ShowMessage("خطأ");
نهاية؛
// زر الحذف
الإجراء TForm1.Button2Click(Sender: TObject);
يبدأ
إذا لم يكن AddrBook.DelRecord(nCurRec) إذن
ShowMessage("خطأ");
نهاية؛
// تعديل الزر
الإجراء TForm1.Button3Click(Sender: TObject);
يبدأ
إذا لم يكن AddrBook.SetRecord(nCurRec, memo1.Text) إذن
ShowMessage("خطأ");
نهاية؛
//زر البحث
الإجراء TForm1.Button4Click(Sender: TObject);
يبدأ
memo1.Text := AddrBook.GetRecord(AddrBook.FindRecord(memo1.Text));
نهاية؛
لا يتضمن الكود الموجود في جزء الواجهة أعلاه أي منطق وصول، رمز كل وحدة بسيط وسهل الفهم وسهل الصيانة. في الواقع، لا يعرف رمز الواجهة ما إذا كان دفتر العناوين محفوظًا في قاعدة بيانات أو ملف نصي. إذا تم استخدام قاعدة بيانات، فلا يعرف ما إذا كان يتم الوصول إلى قاعدة البيانات من خلال ODBC أو ADO أو BDE. في الواقع، تعتمد منطق الوصول هذه على تطبيق فئة TAddrBook، ويمكن وضع تطبيق فئة TAddrBook في ملف .pas منفصل، ولن تؤثر أي تغييرات على تطبيق فئة TAddrBook على جزء الواجهة. عند صيانة التعليمات البرمجية، فمن الحكمة قصر التغييرات على وحدة واحدة.
Nicrosoft([email protected]) بتاريخ 2001.7.14