پیچیدگی در نرم‌افزار چیست؟

پیچیدگی در نرم‌افزار چیست؟تولید نرم‌افزار، یکی از خلاقانه‌ترین فعالیت‌های بشر در طول تاریخ است. برنامه‌نویس‌ها، به محدودیت‌هایی مثل قوانین فیزیک مقید نیستند. آن‌ها می‌توانند دنیاهای مجازی بی‌نظیری خلق کنند که هیچ وقت قبل از آن وجود نداشته است. برنامه‌نویسی نیاز به مهارت‌های جسمانی یا تناسب فیزیکی خاصی ندارد. تمام آن چیزی که لازم است، یک ذهن خلاق و توانایی سازماندهی افکار است.بنابراین، بزرگ‌ترین محدودیت در تولید نرم‌افزار، توانایی ما در فهم سیستم‌هایی است که در حال ساختن آن‌ها هستیم. در طول زمان نرم‌افزار تکامل می‌یابد و ویژگی‌های جدیدی به دست می‌آورد، وابستگی بین اجزاء آن، باعث ایجاد پیچیدگی است. رفته رفته، پیچیدگی‌ها روی هم انباشته شده و برای برنامه‌نویس‌ها، تغییر و نگهداری سیستم سخت‌تر و سخت‌تر می‌شود.این رویه باعث می‌شود، فرایند توسعه‌ی نرم‌افزارها آهسته‌تر پیش رود و منجر به تولید خطا می‌شود. این خطاها، باز هم روند تولید را آهسته‌تر می‌کنند و هزینه‌ها را افرایش می‌دهند.این که پیچیدگی، در طی پیدایش یک نرم‌افزار، به مرور بیش‌تر می‌شود، یک امر گریز ناپذیر است. هر چقدر نرم‌افزار بزرگ‌تر باشد و تعداد افراد بیش‌تری روی آن کار کنند، مدیریت این پیچیدگی سخت‌تر است. این پیچیدگی را نمی‌توان از بین برد ولی می‌توان آن را مدیریت کرد. اگر می‌خواهیم تولید نرم‌افزار را راحت‌تر و ارزان‌تر انجام دهیم، باید راه‌هایی پیدا کنیم که سادگی را در نرم‌افزار بیشتر کنیم.بنابراین، هر چه قدر هم که ما تلاش کنیم، با گذشت زمان، پیچیدگی بیش‌تر می‌شود، ولی اگر سادگی را در طراحی خود رعایت کنیم، می‌توانیم سیستم‌های بزرگ‌تر و قدرتمندتری را به وجود آوریم، قبل از این که پیچیدگی غیر قابل کنترل شود.پیچیدگی در نرم‌افزار چیست؟پیچیدگی، رفتار یک سیستم یا مدل را، که دارای اجزای متعددی است و این اجزا به چندین روش با هم ارتباط دارند، توصیف می‌کند. به عنوان مثال مغز انسان یک سیستم پیچیده است، چرا که از میلیون‌ها نورون تشکیل شده و با هم در ارتباط هستند. همچنین سیستم‌های حمل‌و‌نقل، سازمان‌های اقتصادی و در نهایت جهان به صورت یک کل، سیستم‌ پیچیده‌ای است.در سال 1987، Fred Brooks در مقاله‌ای با عنوان No Silver Bullet دو نوع پیچیدگی را در نرم‌افزار مطرح کرد:پیچیدگی ذاتی یا ضروری (Essential complexity):این پیچیدگی، در ذات مساله‌ای که می‌خواهیم آن را حل کنیم وجود دارد و قابل حذف شدن نیست. اگر یک قطعه از کد، باید شامل 3 عملکرد باشد، به اندازه‌ این 3 عملکرد پیچیدگی خواهد داشت و نمی‌توانیم مثلا با حذف یکی از این عملکرد‌ها از پیچیدگی بکاهیم.پیچیدگی تصادفی (Accidental complexity)این نوع از پیچیدگی ناشی از مشکلاتی است که خود برنامه‌نویس‌ها باعث آن می‌شوند. این پیچیدگی را می‌توان کم‌تر یا حذف کرد.در این مقاله، Brooks معتقد است که مقدار زیادی از پیچیدگی‌های تصادفی نرم‌افزارها، با روی کار آمدن زبان‌های سطح بالای برنامه‌نویسی و معرفی طراحی شی‌گرا، حذف شده است.در کتاب A philosophy of software design پیچیدگی به این صورت تعریف شده است:«پیچیدگی، هر چیز مرتبط با یک سیستم نرم‌افزاری است، که درک و تغییر سیستم را سخت می‌کند.»برای مثال، ممکن است فهم این که یک قطعه از کد چگونه کار می‌کند، دشوار باشد یا برای بهبود یک بخش کوچک از سیستم نیاز به تلاش بسیاری باشد یا شاید اصلاح یک خطا، بدون دستکاری سایر قسمت‌های سیستم امکان‌پذیر نباشد.از منظر دیگر می‌توان به عنوان هزینه و سود به این مساله نگاه کرد. در یک سیستم پیچیده، هزینه‌ زیادی برای یک تغییر کوچک در سیستم پرداخت می‌شود. در یک سیستم ساده، تغییرات بزرگ با هزینه‌ کم اعمال می‌شوند.پیچیدگی به اندازه‌ سیستم ارتباط مستقیم ندارد. ممکن است یک سیستم بسیار کوچک، بسیار پیچیده طراحی شود یا یک سیستم بزرگ به ساده‌ترین حالت ممکن. همچنین اگر در یک سیستم بزرگ، بخش‌های کوچکی که خیلی هم مورد استفاده نیستند پیچیدگی زیادی داشته باشند، نمی‌توان گفت کل سیستم پیچیده است. در واقع می‌توان گفت پیچیدگی کل سیستم، شامل مجموع پیچیدگی‌های بخش‌های مختلف سیستم است، که وزن آن بخش‌ها در این مجموع لحاظ شده است.علت‌های به وجود آمدن پیچیدگی چیست؟حال که نشانه‌های پیچیدگی را شناختیم، ببینیم علت به وجود آمدن آن چیست:وابستگی‌هادر این جا منظور از وابستگی، هر نوع ارتباط بین یک کد با کد دیگر است، به این صورت که برای تغییر در یکی، دیگری هم باید تغییر کند. به عنوان مثال، signature یک متد بین کدی است که متد را تعریف کرده و برای کدی که آن را استفاده می‌کند، وابستگی به وجود می‌آورد و مثلا اگر یک پارامتر اجباری به تعریف متد اضافه شود، تمام کدهایی که از آن استفاده می‌کنند باید تغییر کنند. همچنین اگر دو قطعه کد به صورت فرستنده و گیرنده عمل کنند، پروتکل ارتباطی بین آن‌ها یک وابستگی است. اگر فرستنده تصمیم به تغییر پروتکل بگیرد، گیرنده هم باید تغییر کند.قطعا وابستگی‌ها بخشی از نرم افزار هستند و نمی‌توانیم آن‌ها را از بین ببریم. هدف ما به عنوان طراح نرم‌افزار باید این باشد که تا حد ممکن وابستگی‌ها را کم و همچنین آن‌ها را ساده و واضح طراحی کنیم.وابستگی‌ها معمولا باعث «تشدید تغییر» و «بار شناختی» بالا می‌شوند.ابهامابهام زمانی اتفاق می‌افتد که اطلاعات مهم، واضح و روشن نباشد. مثلا ممکن است نام یک متغیر طوری تعریف شود که با خواندن آن هیچ اطلاعات مفیدی درباره آن متغیر به دست نیاورده باشیم.ابهام به وابستگی هم ارتباط دارد، وقتی که وجود یک وابستگی، واضح نیست. مثلا اگر یک نوع پیام جدید به سیستم اضافه شود ولی برنامه نویس هیچ جا به متن آن پیام دسترسی نداشته باشد.یک روشِ اشتباه برای کم کردن ابهام در نرم‌افزار، مستندسازی است. معمولا اگر در طراحی نرم‌افزار، نیاز به مستندسازی‌های پرهزینه و زیاد داریم، یعنی طراحی نرم‌افزار به درستی انجام نشده است، یک طراحی خوب، قطعا به مستندسازی کمتری نیاز خواهد داشت.ابهام در نرم‌افزار، باعث ایجاد «ندانسته‌های ناشناخته» و «بار شناختی» زیاد می‌شود.جمع‌بندیپیچیدگی، چیزی نیست که با یک اشتباه بزرگ در سیستم ایجاد شود بلکه نیازمند انباشته شدن مسائل کوچک زیادی روی هم است. یک وابستگی یا یک ابهام نمی‌تواند تاثیر زیادی روی قابلیت نگه‌داری سیستم داشته باشد. پیچیدگی وقتی زیاد می‌شود که صدها و هزاران وابستگی و ابهام کوچک در طول زمان در سیستم ایجاد شوند. به همین دلیل مدیریت پیچیدگی سخت می‌شود. هر برنامه‌نویس فرض می‌کند که این تکه کد کوچک که در حال نوشتن آن است، اگر هم دارای ابهام باشد یا وابستگی غیرضروری به سیستم تحمیل کند، مشکلی ایجاد نخواهد کرد. ولی مجموع کار برنامه‌نویس‌های مختلف که با این رویکرد سیستم را توسعه می‌دهند، می‌تواند تبدیل به فاجعه شود.گردآورنده: بهنام ابوترابی کاشانی درس اصول طراحی نرم افزار استاد:دکتر مریم حاج اسمعیلی. دکترای علوم کامپیوتر از دانشگاه کینگستون لندن Dr.Maryam hajiesmaeiliPHD of computer science from Kingston University of Landon