پرش به: ناوبری, جستجو

پنج:شگردهای برنامه‌سازی

شگردهای برنامه‌سازی
Rayanesh-5-esfand93.pdf
شماره پنج
زیرموضوع دوستِ دوست نباشد همچو یک دوست
نویسنده رضوان مهدوی، rezvan.mahdavi@gmail.com

در شماره‌ی سوم با مفهوم شگرد (Idiom) در زبان‌های برنامه‌سازی آشنا شدیم و یک شگرد پرکاربرد در زبان ++C را بررسی کردیم. در شماره‌ی چهارم (شماره ی پیشین) نیز شگردی در زبان جاوا توضیح داده شد. در این شماره هم شگرد دیگری را در زبان ++C معرفی می‌کنیم. همان‌گونه که قبلا اشاره شده است شگردها را در چهار بخش زمینه، مسئله، راه حل و فایده با یک مثال توضیح می‌دهیم.

Attorney-Client

زمینه: کنترل مقدار دسترسی به محتویات خصوصی (Private) یک رده (class) توسط دوست (Friend) همان رده.
مسئله: می‌دانیم زمانی که یک رده، دوست رده دیگری می‌شود، به تمام محتویات آن رده دسترسی دارد، حتی محتویات خصوصی آن. حال آنکه ممکن است به تمام آنها نیاز نداشته باشد و این یعنی بالا بردن احتمال نقض حریم شخصی رده توسط دوستش!؛ دوستی بیجا!، نقض درپوشینه‌گذاری (Encapsulation)، و بالا بردن وابستگی (Coupling). وابستگی در مهندسی نرم‌افزار به معنی میزان وابستگی بخش‌های نرمافزاری به یکدیگر است و برای بهبود کیفیت نرمافزار، باید وابستگی‌ها تا حد امکان کاهش یابد، زیرا در صورت تغییر یک بخش، ممکن است نیاز باشد بخش‌های وابسته به آن نیز تغییر کنند.
برای نمونه در زیر، رده Client رده Bar را دوست خود تعریف کرده است و به این ترتیب Bar به همه محتویات آن دسترسی دارد، هرچند به همه آنها احتیاج ندارد. با این حال نمی‌توان این دسترسی را محدود کرد.

Client {
  private:
    void A(int a);
    void B(float b);
    void C(double c);
    friend class Bar;
}; 
class Bar {
  // This class needs access to Client::A and Client::B only.
  // C++ friendship rules, however, give access to all the private members of // Client.
};


راه حل: برای حل این مشکل، Client یک رده به نام Attorney را به عنوان دوست خود معرفی می‌کند. سپس Bar دوست Attorney می‌شود و به واسطه‌ی آن، دوست Client خواهد بود، هرچند دیگر به طور مستقیم دوست آن نیست (دوستِ دوست نباشد همچو یک دوست!). حال Bar تنها آنچه را که Attorney در اختیارش می‌گذارد میبیند، و نه تمام آنچه را که Client دارد. در واقع Attorney تنها بخشی از محتوای خصوصی رده‌ی Client را که Bar به آن نیاز دارد تکرار می‌کند (و نه همه‌اش را) و همان را در اختیار Bar می‌گذارد. بدین طریق Bar به عنوان دوستِ دوست نمی‌تواند همچو یک دوست! به همه محتویات Client دسترسی داشته باشد. به برنامه‌ی تغییر کرده زیر دقت کنید:

Client {
  private:
    void A(int a);
    void B(float b);
    void C(double c);
    friend class Attorney;
};
class Attorney {
  private:
    static void callA(Client & c, int a) {
      c.A(a);
    } 
    static void callB(Client & c, float b) {
      c.B(b);
    }
    friend class Bar;
};
class Bar {
  // Bar now has access to only Client::A and Client::B through the Attorney.
};

همان‌طور که مشاهده می‌کنید رده Attorney توسط دو شیوه‌ی callA1 و callB، دو شیوه‌ی A و B از Client را فرا می‌خواند و آنها را در اختیار Bar می‌گذارد و به این ترتیب Bar تنها به این دو دسترسی دارد (و نه C).
فایده: با استفاده از این راه حل Bar به همان اندازه داده و رفتار که نیاز دارد دسترسی پیدا می کند و نه بیشتر، که این خود وابستگی را کم می‌کند. به این ترتیب درپوشینه‌گذاری رعایت می‌شود و رده‌ی Client می‌تواند جزییات داخلی‌اش را به واسطه‌ی یک دوست خوب! (Attorney) مخفی نگه دارد.