طراحی نرم افزار (Software Design)
در ادامه آشنايي با حوزهها و فعاليتهاي مختلف در فرآيند توليد نرم افزار كه اميدوارم با توجه به اصول مهندسي نرم افزار باشد، به “طراحي نرم افزار” ميرسيم.
مقدمه
بعد از فعاليتهاي مربوط به حوزهً نيازمنديها نوبت به طراحي يا Design ميرسد. در واقع طراحي مانند پلي است كه نيازمنديهاي تهيه شده را به پياده سازي متصل ميسازد و نقش بسيار مهمي را در فرآيند توليد نرم افزار بازي ميكند. اگر نرم افزار به درستي طراحي گردد، در هنگام پياده سازي برنامه نويسان دربارة چيزي كه بايد پياده سازي شود سردرگمي ندارند و فقط به مسائل مربوط به پياده سازي ميپردازند.
طراحي نرم افزار مقولة بسيار گستردهاي است و ادبيات آن به تنهايي شامل چندين هزار صفحه مطلب است. از معماري نرم افزار بگيريد تا رويكردهاي طراحي مانند شئي گرايي تا طراحي واسط كاربر. در ادامه با عنوانهاي متعدد ولي كوتاه سعي به معرفي كليات آن ميكنم.
به چه كاری طراحي ميگويند؟
ابتدا تعريف برگرفته از چند منبع معتبر:
فرآيند مشخص سازي معماري، مؤلفهها (Components)، واسطها (Interfaces) و ديگر خصوصيات سيستم يا مؤلفه را “طراحي” گويند. به محصول اين فرآيند نيز “طراحي” گفته ميشود.[IEE04]
يا
طراحي نرم افزار شرحي بر ساختار، داده، واسطهاي بين مؤلفههاي سيستم، و گاهي الگوريتمهاي مورد استفادة نرم افزار قرار به پياده سازي ميباشد. [Som06]
تعريف من از طراحي ملموستر است:
تهيه هرآنچه برنامه نويسان از نيازمنديهاي نرم افزار براي پياده سازي نرم افزار نياز دارند.
براي روشن شدن چهارچوبه مبحثي كه در ادامه به آن خواهيم پرداخت شكلي از اجزاي كلي طراحي و ارتباط آن با حوزه تحليل نيازمنديها از [Pre04] آورده ام.
قوائد طراحي
براي طراحي صحيح و خلق طراحي مناسب، لازم است يك سري قوائد رعايت شود، اين قوائد كه در طول ساليان توسط فعالان اين حوزه بدست آمده است، ما را در انجام درست طراحي ياري دهد. به عنوان كسي كه قصد طراحي نرم افزار داريد آشنايي با اين اصطلاحات لازم است.
انتزاع/تجرد/چكيدگي (Abstraction):
ترجمههاي متعددي براي اين اصطلاح آورده شده كه من در اينجا از “انتزاع” استفاده ميكنم. در كل طراحي نرم افزار از “انتزاع”كم كردن جزئيات را مد نظر دارد. مثل هميشه ذكر يك مثال بهتر از توضيحات گيج كننده است: براي چاپ يك صفحه شما امكان دارد بگوييد: “اين صفحه را چاپ كنيد!” يا دقيقتر حرف بزنيد و بگوييد: “به منوي فايل رفته، گزينة چاپ را انتخاب كرده، سپس… و كليد تأييد را فشار دهيد.” در جمله اول روال چاپ با سطح بالاتري از انتزاع نسبت به روال توصيف شده در جمله دوم بيان شده است و جزئيات كمتري دارد. ميتوان جمله سومي نوشت و روال كار را جزئيتر هم تصور كرد.”
انتزاع” در طراحي روشي براي كاهش پيچيدگي محسوب ميشود و داراي سه نوع است: “انتزاع رويهاي” (Procedural Abstraction)، “انتزاع داده” (Data Abstraction) و “انتزاع كنترل” (Control Abstraction).
وابستگي ( Coupling)
كوپلينگ بيان كننده شدت ارتباط بين دو ماژول [عنصر] است [IEE04]. كه من آن را “وابستگي” ترجمه كردهام. وابستگي در طراحي بايد حداقل ممكن باشد كه بدان Low Coupling گويند. با اين كار تغييرات روي ماژالها راحت تر و كم هزينهتر خواهد بود و استفاده مجدد به راحتي صورت ميپذيرد [Lar04].
اصطلاحي كه براي ماژولهايي با وابستگي كم بكار برده ميشود “loosely Coupled” است كه به همين مفهوم اشاره داد.
پيوستگي (Cohesion)
به شدت ارتباط عناصر تشكليل دهندة يك ماژول Cohesion گفته ميشود [IEE04]. وابستگي عناصر تشكيل دهنده يك ماژول بايد حداكثر ممكن باشد كه بدان High Cohesion ميگويند و باعث ميشود ماژولها متمركزتر، قابل فهم تر باشند و به راحتي مديريت شوند [Lar04].
تفكيك يا ماژول بندي (Decomposition/Modularization)
در عمل تفكيك، نرم افزار به قسمتهايي مشخص و آدرس پذيري به نام “ماژول” تقسيم ميشود. ماژول بندي تنها خصوصيت نرم افزار است كه باعث ميشود برنامه به صورت عاقلانهاي اداره شود [IEE04]. مديريت يك نرم افزار بزرگ و يك تكه كار دشواري است و با شكستن آن به بخشهاي كوچكتر (براي مثال با EJB يا COM ) مديريت آن راحتتر صورت ميپذيرد.
كپسوله سازي/پنهان سازي اطلاعات ( Encapsulation/Information Hiding)
بطور خلاصه پنهان سازي اطلاعات يا كپسوله سازي به اين مطلب اشاره دارد كه پيمانههاي مختلف نرم افزار به اطلاعات (داده و الگوريتم) يكديگر [در صورت صلاح ديد] دسترسي نداشته باشند. اين مفهوم كه بعدها در شئي گرايي به عنوان ويژگي شاخص مطرح شد، از دسترسي و دستكاريهاي ناخواسته ماژولها به هم جلوگيري ميكند.
مواردي كه به نظرم مهم بود ذكر كردم، البته اين ليست طولانيتر است و براي مثال Sufficiency, completeness and primitiveness توصيه ميكند خصوصيات هر مؤلفه نرم افزار به حد كفايت (نه كم به زياد) باشد، در صورت تمايل به SWEBOK بخش طراحي براي مشاهده منابع مربوط به اين موارد رجوع كنيد.
طراحي شامل چه فعاليتهايي ميشود؟
براساس استانداردهاي چرخه توليد نرم افزار از جمله IEEE/EIA 12207 طراحي نرم افزار شامل دو فعاليت عمده است:
طراحي معماري نرم افزار
در اين طراحي كه طراحي “سطح بالا” نيز گفته ميشود، به توصيف سطح بالا و كلي ساختار و سازمان نرم افزار پرداخته ميشود و مؤلفههاي مختلف آن شناسايي ميگردند. [IEE04]
براي هر پروژهاي معماري لازم است ولي براي يك پروژه لازم است از ديدگاههاي مختلف بدان پرداخته شود ولي براي پروژههاي كوچكتر فقط يك تصميم براي انتخاب معماري كافي است. يك مثال از معماري نرم افزار در ادامه آورده شده. توضيحات تكميلي در مورد “معماري” بعداً ارائه خواهد شد.
توضيح: اين دياگرام Component با استفاده از UML 2.0 توسط آقاي Scott Ambler كشيده شده و بيان كننده معماري يك سيستم دانشگاهي ميباشد. همانگونه كه مشاهده ميشود مؤلفههاي اين سيستم و ارتباط آنها با يكديگر به خوبي با اين دياگرام بيان شده است.
طراحي تفصيلي نرم افزار
همانگونه كه اشاره شد در معماري نرم افزار، نرم افزار به بخشها و مؤلفههاي مختلف تفكيك ميشود. در طراحي تفصيلي نرم افزار اين مؤلفهها و اجزا با جزئيات كامل بايد تشريح شوند. براي مثال طراحي فيلدهاي جدول بانك اطلاعاتي، طراحي توابع يا كلاسهاي نرم افزار و مشخص كردن ورودي و خروجي آنها، طراحي جزئيات واسط كاربر و اجزاي فرم يا صفحه وب، مثالهايي از طراحي تفصيلي نرم افزار است.
روشهاي كلي طراحي
در طراحي ميتوان رويكردهاي مختلفي اتخاذ نمود. هر روش خصوصيات مخصوصي دارد كه طراح با توجه به نوع سيستمي كه پيش رو دارد بايد روش صحيح را انتخاب كند. در ادامه به معرفي روشهاي مطرح ميپردازم:
طراحي ساخت يافته (Structured Design)
اين روش طراحي سنتي كه حداقل در ايران پركاربردترين روش طراحي است، مبتني بر شناسايي عمكلردهاي اصلي (Major Functions) نرم افزار و سپس شكستن و ريز كردن آنها بصورت بالا به پايين (Top-down) ميباشد. لازم به ذكر است در اين روش معمولاً از Data Flow Diagram براي انتساب داده به فرآيند استفاده ميشود. [IEE04]
طراحي شئي گرا (Object Oriented)
در اين روش سيستم در دنياي واقعي بصورت اشيائي كه داراي خصوصيت و رفتار هستند، در نرم افزار نمود پيدا ميكند. اين اشياء بوسيله Message با هم ارتباط برقرار ميكنند و در كلاسها و زير كلاسها دسته بندي ميشوند [Pre01]. بطور خلاصه هر شئي داراي نام، يكسري خصوصيت (Attribute) و متد (Method) ميباشد كه در ارتباط با هم نرم افزار را تشكيل ميدهند. يكي از محاسن استفاده از روش شئي گرايي اين است كه شكاف مفهومي تحليل، طراحي و پياده سازي را به حداقل رسانده است، به بيان ديگر شما در هر سه اين فعاليتها با مفهوم كلاس، شئي، متد و… سروكار داريد. حسني كه در روشهاي ساخت يافته غايب است. [Lar04]
طراحي متمركز بر ساختار داده (Data-Structure-Centered Design)
اين روش همانند “ساخت يافته” است با اين تفاوت كه پايه طراحي “داده” است و نه “عمليات”. در اين روش طراح در ابتدا ساختار داده ورودي خروجي را مشخص كرده (مثلاً با دياگرام جكسون) و سپس ساختار كنترل را براساس ساختار داده مشخص مينمايد.
طراحي مبتني بر مؤلفه(Component Based Design )
ابتدا مؤلفه را تعريف ميكنم: مؤلفه يك واحد مستقل ميباشد كه از واسطها (Interface) و وابستگيهايي كه بطور شايستهاي تعريف شده، برخوردار ميباشد. مؤلفه بصورت مستقل و مجزا قابل انتشار است [IEE04]. از اين تعريف خشك بگذريم، بطور ساده مؤلفه يك مجموعه عملكرد (معمولاً شئي) است كه با استفاده از كپسوله سازي و انتزاع به يك واحد مستقل و قابل استفاده مجدد تبديل شده است. طراحي با استفاده از مؤلفه و قرار دادن آنها كنار هم براي رسيدن به يك كل كه نرم افزار هدف ماست را طراحي مبتني بر مؤلفه
گويند[Pre01].
براي مطالعه بيشتر در مورد موارد مطرح شده به فصول ۱۱، ۱۴، ۱۵ و ۱۶ اين كتاب مراجعه نماييد.
خصوصيات كيفي طراحي (Quality Attributes)
يكي از بحثهاي مهم كه كمتر از آنچه بايد و شايد مورد توجه قرار ميگيرد، درنظرگرفتن معياريهاي كيفي طراحي است. طراحان نرم افزار عادت دارند برروي حل مسئله تمركز كنند و فراموش ميكنند كه خصوصيات كيفي هميشه جزئي از مسئله است و بايد مد نظر قرار بگيرد[Pre01]. در ادامه به برخي از خصوصيات كيفي كه تحت عنوان FURPS مشهور هستند، ميپردازم:
- عملكرد (Functionality): اين خصوصيت با توجه به امكانات و توانايي نرم افزار طراحي شده و همچينين امنيت (Security) مربوط به آنها ارزيابي ميشود.
- قابليت استفاده (Usability): اين خصوصيت با در نظر گرفتن معياريهاي انساني (Human Factos)، راهنماي نرم افزار و مستندات آن ارزيابي ميشود.
- قابلبت اطمينان (Reliability): اين خصوصيت با توجه به تعدد و شدت خطا، صحت خروجي، توانايي پوشش خطا و پيش بيني پذيربودن (Predictability) نرم افزار ارزيابي ميشود.
- كارايي (Performance): اين خصوصيت كيفي با توجه به سرعت پردازش، زمان پاسخگويي، مصرف منابع، توان و كارايي سنجيده ميشود.
- قابليت پشتيباني (Supportability): اين مورد شامل خصوصيت مختلفي از جمله: امكان توسعه قابليتهاي برنامه(Extensibility)، قابليت تست برنامه (Testability)، وجود امكان پيكربندي (Configurability) و بومي سازي (Internationalization) ميشود.
هر برنامهاي كه طراحي ميشود ممكن است برروي يكي از موارد ذكر شده تمركز بيشتري داشته باشد و لزوماً اهميت مساوي برخوردار نيستند. براي اطلاعات بيشتر به فصل ۹ كتاب [Pre01] رجوع كنيد.
ثبت طراحي
براي مستند سازي يا بيان طراحي لازم است از نمادهايي استفاده شود. اين نمادها بايد آنقدر جامع باشد كه تمام جوانب طراحي را پشتيباني نمايند و مرسوم هم باشد تا براي ديگران نيز قابل فهم باشد.
مهمترين كاربرد ثبت طراحي (و ديگر مراحل توليد) بيشتر برقراري ارتباط با ديگران است تا مستندسازي آن براي مراجعات بعدي، واين نكتهاي است كه كمتر به آن توجه ميشود!
نمادها و زبانهاي وجود دارد كه به دو دسته كلي تقسيم ميشود، دسته اول نمايي ايستا (Static) از ساختار سيستم نمايش ميدهند مانند “دياگرام كلاسهاي نرم افزار” و دسته دومي نمايي پويا (Dynamic) از رفتار سيستم ارائه ميدهند، مانند “Data Flow Diagram”. در ادامه نگاهي دقيقتر به تعدادي از آنها مياندازيم:
توصيف ساختاري (نماي ايستا)
بطور كلي نماي ايستا از يك سري عنصر نرم افزاري و رابطة بين آنها تشكيل شده است.
- Class & Object Diagrams: براي نمايش كلاسهاي (اشياء) طراحي شده و همچنين رابطه بين آنها مورد استفاده قرار ميگيرد. اين دياگرام از خانواده UML است.
- Component Diagrams: مؤلفههاي سيستم و رابطه بين آنها را نمايش ميدهد و بيشتر در سطح معماري سيستم كاربرد دارد و از خانواده UML است.
- Deployment Diagrams: جهت مدلسازي جنبههاي فيزيكي سيستم مورد استفاده قرارميگيرد و شامل گرههاي (Node) سخت افزاري و رابطة بين آنهاست و از خانواده UML است.
- Entity-relationship diagrams يا ERD: يك مدل مفهومي از دادههايي كه در سيستم اطلاعاتي ذخيره ميشوند.
- Jackson structure diagrams: جهت توصيف ساختار داده مورد استفاده قرار ميگيرد.
توصيف رفتاری (نماي پويا)
اين نمادها جهت ثبت رفتار و تراكنش اجزاي سيستم بكار ميآيند كه به برخي از آنها اشاره ميكنم:
- Activity diagrams: اين دياگرام منطق رويهاي عمليات را نمايش ميدهد. اين دياگرام از خانواده UML است.
- Collaboration diagrams: كه در UML 1.x با نام Communication Diagrams شناخته ميشود. فعل و انفعال بين گروهي از اشياء را به نمايش ميگذارد و تمركز آن بر اشياء و پيغامهاي تبادل شده بين آنهاست.
- Data flow diagrams يا DFD: جهت نمايش روند چرخش داده در طول مجموعهاي از فرآيند، استفاده ميشود.
- Flowcharts: روند انجام يك فرآيند را نمايش ميدهد.
- Sequence diagrams: فعل و انفعال بين گروهي از اشياء را به نمايش ميگذارد و تمركز آن بر اشياء و ترتيب پيغامهاي تبادل شده بين آنهاست.
براي مطالعه موارد مربوط به UML به كتاب معروف UML Distilled مراجعه كرده و موارد غير UML را در اين كتاب جستجو كنيد.
مواردي كه از قلم افتاد:
به نظر ميآيد سه مورد مهم ديگر را بايد اشاره ميكردم كه در دسته بنديهاي بالا غايب است:
- الگوهاي طراحي (Design Patterns): الگوهاي طراحي براي مسائلي كه طراح در طراحي زياد با آن مواجه ميشود، يك راه حل كلي ارائه ميدهند. براي مثال ثبت خطا (Error Logging) در نرم افزار مسئله معمولي است كه طراح بايد به آن بپردازد، با استفاده از الگوهاي طراحي بهترين روش براي انجام اين كار توسط طراحان زبده ارائه شده است و طراح فقط بايد آن را با مسئله خود تطبيق دهد. اصطلاح الگوهاي طراحي بيشتر در طراحي شئي گرا كاربرد دارد و اولين بار توسط Kent Beck مطرح شد و پس از آن با كتاب معروف Design Patterns به بلوغ خود رسيد.
- طراحي واسط كاربر (User Inerface): طراحي واسط كاربر كه زير مجموعه حوزة Usability قرار ميگيرد، به طراحي ظاهر قابل رويت نرم افزار اشاره دارد. كتاب About Face كتاب مناسبي براي آشنايي با مباني اين مقوله است.
- طراحي بانك اطلاعاتي (Database Design): بيشتر نرم افزارهاي بزرگي كه در ايران توليد ميشوند به Data Model نياز دارند، چون به احتمال قوي به سيستم اطلاعاتي يك سازمان مربوط ميشود. طراحي بانك اطلاعاتي يكي ديگر از مقولههاي طراحي نرم افزار است كه درنوع خود گسترده است. مخصوصاً اگر Data Warehouse و Data Mining هم به ميان بيايد. جهت مطالعه اين مبحث، اين كتاب توصيه ميشود.
در پايان
سعي كردم نمايي از طراحي را براي خواننده ترسيم كنم. بي شك هر كدام از موارد اشاره شده جدا گانه قابل بررسي و موشكافي است. به مرور در آينده مباحث مهمتر را مورد كنكاش قرار خواهم داد.
لطفاً نظر بدین