با جنبه برنامه بنویسیم! – Aspect Oriented Programming

علت به وجود آمدن برنامه نویسی جنبه گرا – AOP

مشکل پراکندگی و درهم ریختگی یا در هم پیچیدگی  در برنامه توسط جنبه ها قابل حل است. (این دو مشکل را در مقاله ضرورت پیمانه بندی نرم افزار توضیح داده ایم) در برنامه های نرم افزاری بخشی از دغدغه های کاربران با هم تداخل دارند و همانطور که اشاره شد این دغدغه ها در یک مولفه (شی) قابل پیاده سازی نیستند.

در یک سیستم جنبه گرا می توان دغدغه های مداخله ای را به صورت یک دغدغه جدا در نظر گرفت جدا سازی این دغدغه ها و پیاده سازی آن به وسیله ی جنبه مشخص می شوند.

اگر تا کنون از سبک برنامه نویسی شی گرا استفاده می کردید و با آن آشنا بودید. در برنامه نویسی جنبه گرا (Aspect Oriented) با مفهوم جدیدی به نام جنبه آشنا می شوید . پس باید به مفاهیمی از قبیل تابع ، Class و … مفهومی به نام جنبه را نیز اضافه کنید. برنامه نویسی جنبه گرا جدا از برنامه نویسی شی گرا نیست ، بلکه در واقع قابلیت جدیدی است که به برنامه نویسی شی گرا اضافه شده است.

در برنامه نویسی شی گرا پیمانه بندی سیستم (که یکی از اهداف مهندسی نرم افزار است) در قالب اشیا انجام می شود ، اشیا می توانند به خوبی به نیازهای عملیاتی و غیر مداخله ای پاسخ دهند . اما در برنامه نویسی جنبه گرا  علاوه بر کلاس ها که برای پاسخ به نیازهای ساختاری استفاده می شوند. جنبه ها (Aspect) هم قرار دارند  و وظیفه ی پاسخ به نیازهای مداخله ای ( دغدغه های مداخله ای ).

بنابراین در برنامه نویسی  جنبه گرا (AOP) دو بعد کلاس و جنبه وجود دارد.

مقایسه کد در جنبه گرا و شی گرا
مقایسه پراکندگی کد ها در برنامه نویسی جنبه گرا و شی گرا

در شکل بالا مستطیل ‌های سفید کلاس هستند. در قسمت  بدون جنبه که صرفا با کلاس پیاده سازی شده، شیارهای خاکستری کد‌هایی‌ در هر کلاس هستند  که برای پیاده سازی نیاز مداخله‌ای (مانند واقعه نگاری) نوشته شده است. چون این اعمال در چندین نیاز مورد استفاده قرار می‌گیرد پس کلاس‌های متعددی را درگیر کرده.در قسمت با جنبه کلاس ها بدون کد‌های پراکنده مربوط به دغدغه‌های مداخله‌ای پیاده سازی شده اند. کد های مربوط به پیاده سازی نیاز های مداخله ایی در قسمت جنبه (مستطیل خاکستری) پایده سازی شده اند. این امر به پیمان بندی هرچه کامل تر سیستم  کمک می‌کند چرا که در پیمان بندی کمترین تداخل بین پیمانه‌ها (به عنوانه مثال اشیا) باید وجود داشته باشد و هر بخش صرفا وظایف مربوط به خود را انجام می دهد.

بخشهای مختلف جنبه

یک جنبه یا Aspect بخش‌های مختلفی‌ را شامل می شود که به شرح زیر است:

Advice:

کدی که برای پیاده سازی یک دغدغه می‌نویسیم advice نام دارد. این بخش در زمانی‌ که جنبه باید اجرا شود، اجرا می شود. کدهای جنبه میتواند شامل پیاده‌سازی دغدغه‌های وظیفه مندی و یا غیر وظیفه مندی باشد اما در اکثر موارد جنبه برای پیاده سازی نیازهای غیر وظیفه مندی (نیاز‌های کیفی‌) استفاده میشود.

در واقع هدف از به وجود آمدن جنبه پاسخ گوئی به نیازهای کیفی‌ بوده، چرا که این نیاز‌های کیفی‌ هستند که ناظر به کّل سیستم اند و تداخل در وظایف مختلف را ایجاد می‌کند.

Join point:

 رویداد‌هایی که در زمان به وقوع پیوستن آن باید اتفاق؛ جنبه مورد نظر بافته یا اجرا شود.

مدل join point تعریفی‌ از مجموعه رخداد‌هایی‌ است که می‌توان در یک برنامه جنبه گرا مورد اشاره واقع شود. مدل join point حالت استانداردی ندارد و هر زبان برنامه‌نویسی جنبه گرا مدل join point  خود را دارد.

