البرمجة غرضية التوجه :
قد تتسائل كثيرا ماهي غرضية التوجه هذه ولماذا هذة الزحمة الإعلانية لها,
حسنا برأيي أنه ربما تكون الإبداعات البرمجيه الحديثه ما هي إلا نتاج التفكير الغرضي الصحيح .
غرضية التوجه بعيدا عن المفهوم القواعدي لها هي أسلوب كتابة برامج يركز على قابليه إعادة الإستخدام والتوسعيه , أي يلغي فكرة موت البرنامج بعد أن تزيد سطورة عن حد معين , حيث يصبح من غير الممكن التعامل معه كما هو على شكل وحدة واحدة وإجراء التغييرات عليه دفعة واحدة .
يبنى الأسلوب الغرضي التوجه على أساس تقسيم العمل على شكل وحدات عضويه متكامله كل وحدة قائمه بذاتها تملك خصائصها وأفعالها ويمكن تطويرها بشكل منفصل عن البرنامج الرئيسي وإستخدامها في برامج أخرى.
إذن أولا : قابلية إعادة الإستخدام التي تفصل بين باني الصنف (الكومبونينت) ومستخدم الصنف , الكثير منا يستخدم مكونات برمجيه لايعرف عنها الكثير , كلنا نستخدم المكون (Button) وقليلون منا من يعرفون برمجته , تخيل لولا البرمجة الغرضيه كم كان الوضع صعبا . ليس فقط كذلك , بل سيتم التركيز على جعل هذا الصنق وحدة ممركزه منفصله وبالتالي عند القيام بأي تغييرات عليه ستطبق التغييرات تلقائيا على كل جزء يستخدم هذا الصنف . (مثلا لوقمت بتطوير نوع أزرار جديد "صنف" وأستخدمته 20 مرة في برنامجك . عندها لتعديل شكل الأزرار في برنامجك يكفي تغيير شفرة الصنف مرة واحدة , ولن تضطر للمس ال20 زر البقيه .
وأفترض لو كان للبرنامج عدة أصناف عندها يمكن برمجة كل صنف لوحدة من قبل شخص أو عدة أشخاص وبناء كل صنف لن يرتبط ببناء الأصناف الأخرى إلا من حيث الدخل\خرج .
ثانيا : التوسعيه . وهي مبنيه على كون الصنف المبني وحدة مستقله لاتحتاج شيء من أحد , وبالتالي بإمكاننا تصديرة وإستخدامه في برامج أخرى غير برنامجنا الحالي أو نشرة على الإنترنت ليستفيد منه آخرون , أو حتى إستخدامه من لغات برمجة أخرى .
ملاحظة : يوجد بعض الفروق بين المكون Component والصنف Class ولكني رأيت أن لا أدخل في تفاصيل ذلك .
الآن بعد أن دخلت معي قليلا بالجو . سأسمي البرمجه الغرضية تقنية ثورية بدلا من تسميتها أسلوب كتابة برامج , لإنها فعليا تعتمد على دعم لغة البرمجة لهذة الأساليب وبالتالي هي تقنية تبنى على أساسها لغات البرمجة تمكن المستخدم من العمل بإسلوب البرمجة الغرضية التوجه.
لكي نقول عن لغة برمجه أنها تدعم غرضية التوجه لابد من دعمها ثلاث مفاصل :
- التغليف encapsulation.
- الوراثة inheritance .
- تعدديه الأشكال polymorphism.
التغليف Encapsulation :
تعتمد فكره غرضية التوجه على إخفاء البيانات ضمن وحدات مستقلة.
وتستخدم الأصناف لتحقيق ذلك, حيث يتم إخفاء البيانات داخل الأصناف الخاصة بها, أو نقول بعبارة أخرى يتم تغليف البيانات داخل الأصناف .
عاده يتم توضيح هذه الفكرة باستخدام ما يسمى الصناديق السوداء (black boxes) , حيث لا تضطر أن تعرف كيف تتم الأمور بالداخل وما هي المحتويات الداخلية , وكل ما يهمك هو كيف تتعامل مع واجهه الصندوق الأسود وتعطيه معطياتك وتأخذ النتائج بغض النظر عن ما يتم في الداخل . إن ما يهمك فعليا من الصندوق هو آلية التعامل معه (مع واجهته) ولا تعطي اهتماما كبيرا عن تفاصيل داخل الصندوق,
خذ على سبيل المثال جهاز التلفزيون, إذا اعتبرنا التلفزيون صندوقا أسود, فإن كل ما يهمنا من هذا الصندوق هو كيفيه تشغيله وإطفاءه وتغيير المحطات وبعض الأمور الثانوية الأخرى, دون اهتمام بفهم الدارات الداخلية المكونة له, ودون الدخول في تفاصيل معالجته للإشارة وتحويلها إلى صوره وصوت .
إذن نخزن البيانات داخل الأصناف وعندها يمكننا أن نكتفي بمعرفه كيفيه استخدامها من الخارج . إن كيفيه الاستخدام تدعى واجهه الصنف (class interface) وهي التي تسمح للأجزاء الأخرى من البرنامج باستخدام الأغراض المعرَّفة من هذا الصنف, وبالتالي عندما تستخدم غرض ما فإن معظم شفرته تكون مخفيه, ونادرا ما تعرف ما هي البيانات الداخلية له حتى أنه قد لا توجد طريقة لدخول البيانات الخاصة به بشكل مباشر مالم تستخدم المناهج المتاحة على الواجهة والتي تسمح لك بتغيير وقراءه البيانات, وذلك يعتبر من أهم الفروق بين البرمجة غرضية التوجه و البرمجة الكلاسيكية والتي تكون البيانات فيها عامه لكل الأصناف غير تابعه لصنف محدد كما أنك تستطيع تغيرها مباشره وبالتالي تقع في مطب ظهور أخطاء نتيجة عدم إمكانية اختبار القيمة المدخلة قبل إدخالها وذلك بسبب كون البيانات ظاهره ويمكن الوصول المباشر إليها,...
• كما أن للتغليف ميزة سحرية للمبرمج نفسه
لأنها تسمح له بتغيير التركيب الداخلي للصنف في التحديثات المستقبلية مع بقاء واجهه الصنف نفسها, وبالتالي ستطبق التغييرات تلقائيا على بقيه الأغراض التي استخدمت هذا الصنف بأقل عناء ممكن, دون الحاجة لتغير شفرتنا في مناطق مختلفة من البرنامج. وذلك مثل حاله توابع API لها أسماء ثابتة, مهما تغيرت آلية عملها الداخلية طالما بقيت الأسماء كما هي ستبقى برامجنا تستدعيها بنفس الطريقة, وتغيير في بنية هذا التوابع لن يستوجب تغيير في البرامج التي تستدعيها
الوراثة من أنماط موجودة:
غالباً ما نحتاج بناء نموذج مختلف قليلا من صنف موجود, بدلا من بناء صنف جديد من البداية, ربما نحتاج إضافة مناهج جديدة أو خصائص أو تعديل أخرى موجودة.
والفكرة من ذلك هي أننا نريد المتابعة من نقطه توقف الغير, وليس البدء من الأول لذلك سأقترح أننا نستطيع فعل ذلك بطريقتين:
- نسخ الشفرة من هناك ولصقها هنا . وبذلك ستضاعف شفرتك مرتين , ناهيك عن الأخطاء , والغرق في تفصيلات تبعدك عن مشروعك الأساسي , والخروج عن مبدأ مركزيه الشفرة .
- لماذا لا تقوم بدلا من ذلك باستخدام إحدى أروع ميزات البرمجة الغرضية : ألا وهي الوراثة (inheritance) .
وبالتالي نستطيع ببضعة سطور شفرة فقط أن نبرمج كائن جديد (زر مثلا ) يحوي جميع ميزات الزر العادي وزيادة بعض الخصائص والدوال الخاصة بنا .
ملاحظه :
إن البرمجة غرضية التوجه تفضل ألقدرة على التوسع و إعادة الاستعمال (reusability), على أي شيء آخر, حيث أنك تستطيع كتابه شفرات تستخدم أصناف من بنية وراثيّة معقده دون أي معرفه بالأصناف المحددة التي تشكل جزء من هذه البنية , وبكلمه أخرى تبقى هذه البنية الوراثيّة وبرامجك التي تستخدم هذه البنية قابله للتوسع والتغيير , حتى بوجود آلاف السطور من الشفرة التي تستخدمها . ولكن بشرط واحد أساسي : أن يكون الصنف السلف لهذه الشجرة الو راثية مصمم بعناية فائقة .
وبالتالي تضمن أنك لن تتوقف في مرحلة ما عن تطوير المشروع لغرقك في كميه هائلة من الشفرة والتي أصبحت غير مفهومه وغير صالحه لكل الحالات,
وهذه هي تركه غرضية التوجه الأساسيّة, أنها جعلت تطوير البرامج الضخمة أمرا ممكنا وسهلا.
تعددية الأشكال (Polymorphism)
توفر هذه الخاصية القدرة على استدعاء المناهج المحددة في صنف ما اعتمادا على نوع هذا الصنف .
وتتيح الإشارة إلى صنف على أنه صنف آخر يكون بالعادة في نفس فرع شجره الوراثة كالإشارة للصنف الابن على أنه أحد الآباء. مما يتيح اعادة الاستخدام للأصناف و جعل البرامج أكثر قابليه للتطور وأكثر تفاعليه في زمن التشغيل (Run Time) .
وبالتالي فالعملية نفسها تتصرف بشكل مختلف في أصناف مختلفة. The same operation amy behave differently on different classes
تعددية الأشكال هي الجزء الأكثر صعوبة التي يعاني من فهمها الكثيرون . لتبسيط الموضوع : تتعلق تعددية الأشكال بدعم تصرفات غير قياسية في زمن التشغيل (runtime) حيث تتيح
1- نسب متغير من صنف ما إلى متغيير من صنف آخر (ضمن قواعد DownCasting)
2- إختبار من أي صنف هو المتغيير الحالي
3- تنفيذ المناهج بناء على نوع الصنف الناتج.
خذ مثلا المتحول Sender الذي يوجد في العديد من لغات البرمجه (Delphi C++Builder C# وغيرها ..) يمكن بإستخدام هذا المتحول معرفة من هو الغرض الذي أطلق الحدث والتحكم فيه مع ان Sender حتما ليس من نفس صنف الغرض , وفي حال قمنا بعملية قلب أنماط للتعامل مع sender على أنه من صنف آخر (زر مثلا Button) فإننا سنستطيع الوصول لكافة مناهج هذا الزر عن طريق المتغيير sender .
أي أن sender متعدد الأشكال لإنه يمكنة التلائم حسب نوع الصنف الذي قام بإطلاق الحدث .. وهذه هي تعددية الأشكال بأبسط شكل لها .