شاید قبلاً نام AOP (سرنام Aspect Oriented Programming) را شنیده باشید. بسیاری از ما اولین بار که این نام را شنیدیم با تصور این که AOP نیز یکی از آن پارادایمهایی است که هر چند سال یکبار برای جایگزینی برنامهنویسی شیءگرا مطرح میشوند، بیتفاوت آن را کنار گذاشتیم. اما داستان AOP، طولانیتر از این حرفها است. زمان آن رسیده که کمی خاک شیوه برنامهنویسی خود را بگیرید. مکاشفات جذابی وجود دارد.
بسیاری از افراد معتقدند، علوم کامپیوتر آن قدرها هم که بهنظر می آید، سریع پیشرفت نمیکند. آنها معتقدند، در بسیاری از شاخهها کار تقریباً تمام شدهاست و کارهای جدید فقط در حد پیشرفتهای جزئی انجام میگیرد. در حقیقت، بعضی از موضوعهای مطرح شده توسط این گروه بدبین، تا حدودی به واقعیت نزدیک است. بسیاری از پایههای علوم کامپیوتر شکل گرفته است و به نظر میآید تغییر آنها، دستکم به این زودیها امکانپذیر نیست. در بعضی از شاخهها یک فناوری آنچنان جای پایش را محکم کردهاست که حتی تصور وجود روشی دیگر کمی سخت به نظر میرسد.
اما کامپیوتریها مردم جالبی هستند. شاید آنها خیلی پرکار نباشند، اما همیشه ایدههای جدید و خلاقانه راهی برای نفوذ به درون دنیایشان پیدا میکنند. شاید در بسیاری از زمینهها، کار شما به مطالعه کارهای کلاسیک انجام شده محدود شود، اما همیشه جادههای جدیدی وجود دارد.
گریگور کیزالس (Gregor Kiczales)، بیشتر وقت خود را در آزمایشگاه پارک (PARC) که مبدأ شروع بسیاری از خلاقیتهای بزرگ حوزه علوم کامپیوتر بوده، گذرانده است. محیط صنعتی - آکادمیک آزمایشگاه علاوه بر دلمشغولیهای آکادمیک، کیزالس را به مسائل و مشکلات حوزه نرمافزار در دنیای واقعی آشنا ساخته است. در حقیقت، یکی از همین مشکلات (Cross-cutting Concern) بود که منجر به ارائه مدل AOP توسط این پروفسور دانشگاه UBC و همکارانش در زیراکس پارک شد. مدلی که به تحرکات زیادی در حوزه نرمافزار منجر شد تا جایی که Daniel Sabbah، معاون بخش استراتژیهای نرمافزاری شرکت آیبیام درباره آن میگوید: «زمان توسعه نرمافزارها به وسیله مفهوم Aspect-Oriented فرا رسیدهاست. صنعت نرمافزار به آن نیاز دارد و آیبیام در حال حاضر از آن استفاده میکند.»
اولین ارائه رسمی از این موضوع به سال 1997 برمیگردد. البته، اطلاعات تاریخی درباره AOP بسیار اندک است و ما از روند کار چیز زیادی نمیدانیم. کیزالس خود در پاسخ به پرسش نگارنده پیرامون تاریخچه و روند شکلگیری AOP میگوید: «متأسفانه هیچ تاریخ مدونی برای AOP وجود ندارد.» در این مقاله سعی کردهایم معرفی مناسبی از این پارادایم جدید برنامهنویسی ارائه دهیم.
چرا از پارادایم استفاده میکنیم؟
توماس کوهن، پارادایم را اینگونه تعریف میکند: «پارادایم در نتیجه فعالیتهای اجتماعی ظاهر میشود که در آن مردم ایدههایشان را توسعه میدهند و قواعد و مثالهایی میسازند که این ایدهها را بیان کند.» این شاید یکی از رسمیترین تعریفهایی باشد که در سراسر عمرتان برای پارادایم میشنوید. اما این جمله زیبا برای یک برنامهنویس چه معنایی دارد؟
کامپیوترهای اولیه توسط کدهای باینری برنامهریزی میشدند و برنامهنویس، با ارسال دنبالهای از صفر و یک ها به پردازنده مرکزی بهطور مستقیم برای آن کامپیوتر برنامهنویسی میکرد. با گذشت زمان، زبانهایی با سطوح بالاتر عرضه شدند. اسمبلی، C و جاوا نمونهای از زبانهای نسلهای مختلف هستند. با معرفی هر نسل، نحوه نوشتن برنامه و نگرش به مفاهیم نیز در آن تغییر مییافت. ارائه شیوههای جدید تولید نرمافزار به امید ایجاد راههای بهتر برای طراحی و پیادهسازی یک برنامه، هنوز نیز ادامه دارد. روش پایهای برنامهنویسی را که در بالا بیان شد، پارادایم برنامهنویسی مینامند. در حقیقت، پارادایمها چهارچوب کلی معماری یک برنامه و نحوه ارتباط اجزای آن با یکدیگر را مشخص میکنند. با ذکر مثالهایی از پارادایمهای مختلف، مفهوم را روشنتر میکنیم.
شاید برنامهنویسی رویهای (Procedural Programming) اولین پارادایم مطرحشده برای زبانهای برنامهنویسی است. در این پارادایم، اعمال، مرحله به مرحله توسط فراخوانی رویههایی که برای انجام کارهای مختلف نوشته میشوند، انجام میگیرند. این مدل با مشخص کردن ترتیبی برای فراخوانی رویهها یکییکی آنها را اجرا میکند و با اتمام کار هر کدام رویه بعدی اجرا میشود. در حقیقت، برنامهنویسی رویهای، ادامه ایده کلیتری بهنام برنامهنویسی امری (Imperative Programming) است. بهطور ساده استراتژی این مدل برنامهنویسی به این صورت است که تعدادی دستور وجود دارند که باید توسط کامپیوتر اجرا شوند. زبانهای امری دقیقاً مانند اسمشان عمل میکنند: اول این کار را انجام بده، بعد آن را و... .
برنامهنویسی شیءگرا نیز در بیشتر مواقع مثالی از مدل امری است، زیرا در آنجا نیز روش کار برنامه عموماً به صورت اجرای سلسلهای از دستورها است. اگرچه معمولاً برنامهنویسی شیءگرا به صورت یک مدل جداگانه مورد بررسی قرار میگیرد. در مقابل مدل برنامهنویسی امری، مدل اعلانی (Declarative) قرار دارد. در این مدل تمرکز روی ماهیت چیزها است نه نحوه کارکرد آنها. در مدل اعلانی آنچه اهمیت دارد، توصیف این است که یک جزء برنامه چگونه است، نه اینکه چگونه ساخته میشود. اگر برنامه خود را به دو قسمت منطق و کنترل تقسیم کنید، در مدل اعلانی شما منطق برنامه خود را در اختیار میگیرید و نگران آنچه در بخش کنترل اتفاق میافتد، نیستید. مثال بارز اینگونه زبانها، HTML است. با توجه به نزدیک بودن ساختار مدل اعلانی به ساختار ریاضیات، اثبات درستی یک برنامه در این مدل راحتتر انجام میگیرد. به همین دلیل، مدل اعلانی در نوشتن برنامههایی که باید درستی آنها به صورت یک حکم ریاضی ثابت شود، کاربرد فراوانی دارد. عموماً زبانهای مدل امری در محیطهای کاری از محبوبیت بیشتری برخوردارند، اما نمیتوان از تأثیر مدل اعلانی در ساخت برنامههای علمی (به خصوص ریاضی) به سادگی گذشت. این معرفی بسیار کوتاه از پارادایمها فقط برای این بود که بدانیم آنها واقعاً یکی نیستند! هر پارادایم، یک سبک برنامهنویسی و از آن مهمتر یک سبک نگرش را به دنبال دارد که میتواند تعاریف و اصول یک برنامهنویس را دگرگون سازد. پارادایمها قطعاً به وجود نیامدهاند که معجزه کنند، بلکه قرار است کار را برای برنامهنویسان راحتتر سازند.
Aspect-Oriented Programming نیز، که در واقع در ادامه مدل OOP عرضه شد، یک پارادایم برنامهنویسی است که در ادامه به معرفی آن میپردازیم.
وقتی OOP جوابگو نیست...
سناریوی زیر را در نظر بگیرید: فرض کنید شما مسئول طراحی وبسایت برای یک شرکت فروش آنلاین لباس شدهاید. این سایت، مانند بیشتر سایتهای دنیا دو بخش دارد: بخش نخست برای مشتریان که میتوانند در آن اجناس را مشاهده کنند و آنها را بخرند. بخش دوم نیز برای انجام کارهای اداری خود شرکت است که فقط کارمندان خاصی به آن دسترسی دارند. بهعنوان مثال، اضافه کردن اقلامی به فروشگاه آنلاین یا بررسی کردن حساب بعضی از مشتریها. شما و گروه برنامهنویسی با تلاشی قابل ستایش سایتی بسیار جامع و زیبا طراحی میکنید و آن را به شرکت ارائه میدهید. اما روزی که برای دریافت حقالزحمه خود میروید، متوجه میشوید که همه از دست شما عصبانی هستند. کارمندان نمیتوانند البسه جدید را وارد فهرست فروشگاه کنند، کاربران سایت در حال افزایش اعتبار حساب کاربری خود به صورت دستی هستند! ایمیل کاربران با فرمت اشتباه ذخیره شده است، پیگیری فروش روزهای قبل در مواردی دچار مشکل میشود و... . مشکل چیست؟
با افزایش پیچیدگی در یک برنامه نحوه کنترل شما روی روند رشد آن نیز دشوارتر میشود. با این که ممکن است در بسیاری از قسمتهای برنامه کارهایی شبیه به هم انجام دهید، اما جا انداختن یکی از این کارها در هر یک از قسمتها میتواند کارایی کل برنامه شما را زیر سؤال ببرد. به مثال امنیت سایت فروش لباس باز میگردیم. شما متوجه میشوید با توجه به پیچیده شدن معماری سایت، بسیاری از کارهای ضروری را از قلم انداختهاید. در بسیاری از جاها فراموش شده که قبل از فراخوانی روشهای امن (Secure) هویت کاربر مشخص شود تا فرد غیرمسئول نتواند به اطلاعات محرمانه دسترسی داشته باشد. در بسیاری از قسمتها ورودیهای اشتباهی که کاربران به صورت دستی به سیستم میدهند، تأیید اعتبار (Validate) نمیشوند و این باعث بروز سردرگمی در سیستم میشود. در ضمن در بعضی از روشها با توجه به زیاد بودن کارهای حاشیهای (مانند ثبت کردن عملیات یک سیستم (Logging)، تراکنشهای پایگاهداده و مدیریت خطاها فراخوانی روشهای بعضی کارها از قلم افتادهاست. در نتیجه سایت کاملاً کارایی خود را از دست داده و عملاً به یک سیستم خراب تبدیل شدهاست. از تمام این موارد بدتر اینکه مشکلات شما به اینجا ختم نمیشود. وقتی درصدد اصلاح کدها بربیایید، میبینید اینکار خیلی دشوارتر از آن است که تصور میکردید، زیرا کد هر قسمت آمیختهای از روند کاری اصلی برنامه (Business Logic) و کارهای حاشیهای مانند بررسی کردن امنیت و Logging و ... است. جداسازی کد به صورتی که بتوانیم بخشهای مختلف را مورد بررسی قرار دهیم، کار بسیار مشکلی است و اینکار شما و گروه طراحی را دشوارتر از قبل میکند.
مشکل سایت قسمت بالا مشکل تمام سیستمهای شیءگرا است. به کارهای مذکور که برای تمام قسمتهای سایت یکسان هستند، Cross-Cutting Concern گفته میشود. در حقیقت، Cross-Cutting Concern ،Concernهایی هستند که در چندین قسمت سیستم مورد توجه قرار میگیرند (بهعنوان نمونه، در مثال بالا بررسی امنیت و تراکنشهای پایگاهداده و عملیات Logging).
این Concernها معمولاً نمیتوانند در یک ماجول بهطور کامل کپسوله شوند. همانطور که در مثال مذکور میبینید، باید چندین فراخوانی هر کدام از آنها را در سیستمهای امنیتی بالا قرار دهیم تا بتوانند آنها را به قسمت برقراری امنیت متصل کنند. Cross-Cutting Concern جایی است که دیگر مدل شیءگرا جواب کارآمدی به ما نمیدهد.
AOP؛ تولد یک مفهوم
در 1997 گریگور کیزالس و گروهش در زیراکس پارک مفهومی را معرفی کردند که Aspect Oriented Programming یا به اختصار AOP نامیده میشود. نام اولیه این پروژه تجزیه و سرهم کردن (Decomposition & Weaving) بود، اما بعدها به AOP تغییر نام داد. کیزالس درباره این موضوع میگوید: «این نظر یکی از اعضای گروه بود که به درستی اشاره کرد تلفظ این نام بسیار سخت است و در ضمن به نظر کمی زیادی Nerdy است.»
AOP، در حقیقت بهعنوان یک مکمل برای برنامهنویسی شیءگرا عرضه شد تا ضعفهایی را که در قسمت قبل به اختصار به آن اشاره کردیم پوشش دهد. کار اصلی AOP کار کردن با Cross-Cutting Concern ها است. اما بیایید دقیقتر به مفهوم AOP بپردازیم. شما برای نوشتن یک برنامه علاوه بر منطق کاری برنامه خود (که جریان اصلی برنامه است)، باید بهطور همزمان نگران بسیاری از کارهای حاشیهای دیگر نیز باشید. سؤالهایی از قبیل: «اگر یک قسمت از برنامه مطابق پیشبینی کار نکرد، چه کنم؟» یا «چگونه امنیت را به برنامهام تزریق کنم؟» یا حتی «چگونه مدیریت حافظه را انجام دهم؟»، سؤالاتی هستند که هر برنامهنویس در طول یک پروژه بارها از خود میپرسد. اما چگونه باید با این Concern ها کنار آمد؟ شاید به ذهن همه ما این فکر خطور کرده باشد که چه خوب بود اگر کارهای حاشیهای و کد اصلی در دو فرآیند کاملاً جدا تولید میشدند تا علاوه بر افزایش Modularization، بتوانیم نگرانیهای خود را تقسیم کنیم. در حقیقت این ایده، فکر اصلی پشت سر AOP است. البته انجام کارهای حاشیهای در پشت صحنه ایدهای قدیمیتر از AOP است. بهعنوان مثال، میتوانید انجام مدیریت حافظه و Garbage Collection توسط JVM در زبان جاوا را در نظر بگیرید. شما میتوانید کد خود را بدون نگرانی درباره مسائل مربوط به دو مورد ذکرشده در بالا بنویسید، زیرا جاوا خود با آنها کنار میآید. انجام جداگانه کد و کارها باعث افزایش modularization میشود و همه برنامهنویسان میدانند که این افزایش میتواند چهقدر دنیا را زیبا کند!
جان هانت میگوید: «من هنوز میتوانم خودم را جلوی سورس کد یک برنامه تصور کنم در حالیکه سعی میکنم منطق کاری پایهای آن را از بقیه چیزهای دور و برش مجزا سازم.» شاید شما هم در غم او شریک باشید. درک سازوکار اصلی کارکرد یک برنامه، موضوع بسیار مهمی است که معمولاً بسیار سخت انجام میگیرد. زیرا تمام کد اصلی برنامه با جزئیات حاشیهای (البته نه لزوماً از نوع پیشپا افتاده) مخلوط شده است که علاوه بر مشغول ساختن ذهن کدنویس و کند کردن فرآیند عیبیابی، باعث میشود تا درک روند کاری اصلی کد نیز برای کسی که سعی در فهم آن دارد، بسیار مشکل شود. اما راه حل گروه کیزالس برای این موضوع چه بود؟ چیزی که آنها عرضه کردند میتوانست Cross-Cutting Concernها را به صورت یک ماجول جداگانه مورد بحث قرار دهد. ماجولی که علاوه بر عملیات اصلی که باید انجام دهد، در برگیرنده شرط اجرای این Concernها نیز است. بگذارید با ذکر یک مثال موضوع را مشخص کنیم. به همان بحث امنیت باز میگردیم. در مدل شیءگرا راهحل ما ساختن یک کلاس (یا یک روش در یک کلاس) برای بررسی بحث دسترسی کاربر موردنظر بود. پس از ساخت یک ماجول برای بررسی، با اضافه کردن عبارتهای فراخوانی آن در قسمتهای مختلف برنامه، کار را تکمیل میکنیم. در حقیقت، روند کاری در مدل شیءگرا در دو جا دنبال میشود. یکی کلاس یا روشی که برای بحث امنیت نوشتهایم، یکی هم مکانهای فراخوانی آن از کد اصلی برنامه.
اما راهحل AOP متفاوت است. در AOP دو مکان قبلی (ماجول امنیت و مکان فراخوانی) تقریباً با یکدیگر ترکیب میشوند. به این ترتیب که شما کد مربوط به Concern (در مثال ما چک کردن امنیت) را در یک ماجول جداگانه قرار میدهید و سپس در همان ماجول شرطهای فراخوانی این کد را ذکر میکنید (بهعنوان مثال، درباره بحث موردنظر ما باید بررسی هویت در مواردی انجام شود که یک روش امن فراخوانی میشود). به این ترتیب، تمام روند کاری Cross-cutting Concernها از سازوکار اصلی برنامه مجزا میشوند. کاملاً مشخص است که این جدایی میتواند چه مزیتهایی را برای سیستم به ارمغان بیاورد. بهعنوان مثال، میتوان این دو بخش کد (کد اصلی و Cross-cutting Concernها) را به دو گروه مختلف برنامهنویسی واگذار کرد یا حتی درباره خود Cross-cutting Concernها میتوان هر بخش را به خبره آن کار سپرد. مثلاً بخش بررسی کردن امنیت به متخصصان امنیت یا بخش تراکنشهای پایگاهداده به متخصصان آن.
شاید باز هم اصرار کنید که تمام این کارها با مدل شیءگرا نیز قابل دسترس بود (بحث کاملتری درباره این مقایسه در بخش آخر مقاله آمده است). البته درست میگویید! اما توجه داشته باشید که در یک مدل شیءگرا برنامهنویس باید از نکات زیر آگاهی داشته باشد:
1- برنامهنویس باید از وجود چنین کلاسهایی که برای هماهنگ کردن این Cross-cutting Concernها ساخته شده است، خبر داشته باشد.
2- باید Specification دقیق آن کلاس را بداند تا بتواند از آن استفاده کند.
3- باید بداند دستور مربوط به فراخوانی روشهای آن کلاس را کجای کد اصلی قرار دهد.
در تمام این سه مرحله امکان رخ دادن خطا وجود دارد. به خصوص در قسمت آخر که فراموشی برنامهنویس برای فراخوانی تمام روشهای لازم از شایع ترین اشتباهها است. اما با استفاده از AOP، با توجه به جدا شدن دغدغههای برنامهنویسان این دو بخش چنین مشکلاتی اصولاً مطرح نمیشوند (البته مشکلات دیگری مطرح میشوند که چند نمونه از آنها در قسمت آخر مقاله مطرح میشود). با استفاده از AOP میتوانیم بدون تغییر کد اصلی، Concernهایی به آن اضافه کنیم که رفتارهای سیستم را تقویت کند. در بخش بعد به بررسی مفاهیم اصلی AOP میپردازیم.
این یک AOP است...
چه چیزی مُهر AOP را روی یک سیستم میزند؟ مسلماً معیار طراحی یک سیستم براساس AOP، این نیست که سازنده آن اینگونه بگوید. این موضوع که آیا یک پروژه از AOP استفاده میکند یا خیر، به مکانیزم کاری آن پروژه و ماهیت نیازهای آن بستگی دارد. بهعنوان مثال، کل عملیات مربوط به پرینت کردن یک سند را در نظر بگیرید. شما ممکن است در قسمتهای مختلفی از برنامه خود عملیات پرینت کردن را نیاز داشته باشید. به این ترتیب، باید بارها روشهای مربوط به آن را فراخوانی کنید. ممکن است با توجه به این تعاریف شما پرینت را به صورت یک Concern در نظر بگیرید. اما آیا این طراحی یک طراحی منطقی است؟ در تعریف Concernهایی که در AOP مورد توجه قرار میگیرند یک نکته فرعی وجود دارد و آن این است: این Concernها معمولاً به صورت یک ماجول جداگانه (در مدل های قبل از AOP) دستهبندی نمیشوند. این تعریف جواب سؤال بالا را مشخص میکند. در مثال بالا روشهای مربوط به عملیات پرینت کردن برای برنامهنویس کاملاً مشخص است و مطرح کردن این نکته که او ممکن است فراموش کند که آنها را فراخوانی کند تا حدودی خندهدار به نظر میآید. پس چندان منطقی نیست که پرینت کردن را به وسیله AOP پیادهسازی کنیم. عدم استفاده از AOP در مثال بالا بدیهی بود، اما ایده پشت این مطلب را مشخص میکند. AOP باید در مواردی به کار گرفته شود که به آن نیاز است. وقتی مکانیزمی که وجود AOP را میطلبد، موجود نیست میتوانیم خیلی راحت از پارادایم های دیگر استفاده کنیم. پس باید قبل از استفاده از AOP نیازهای یک سیستم را کاملاً تحلیل کنیم تا لزوم یا عدم لزوم به کارگیری آن را مشخص سازیم. در ادبیات AOP، تعاریفی رسمیتر از مفاهیم اولیه آن وجود دارد که موارد استفاده AOP را روشنتر میکند.
Quantification یا تعیین عناصر:
Quantification ایدهای است که در آن یک برنامهنویس میتواند با نوشتن یک سری عبارت در قالب یک واحد و به صورت مجزا از بقیه سیستم، بسیاری از جاهای غیرمحلی برنامه را تحتتأثیر قرار دهد. درباره AspectهاQuantification میتواند به این صورت معنی شود که توانایی Aspectها برای اثرگذاری در نقاط مختلف یک برنامه است.
Obliviousness یا فراموشکاری:
Obliviousness بیانگر این ایده است که یک برنامه اطلاعی از این که یک Aspect کی و کجا اجرا میشود، ندارد. نتیجه اینکه شما نمیتوانید با نگاه کردن به کد بگویید کدام Aspect اجرا میشود و این باعث ارتقای مفهوم جداسازی میشود.
تعریف Filman-Friedman
دو مفهوم ذکر شده در بالا (تعیین عناصر و فراموشکاری) از دیدگاه تعریف Filman-Friedman دو مفهوم لازمالاجرا در زمینه طراحی برنامههای Aspect Oriented هستند. در حقیقت، با توجه به این تعریف هر طراحی باید شامل هر دو ایده بهطور کامل باشد. هرچند خیلیها این دو تعریف را بسیار سختگیرانه میدانند، زیرا برنامههای بسیاری با طراحی AOP وجود دارند که تنها به خاطر جلوگیری از اختلاط دو کد، یکی از آنها Aspect محسوب میشود که این طراحی لزوماً نقاط مختلف برنامه را مورد هدف قرار نمیدهد (مثال رعایت نشدن تعیین عناصر). همچنین در بعضی مواقع، برنامهنویسان AOP محل فراخوانی Aspect را با علامتی خاص مشخص میسازند (مثال رعایت نشدن فراموشکاری)
دو اصطلاح Tangling و Scattering
● پراکندگی: (Scattering) پیادهسازی یک Concern، پراکنده شده است هر گاه کد آن بین چند ماجول پخش شده باشد.
● پیچش: (Tangling) پیادهسازی یک Concern، پیچیده شدهاست هر گاه کد آن با کد یک Concern دیگر مخلوط شده باشد.
پراکندگی و پیچش در Aspect Oriented بهعنوان علائم یک Cross-Cutting Concern در نظر گرفته میشوند. در حقیقت عموماً Concernهایی که چنین خصوصیاتی را در پیادهسازیهای غیر AOP داشته باشند، مورد بحث قرار میگیرند.
AOP در عمل
باید اعتراف کرد که با وجود ارزشمند بودن توضیحات و تئوریهای برنامهنویسی، تا وقتی که آنها را در عمل، به وسیله برنامهنویسی مورد آزمایش قرار ندهیم، در حقیقت کار خاصی انجام ندادهایم. در ادامه سعی میکنیم مفاهیم مطرح شده را به همراه کد آن مورد بررسی قرار دهیم تا علاوه بر معرفی و تعریف مفاهیم موجود در AOP، با نحوه به کارگیری آنان نیز آشنا شویم، اما قبل از هر چیز باید به این سؤال پاسخ دهیم که کجا میتوانیم AOPبنویسیم؟
برای پاسخ دادن به این پرسش، ابتدا باید ببینید AOP چگونه اجرا میشود. برای نوشتن یک پروژه به صورت AOPشما ابتدا هر دو بخش کد خود را (اعم از روند کاری اصلی برنامه و کدهای مربوط به Aspectها) به صورت جداگانه در یک زبان شیءگرا مینویسید و سپس موجودی به نام Aspect Weaver آن دو بخش را با یکدیگر ترکیب کرده و کد نهایی را میسازد. جداسازی کد اصلی و کد Concernها (کد اصلی نیازی به اطلاع از بخش Concernها ندارد) به افزایش قابلیت استفاده دوباره (Reusability) و قابلیت نگهداری (Maintainability) پروژه کمک شایانی میکند. شکل 1 نحوه کار Weaverها را نشان میدهد. دو نمونه بارز از ابزارهایی که میتوان با استفاده از آنها برنامههای Aspect-Oriented نوشت AspectJ و AspectWerkz هستند.
AspectJ یک Extension است که برای زبان جاوا در زیراکس پارک و توسط گروه بهوجود آورنده AOP نوشته شدهاست. این Extension به دو صورت تنها و تعبیه شده در Eclipse IDE عرضه میشود. AspectJ پتانسیل پشتیبانی از مدلRT Weaver را نیزدارد، اما برای بهره بردن از تواناییهای آن باید از آن بهصورت یک Compile-time Weaver استفاده کرد (هماکنون به صورت Compile-time و loadtime عرضه میشود).
Aspect Weaver !
در حقیقت Aspect Weaver کد اصلی و کد Aspectها را بهعنوان ورودی میگیرد و محصول نهایی را تولید میکند. توجه به این موضوع ضروری است که نگاه کلی به Weaverها مانند یک کامپایلر نیست، زیرا قرار نیست که تمام کارهای پیچیدهای را که یک کامپایلر انجام میدهد. Weaver نیز در مورد ترکیب دو بخش کد انجام دهد. در حقیقت، همانطور که خود کیزالس هم اشاره می کند، وظیفه Weaverها فقط Integration ) مجتمعسازی ) است. تکنیکهای اولیه Weaving به دو دسته عمده تقسیم میشوند: Compile Time) CT) و Run-Time) RT Weaver)هایCT. همانطور که از نامشان پیدا است، تمام کارهای مربوط به ترکیب کد را در زمان کامپایل انجام میدهند و در حقیقت کد نهایی که اجرا میشود، محصول کامل است. در مقابل RTها اینکار را در زمان اجرا انجام میدهند و ایجاد ارتباط را تا آن وقت به تأخیر میاندازند. Weaverهای CT با توجه به این که تمام فرآیند ایجاد ارتباط را در ابتدای کار و هنگام کامپایل انجام میدهند بسیار سریعتر از RTها عمل میکنند، اما در مقابل RTها هم این مزیت را دارند که در صورت تغییر کد Aspectها نیازی به انجام دوباره عملیات Weaving نیست و برخلاف CTها در Run-Time Weaver تغییرات در کد بدون نیاز به هیچ کاری سریع منعکس میشوند. همانطور که در بالا ذکر کردیم، تکنیکهای Weaving دیگری نیز وجود دارند که در واقع فضای بین Compile-time و Run-time قرار میگیرند. این دو تکنیک Weaving را (post-compile time (binary و Load-time مینامند. Binary Weaving در حقیقت عملیات Weaving را روی byte code انجام میدهد (پس از کامپایل). Load time Weaving نیز یک نوع binary Weaving است. با این تفاوت که عملیات Weaving را تا زمانی که یک کلاس به Class loader معرفی نشده است، به تأخیر میاندازد. (این توانایی میتواند برخی از نقصهای مدل Compile-time را برطرف کند، زیرا شما میتوانید بدون کامپایل کردن دوباره کد اصلی خود (Aspect ،(Business Logicهایی به برنامه اضافه کرده و سپس آنها را به پروژه اصلی لینک دهید). در حقیقت، در این مدل تا جایی که ممکن است عملیات Weaving به تأخیر میافتد و تا مرحله Load شدن کلاسهای موردنیاز هیچ ترکیبی انجام نمیشود.
AspectJ محیطی ساده و بسیار کارا دارد و هماکنون محبوبترین ابزار برنامهنویسی Aspect-Oriented است. نسخههای جدیدتر AspectJ بهطور کامل با محیط توسعه Eclipse هماهنگی دارند و میتوان از تمام امکانات Eclipse در مورد Aspectها نیز سود برد.
توجه به این نکته ضروری است که AspectJ تغییراتی در Syntax زبان به وجود میآورد که این موضوع میتواند باعث بروز مشکلاتی شود (Eclipse با توجه به اضافه کردن Keywordهای مربوط به برنامهنویسی AOP این مشکل را ندارد).
این مشکلات باعث شدند تا ابزارهای دیگری به وجود آیند که به این تغییرات گرامری در زبان برنامهنویسی نیازی نداشته باشند. یک نمونه مشهور از این زبانها AspectWerkz است. AspectWerkz در حال حاضر از هر سه مدل Compile-time ،Load-time و Run time استفاده میکند. خصوصیت بارز AspectWerkz این است که Syntax زبان را تغییر نمیدهد و در حقیقت تغییرات را با استفاده از Annotation انجام میدهد که به یک ساختار زبانی جدید نیازی ندارد. در حال حاضر، دو پروژه AspectJ و AspectWerkz با یکدیگر ترکیب شدهاند تا بتوانیم از قابلیتهای هر دو به صورت همزمان استفاده کنیم.
تمام این مقدمهها برای این ذکر شد که شما کمی بیشتر با نحوه عملکرد داخلی ابزارهای توسعه برنامههای Aspect-Oriented آشنا شوید.