به عنوانه مثل در زبان AspectJ موارد زیر را به عنوان رویداد(event ها) داریم:

  1. Call event زمانی‌ که متد یا سازنده‌ای صدا زده میشود مثل توابعی که اول آنها نام update آماده است
  2.  Execution events زمانی‌ که متد یا سازنده‌ای در حل اجراست.
  3. Initialization event هنگام ایجاد کلاس یا اشیا
  4. Data event هنگام دسترسی به یک فیلد و یا دست‌کاری آن (مثل get و ‌set در شی‌ گرایی )
  5. exception event زمانی‌ که استثنای خاصی‌ در برنامه به وجود میاید.

Point cut:

رخداد‌هایی‌ را شناسایی می‌کند که با advice در ارتباط هستند این به آن معناست که شما میتوانید advice را در نقاط مختلفی‌ از برنامه بسته به مدل join point که پشتیبانی‌ می‌شود بیاورید.

شکل زیر مثالی از کد یک جنبه است:

مثال کد جنبه به زبان AspectJ
مثالی از کد یک جنبه به زبان AspectJ

بافتن(weaving)

بافنده در واقع در کنار کامپایلر ها قرار می گیرند. زمانی که کد های اصلی برنامه و همچنین کد های جنبه تولید شدند، بافنده کد های جنبه و برنامه اصلی را دریافت می کرده، سپس آنها را به ترتیب مورد نظر کنار هم قرار می دهد. این عمل را طبق نظر آقای کیزالس یکپارچه سازی می گویند. در نهایت کد های یکپارچه شده در اختیار کامپایلر قرار می گیرند.

عملکرد بافنده ها در زبان جنبه گرا
عملکرد بافنده ها برای بافتن جنبه ها

نباید این اشتباه را کرد که بافنده جنبه ها کامپایلر هستند. بلکه واسطی است بین کدهای برنامه و کامپایلر. همانطور که از توضیحات مربوط به بافنده مشخص است، جنبه ها همچون اشیا مفاهیم انتزایی هستند. یعنی  ماشین  آن کدی که توسط کامپایلر ها کامپایل می شود را دریافت می کند اما درکی از کلاس ها یا جنبه ها ندارد، و این عناصر برای ماشین تعریف نشده هستند. کامپایلر ها هستند که متوجه می شوند مثلا یک شی خاص در کجای برنامه اصلی قرار دارد.

انواع بافنده ها🙁Aspect Weaver)

  • سورس کد قبل از پردازش source code per-process

در این شیوه ابتدا بافنده کد برنامه را گرفته و جنبه ها را در جایی که باید اعمال شود قرار می دهد. و یک کد به زبان مورد نظر(مثلا جاوا یا C++) تولید کرده و آن کد تحویل کامپابلر داده می شود، کامپایلر نیز همچون گذشته همان کد برنامه را کامپایل می کند.

  • بافنده متصل زمانی Link-Time

در این روش بافنده در کامپایلر قرار دارد و همزمان با کامپایل برنامه بافتن جنبه نیز انجام می شود. این روش مستلزم این است که کامپایلر دست کاری شود و بافنده به آن اضافه شود. این روش در AspectJ نیز استفاده شده است.

  • بافنده پویا در زمان اجرا Dynamic weaving at execution time

در این روش جنبه ها با کد برنامه ادغام نمی شود و در زمان اجرای برنامه در هرلحظه محل برش چک می شود و در صورت رخ دادن نقطه اتصال ، کدهای جنبه اجرا  می شوند.

در بین این سه روش پرکاربردترین روش ، بافنده متصل زمانی است که سرباری اضافی زمان اجرا را بر خلاف روش بافندگی پویا در زمان اجرا ندارد اما با وجود سرباری  زیاد پویایی و انعطاف پذیری زیادی دارد . روش اول نیز منسوخ شده است که به دلیل انعطاف پذیری بسیار پایین آن است.

نویسنده مطلب: حسین اسحقی

2 دیدگاه در “با جنبه برنامه بنویسیم! – Aspect Oriented Programming

  • حامد

    (فروردین ۲۸, ۱۳۹۶ - ۰:۰۲ ق٫ظ)

    این مطالب ادامه داره؟؟

    • حسین اسحقی

      (فروردین ۲۸, ۱۳۹۶ - ۸:۴۵ ق٫ظ)

      انشاالله کمی درباره مهندسی نیازمندی بر مبنای مدل جنبه گرا هم در مقاله ایی دیگر صحبت خواهیم کرد

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

1 + 1 =