سلام
بخشی که می خواهم بگذارم مربوط به یک تحول جدید در برنامه نویسی است که به عنوان سمینار درس مهندسی نرم افزار در دانشگاه ما ارایه شده است
از تمامی کسانیکه در این پروژه زحمت کشیده اند کمال تشکر را دارم
مقدمه
در بیشتر سیستمهای نرم افزاری کنونی دغدغه[1]های مختلفی وجود دارد که بین بخشهای مختلف برنامه مشترک هستند و بعضاً رابطههای پیچیدهای بین بخشهای مختلف برنامه ایجاد میکنند. دغدغههایی از قبیل امنیت، امکان ثبت وقایع و ... بخش کوچکی از این دغدغهها را تشکیل میدهند. اگر برای پیادهسازی اینگونه دغدغهها از تکنیکهای برنامهنویسی شیءگرا استفاده شود، یک سیستم پیچیده، غیر قابل فهم و غیر انعطاف پذیر بهوجود میآید. روش جدید برنامهنویسی جنبهگرا[2](AOP) باعث میشود که تقسیمبندی بخشهای مختلف برنامه به نحوی ساده شود که برطرف کردن دغدغهها باعث پیچیدگی زیادی نشود. این کار باعث راحتتر شدن طراحی، فهم، و نگهداری سیستم خواهد شد. علاوه بر این، AOP باعث تولید محصولاتی با بهرهوری بالاتر، کیفیت بهتر، و امکان اضافه کردن قابلیتهای بیشتری میشود.
دغدغه[3] یک هدف مشخص، مفهوم یا حوزهی کاری است. یک سیستم نرمافزاری عادی شامل دغدغههای متعددی، از دغدغههای لایههای مرکزی گرفته تا دغدغههای لایههای سیستمی، میشود. برای مثال، دغدغهی مرکزی یک سیستم پردازش کارت اعتباری پردازش پرداختها است. در صورتی که دغدغههای سیستمی آن سر و کار داشتن با ثبت وقایع، یکپارچه کردن تراکنشها، شناسایی کاربر، امنیت، کارایی و ... است. خیلی از این دغدغهها، که به دغدغههای تداخلی[4] معروفند، بر روی پیادهسازی پیمانههای مختلف برنامه اثر میگذارند. در صورت استفاده از روشهای کنونی برنامهنویسی این دغدغههای تداخلی برروی تعداد زیادی از پیمانههای برنامه پخش میشوند و اثر میگذارند و به همین دلیل طراحی و درک سیستم مورد نظر سختتر، و همچنین پیادهسازی آن پیچیدهتر خواهد شد. تغییر هم در چنین سیستمی مطمئناً سختتر خواهد بود. برنامهنویسی جنبهگرا بهتر از روشهای متداول قبلی دغدغهها را از پیمانههای سیستم جدا میکند. به همین دلیل بهتر میتوان از تداخل دغدغهها جلوگیری کرد.
در این مقاله به بررسی مشکلاتی که تداخل دغدغهها در بخشهای مختلف برنامه ایجاد میکند میپردازیم و سپس مفاهیم پایهی برنامهنویسی جنبهگرا را مورد بررسی قرار میدهیم. در نهایت به بررسی چند نمونه از زبانهایی که از جنبهگرایی پشتیبانی میکنند میپردازیم.
بخش1 سیر تکامل روش برنامهنویسی
در روزهای اولیهی پیدایش علم کامپیوتر، برنامهنویسان برنامههای خود را مستقیماً با استفاده از کدهای سطح ماشین مینوشتند. به همین دلیل آنان فکر خود را بیشتر از اصل مسأله، متوجه مجموعه دستورات ماشین مورد نظر میکردند! بهتدریج زبانهای سطح بالاتری بهوجود آمدند که برای ما سطحی از انتزاع بر روی کامپیوترهای مختلف مورد استفاده ایجاد میکردند. وقتی به یک زبان برنامه مینوشتیم، دیگر لازم نبود به این مسأله فکر کنیم که برنامه روی چه ماشینی اجرا میشود. بعد از آن نوبت به زبانهای ساختیافته رسید. میتوانستیم برای راحتتر کردن کار، مسألهی خود را به تعدادی روال، که برای انجام کارها لازم هستند، تقسیم کنیم. برنامه نویسی شیء گرا به ما این اجازه را داد که یک سیستم را به صورت تعدادی شیء که با هم ارتباط و همکاری دارند ببینیم. کلاسها به ما این اجازه را میدادند که جزئیات پیادهسازی را پشت واسط برنامهنویسی پنهان کنیم. چند شکلی بودن امکان رفتار و واسطه مشترک برای مفاهیم مشابه را به ما میداد. به این وسیله میتوانستیم پیمانههای خاص و جدید را بدون نیاز به دستکاری در پیادهسازی مفاهیم پایه ایجاد کنیم.
روشهای برنامهنویسی و زبانها در واقع راه ارتباط با ماشین را تعریف میکنند. هر روش جدید راههای جدیدی برای تجزیهی مسأله ارائه میدهند: کد ماشین، کد مستقل از ماشین، روالها، کلاسها، و ... . هر روش جدید یک طرز نگرش تازه برای تبدیل نیازهای سیستم به زیرساختهای برنامهنویسی ارائه میدهد. تکامل این روشهای برنامهنویسی این امکان را به ما میدهد که سیستمهای پیچیدهتری ایجاد کنیم. عکس این مطلب نیز صادق است: سیستمهای پیچیده میتوانند پیادهسازی شوند، چون این روشها به ما این اجازه را میدهند.
در حال حاضر، بیشتر برنامهنویسی شیءگرا به عنوان روش ایجاد پروژههای نرمافزاری استفاده میشود. این روش قدرت خود را روی مدل کردن رفتارهای معمولی نشانداده است. ولی، همانطور که به زودی خواهیم دید، و همانطور که ممکن است شما قبلاً تجربه کرده باشید، این روش به خوبی نمیتواند روی رفتارهایی که بین چندین پیمانه (مخصوصاً پیمانههای مستقل و احتمالاًبیربط) مشترک است کار کند. بلعکس روش برنامه نویسی جنبهگرا تا حد خوبی این مشکل را برطرف میکند. به احتمال زیادی برنامهنویسی جنبهگرا ارائهدهندهی گام بزرگ بعدی در تحول روشهای برنامه نویسی خواهد بود.
بخش2 تحلیل یک سیستم به عنوان مجموعهای از دغدغهها
یک سیستم پیچیدهی نرمافزاری را میتوان به صورت پیادهسازی مخلوطی از چندین دغدغه ببینیم. یک سیستم خیلی معمولی ممکن است از تعداد زیادی دغدغه، شامل منطق کاری، کارایی، ماندگاری دادهها، ثبت وقایع و اشکالزدایی، هویت شناسی، امنیت، امنیت کار موازی[5]، بررسی اشکالها و غیره تشکیلشدهباشد. همچنین ممکن است با دغدغههای فرآیند تولید نرمافزار، مانند قابلیت درک، قابلیت نگهداری، قابلیت ردیابی، و سادگی تحول در سیستم مواجه باشیم.
ما نیازمندیها را از یک منشور مشخص کنندهی دغدغهها میگذرانیم، که این منشور دغدغههای مختلف مربوط را در هر نیازمندی مشخص میکند. همین دیدگاه برای دغدغههای فرآیند ایجاد نرمافزار نیز قابل تعمیم است.
بخش3 دغدغههای متداخل در یک سیستم
برنامهنویس، یک سیستم را به عنوان راهحلی برای چندین نیازمندی به وجود میآورد. به طور کلی میتوان این نیازمندیها را به نیازمندیهای سطح مرکزی و نیازمندیهای سطح سیستمی تقسیم کرد. بسیاری از نیازمندیهای سطح سیستمی مستقل از یکدیگر و مستقل از نیازمندیهای سطح مرکزی هستند. نیازمندیهای سیستمی همچنین در بسیاری از پیمانههای مرکزی تداخل دارند. برای مثال، یک برنامهی بنگاهی[6] از تعداد زیادی دغدغهی تداخلی مانند هویت شناسی، ثبت وقایع، استفادهی مشترک از منابع، سرپرستی، کارایی، و مدیریت ذخیرهسازی تشکیل شدهاست. هر کدام از این دغدغهها با بسیاری از زیرسیستمها تداخل دارد. برای مثال دغدغهی ذخیرهسازی بر روی تمام اشیاء ماندگار در سیستم اثر میگذارد.
به این مثال ساده ولی واقعی توجه کنید. پیادهسازی محافظت شده[7] ی یک کلاس تجاری را در نظر بگیرید:
public class SomeBusinessClass extends OtherBusinessClass
}
Core data members //
Other data members: Log stream, data-consistency flag //
Override methods in the base class //
(public void performSomeOperation(OperationInformation info
}
Ensure authentication //
Ensure info satisfies contracts //
Lock the object to ensure data-consistency in case other //
threads access it //
Ensure the cache is up to date //
Log the start of operation //
==== Perform the core operation ==== //
Log the completion of operation //
Unlock the object //
{
More operations similar to above //
(public void save(PersitanceStorage ps
{
}
(public void load(PersitanceStorage ps
{
}
{
در کد فوق، باید حداقل سه مسأله را مورد نظر قرار داد.
اول اینکه فیلدهای دیگر (Other Data Members) مربوط به دغدغهی اصلی این کلاس نیستند.
دوم اینکه به نظر نمیرسد پیادهسازی متد performSomeOperation() فقط مربوط به کار اصلی این متد باشد. در واقع در پیادهسازی این متد، در کنار دغدغهی اصلی، به کارهای جانبیای از قبیل ثبت وقایع، چک کردن هویت، امنیت کار موازی، چک کردن درستی cache و ... پرداختهاست. علاوه بر این، به نظر میرسد بسیاری از این دغدغههای جانبی به همین ترتیب در کلاسهای دیگر نیز پیادهسازی شدهاند.
سوم اینکه مشخص نیست که آیا متدهای save() و load() که کار مدیریت ماندگاری دادههای را انجام میدهند باید بخشی از قسمت اصلی این کلاس باشند یا خیر.
[1] Concern
[2] Aspect Oriented Programming
[3] Concern
[4] Cross-cutting Concerns
[5] Multithread safety
[6]
[7] Encapsulated