السلام عليكم
اتمنى انكم تكونوا بصحة طيبة ,
دائماً ما اسمع كلمة تغليف المتغيرات في بعض الدروس البرمجية مثل Java or Php ؟ عن طريق get, set .
سمعت انه بسبب عدم التعامل المباشر مع المتغيرات,
فايش المشكلة لو اني تعاملت معاها على طول بدون set او get ؟
فايش فوائد التغليف ؟ ولماذا ؟
شكراً لكم
التعليقات
يفيدك ال Encapsulation في تصميم أكثر مرونه Flexible Design قابل للتحسين والتغيير بدون اي Side Effect
حيث كلما تخفي تفاصيل ال Implementation كلما ساعدك في تحسين الية العمل أو تغييرها بدون أن يتأثر أي Client من هذه التغييرات، وايضاً قد تعطيك فرصه لكي تتحقق من صحة البيانات المرسلة بدلاً من وضعها مباشرة..
على سبيل المثال: قمت بكتابه برنامج بسيط يقوم باسترجاع الموظف من خلال رقم الid ، سواء كانت مصدر الموظف هو Collection في الذاكرة أو في القرص أو مخزن في مكان ما.. فالدالة getEmployee سوف ترجعه ..
مثلاً كنت داخلياً تخزنه في الRegistry لسبب ما، وبعد ذلك واجهت مشكلة في الأداء وقررت تخزينه في File ، فالClient لن يتأثر بعد هذا التغيير ..
مثال اخر: تقوم بترتيب الموظفين SortEmployee فسواء استخدمت خوارزمية Merge أو Bubble ، فلا يهم للClient المهم هو أنه يستطيع الترتيب فقط.. ويمكنك مثلاً في اول اصدارة استخدام خوارزمية وبعد ذلك ترى أنها بطئية وتغيرها لأخرى والكلاينت لن يعرف اطلاقاً عن هذا التغيير لأنه مخفى.
الClient تعني الكود الذي يستخدم تلك الدوال والكلاسات سواء كتبته انت أو كتبه غيرك.. عليك أن تنظر لمشروعك على أنه API وأنك API Designer وستصمم المشروع على أساس API حتى يستخدم لبناء الوظائف الأساسية (حتى لو كنت انت المبرمج الوحيد) ..
عندما تنظر بهذا الرؤية ، سوف لن تعطي ال Client أكثر من يحتاجه ، فقط دالة أو اثنين أو كلاسين ، والباقي تخفيه، حتى تتحكم فيه وتغيره كما تشاء فيما بعد..
مثلاً: الكلاينت يريد دالة اسمها SendSMS تأخذ رقم ونص وترسله بغض النظر عن كيفية العمل ، ربما تكون متصل بخدمه على الانترنت أو موصل جوال بالحاسوب وتقوم برمجياً بالاتصال من خلال الAT Commands وترسل .. كل هذا لا يهتم به الكلاينت فهو يريد دالة واحدة فقط..
لذلك لا تقوم بعمل public الا أنت متقيناً ان هذا يريده الclient، لا تقوم بعمل public class ولا public method الا وهناك حاجة لها.. أخفى كل شيء class by package ، وprivate methods و private variables (الا في حالات معينة لا تحتاج لذلك).
من فوائد هذه الأخفاء أنه في حالة كنت تريد التحقق من القيمة بدلاً من وضعها مباشرة على المتغير، مثلاً لديك متغير يمثل رصيدك في الموقع، بدلاً من جعل ال Client يرسل قيمة ما (مثلاً قد يرسل -10 وهذا خطأ فالرصيد لا يمكن يكون سالب) فتقوم داخل الدالة setBalance بالفحص والتأكد من أن الرقم صحيح والا فالthrow IllegalArgumentException
لا تثق بالclient اطلاقاً وتأكد أنه سيحاول كسر كودك بأي شكل وعليك أن تقوم بعمل Defensive Copy (نسخ القيم ) من الكائنات المرسلة لدوالك والتي يمكن أن تتعدل بأن تستدعي كلاسك Mutable Objects.
ايضاً، لا تقوم بعمل setter الا عندما تحتاجها، فالعمل على الكائنات التي حالتها تتغير يعقد العمل ... و كثير من الأحيان الكلاس يعبئ من دالة البناء (سواء كانت من static factory أو builder pattern أو دالة بناء عادية) ولكنك بعد ذلك لن تحتاج لتغيير حالتها وانما تسترجع المعلومات منها.. كلما كثرت من عمل الكلاسات غير القابلة للتعديل Immutable Class كلما كان كودك أسهل في الفهم وأيضاً Thread-Safe
أيضاً، اذا اتبعت فكرة ان تخفى كل شيء ، فقد تجد أن لديك package في المشروع به كلاس واحد public والبقية package private ، هذه الكلاسات مخفية ولا تُستخدم سوى من ذلك ال Package ، لذلك لا تحتاج أن تقوم بعمل setter/getter ولا تحتاج لأن تقوم بعمل private variable في هذه الحالة ؟ لأنك اصلاً مخفى ال Top Level Class عن ال Public API.
خلاصه:
تحتاج ال getter (وربما setter) لكل المتغيرات القابلة للتغيير Mutable Variables في كل ال public classes
الكلاسات المخفية لا تحتاج لأخفاء متغيراتها لأنه من الأساس غير ظاهره للClient
يمكنك الاستزادة عن طريق البحث عن:
Defensive Copy, Immutable, Package Private, Public API
هل تقصد بالتغليف مصطلح wrap؟
و اعذرني ان لم يكن هو
ان كان نعم فالتغليف حينها هو مصطلح شائع بين المبرمجين، لكن ليس هناك اي نص رسمي يحوي في طياته هذه الكلمة،،
عملية التغليف - اذا كانت المقصودة - فهي عملية وضع متغير من نوع في متغير من نوع اخر للحصول على ميزات النوع الثاني في المتغير الاول
مثال يوضح العملية في لغة Java
FileInputStream x = new FileInputStream("absolutepathtoafile");
DatanputStream z = new DataInputStream(z);
فهنا استطعنا فتح الملف من الـFileInputStream ,و استخدام ميزات الملفات الثنائية BinaryFiles من الــ DataInputStream