مهندسی نرمافزار چیست و چرا برای ساخت محصولات موفق ضروری است؟
hajiali
۲۲ شهریور ۱۴۰۵
زمان مورد نیاز برای مطالعه ۱۰ دقیقه
مهندسی نرمافزار فقط کدنویسی نیست؛ مجموعهای از اصول و روشها برای طراحی، توسعه، تست و نگهداری نرمافزارهای قابل اعتماد و قابل توسعه است. در این مقاله با مفاهیم مهم مهندسی نرمافزار و نقش آن در ساخت محصولات موفق آشنا میشویم.
وقتی صحبت از ساخت یک نرمافزار میشود، معمولاً اولین چیزی که به ذهنمان میرسد کدنویسی است. چند خط کد مینویسیم، برنامه اجرا میشود و تمام.
اما در دنیای واقعی ماجرا کمی متفاوت است.
یک نرمافزار واقعی قرار است ماهها یا حتی سالها توسعه پیدا کند، کاربران مختلفی داشته باشد، ویژگیهای جدید دریافت کند، با سرویسهای دیگر ارتباط برقرار کند و در نهایت پایدار و قابل اعتماد باقی بماند.
اینجاست که مهندسی نرمافزار اهمیت پیدا میکند.
مهندسی نرمافزار کمک میکند بهجای اینکه فقط «کد بزنیم»، بتوانیم نرمافزار درست، قابل نگهداری و قابل توسعه بسازیم.
مهندسی نرمافزار دقیقاً چیست؟
به زبان ساده، مهندسی نرمافزار مجموعهای از اصول، روشها و تجربههایی است که به ما کمک میکند نرمافزار را به شکل اصولی طراحی، توسعه، تست، استقرار و نگهداری کنیم.
پس مهندسی نرمافزار فقط برنامهنویسی نیست.
برنامهنویسی یکی از بخشهای مهندسی نرمافزار است، اما تمام آن نیست.
در یک پروژه واقعی، مسائل مختلفی باید حل شوند:
نیازمندیهای محصول دقیقاً چیست؟
معماری سیستم چگونه باشد؟
دادهها چطور ذخیره و مدیریت شوند؟
کد چگونه سازماندهی شود؟
چطور مطمئن شویم تغییرات جدید چیزی را خراب نمیکنند؟
نرمافزار چطور Deploy شود؟
اگر تعداد کاربران چند برابر شد چه اتفاقی میافتد؟
اگر یکی از سرویسها از کار افتاد چه کنیم؟
چطور کدی بنویسیم که توسعهدهنده دیگری بتواند چند ماه بعد آن را بفهمد؟
اینها تنها بخشی از مسائلی هستند که مهندسی نرمافزار با آنها سروکار دارد.
چرا فقط «کد کار میکند» کافی نیست؟
یکی از رایجترین اشتباهات در پروژههای نرمافزاری این است که موفقیت را فقط با یک معیار بسنجیم:
«برنامه اجرا میشود، پس مشکلی نداریم.»
فرض کنید یک فروشگاه اینترنتی ساختهایم.
در ابتدا فقط چند صد کاربر دارد. سیستم سریع است، کدها سادهاند و همه چیز خوب پیش میرود.
اما بعد از مدتی تعداد کاربران افزایش پیدا میکند. ویژگیهای جدید اضافه میشوند. چند توسعهدهنده دیگر وارد تیم میشوند و تغییرات بیشتری روی سیستم انجام میشود.
اینجاست که مشکلات یکییکی ظاهر میشوند.
یک تغییر کوچک باعث خراب شدن بخش دیگری میشود. رفع یک باگ، باگ دیگری ایجاد میکند. اضافه کردن یک قابلیت ساده چند روز زمان میبرد و توسعهدهندگان قبل از هر تغییر مجبورند با احتیاط در بخشهای مختلف کد جستوجو کنند.
نرمافزار هنوز «کار میکند»، اما دیگر قابل توسعه نیست.
این همان جایی است که تفاوت بین «کدنویسی» و «مهندسی نرمافزار» خودش را نشان میدهد.
ویژگیهای یک نرمافزار مهندسیشده چیست؟
یک نرمافزار خوب فقط نرمافزاری نیست که خروجی صحیح تولید کند.
خوانایی
کد را فقط کامپیوتر اجرا نمیکند؛ انسانها هم باید آن را بخوانند.
نامگذاری مناسب، ساختار منطقی و مسئولیتهای مشخص باعث میشوند فهمیدن کد سادهتر شود.
کد خوب الزاماً کدی نیست که کوتاه باشد. کد خوب، کدی است که واضح باشد.
قابلیت نگهداری
نرمافزار قرار نیست یک بار نوشته شود و برای همیشه کنار گذاشته شود.
محصولات واقعی دائماً تغییر میکنند. نیازهای کاربران، بازار و حتی تکنولوژی تغییر میکنند.
بنابراین معماری و کد باید به شکلی باشند که بتوان تغییرات آینده را با هزینه منطقی روی سیستم اعمال کرد.
تستپذیری
هیچ توسعهدهندهای نمیتواند با اطمینان بگوید:
«من کد را نوشتم و مطمئنم هیچ مشکلی ندارد.»
ما انسان هستیم، نه یک کامپایلر با اعتمادبهنفس بیش از حد.
تستهای نرمافزاری کمک میکنند رفتار سیستم را بررسی کنیم و مطمئن شویم تغییرات جدید باعث خراب شدن قابلیتهای قبلی نشدهاند.
بسته به پروژه میتوان از تستهای مختلفی استفاده کرد:
Unit Test
Integration Test
End-to-End Test
API Test
هدف تست فقط پیدا کردن باگ نیست. تست خوب به تیم اجازه میدهد با اعتماد بیشتری تغییر ایجاد کند.
معماری نرمافزار چرا اهمیت دارد؟
قبل از اینکه یک ساختمان ساخته شود، برای آن نقشه طراحی میشود.
در نرمافزار هم چیزی شبیه به همین اتفاق وجود دارد.
معماری نرمافزار مشخص میکند بخشهای مختلف سیستم چگونه کنار یکدیگر قرار میگیرند و چگونه با هم ارتباط برقرار میکنند.
برای مثال ممکن است یک سیستم شامل بخشهای زیر باشد:
در پروژههای بزرگتر، معماری میتواند پیچیدهتر شود و سرویسهای مختلف، Queueها، Cacheها و سرویسهای خارجی هم وارد سیستم شوند.
اما یک نکته مهم وجود دارد:
معماری پیچیده لزوماً معماری بهتر نیست.
گاهی یک سیستم ساده با یک معماری Monolithic میتواند کاملاً مناسب باشد و نیازی به Microservice نداشته باشد.
یکی از نشانههای یک مهندس نرمافزار خوب این است که بتواند بین پیچیدگی و نیاز واقعی پروژه تعادل برقرار کند.
آیا همیشه باید از جدیدترین تکنولوژی استفاده کنیم؟
نه.
هر تکنولوژی جدیدی لزوماً راهحل بهتری برای پروژه ما نیست.
ممکن است یک تکنولوژی جدید جذاب، سریع و پرطرفدار باشد، اما استفاده از آن در یک پروژه خاص باعث افزایش هزینه نگهداری یا پیچیدگی سیستم شود.
انتخاب تکنولوژی باید بر اساس عواملی مانند این موارد انجام شود:
نیاز محصول
اندازه پروژه
تخصص تیم
هزینه توسعه و نگهداری
مقیاس مورد انتظار
اکوسیستم و پشتیبانی
امنیت
Performance
نیازهای آینده
در مهندسی نرمافزار، سؤال اصلی این نیست که:
«جدیدترین تکنولوژی چیست؟»
سؤال بهتر این است:
«برای این مسئله، سادهترین و قابلاعتمادترین راهحل چیست؟»
نقش مستندسازی در مهندسی نرمافزار
یکی از بخشهایی که معمولاً تا زمانی که مشکل ایجاد نشده جدی گرفته نمیشود، مستندسازی است.
فرض کنید توسعهدهندهای یک سال روی پروژه کار کرده و تصمیمهای مهم معماری را فقط در ذهن خودش نگه داشته است.
اگر فرد دیگری وارد تیم شود، احتمالاً باید بخش زیادی از این اطلاعات را دوباره کشف کند.
مستندات خوب لازم نیست صدها صفحه باشند.
گاهی یک فایل ساده که توضیح دهد:
پروژه چگونه اجرا میشود؟
معماری کلی چیست؟
سرویسها چه کاری انجام میدهند؟
تصمیمهای مهم چرا گرفته شدهاند؟
فرآیند Deploy چگونه است؟
میتواند ساعتها زمان تیم را نجات دهد.
مهندسی نرمافزار یعنی مدیریت پیچیدگی
شاید بتوان مهمترین وظیفه مهندسی نرمافزار را در یک جمله خلاصه کرد:
مدیریت پیچیدگی.
هرچه یک محصول رشد میکند، پیچیدگی آن هم بیشتر میشود.
تعداد قابلیتها افزایش پیدا میکند، کاربران بیشتر میشوند، سرویسهای بیشتری به سیستم متصل میشوند و تیم توسعه بزرگتر میشود.
اگر این پیچیدگی کنترل نشود، توسعه نرمافزار بهمرور سختتر و پرهزینهتر میشود.
مهندسی نرمافزار کمک میکند این پیچیدگی را به بخشهای کوچکتر و قابل مدیریت تقسیم کنیم.
چند اصل ساده اما مهم
برای ساخت نرمافزارهای قابل اعتماد، لازم نیست همیشه از پیچیدهترین معماریها استفاده کنیم.
گاهی رعایت چند اصل ساده تأثیر بسیار بیشتری دارد:
ساده نگه دارید
هر پیچیدگی جدید باید دلیل مشخصی داشته باشد.
مسئولیتها را جدا کنید
هر بخش از سیستم بهتر است وظیفه مشخصی داشته باشد.
برای آینده بیش از حد طراحی نکنید
قرار نیست امروز مشکلاتی را حل کنیم که شاید سه سال دیگر وجود داشته باشند.
کد را قابل تغییر نگه دارید
تغییر بخش طبیعی زندگی یک محصول نرمافزاری است.
کیفیت را بخشی از فرآیند بدانید
کیفیت چیزی نیست که در آخر پروژه به نرمافزار اضافه شود.
مهندسی نرمافزار در نهایت درباره انسانهاست
ممکن است عجیب به نظر برسد، اما بخش بزرگی از مهندسی نرمافزار درباره کد نیست.
درباره آدمهاست.
توسعهدهندگان باید بتوانند کد یکدیگر را بفهمند.
تیم محصول باید بتواند با تیم فنی ارتباط مناسبی داشته باشد.
تصمیمهای معماری باید قابل توضیح باشند.
و دانش پروژه نباید فقط در ذهن یک نفر باقی بماند.
یک نرمافزار خوب، نتیجه همکاری خوب بین افراد، فرآیندهای مناسب و تصمیمهای فنی درست است.
جمعبندی
مهندسی نرمافزار یعنی نگاه کردن به توسعه نرمافزار بهعنوان یک مسئله بلندمدت، نه صرفاً نوشتن چند خط کد برای حل یک مشکل امروز.
یک نرمافزار مهندسیشده باید تا حد امکان:
قابل فهم باشد
قابل تست باشد
قابل نگهداری باشد
قابلیت توسعه داشته باشد
امنیت مناسبی داشته باشد
در صورت نیاز مقیاسپذیر باشد
و مهمتر از همه، متناسب با نیاز واقعی محصول طراحی شده باشد.
در نهایت، هدف مهندسی نرمافزار ساخت پیچیدهترین سیستم ممکن نیست.
هدف این است که با کمترین پیچیدگی غیرضروری، نرمافزاری بسازیم که امروز نیاز کاربران را حل کند و فردا هم بتوانیم بدون ترس آن را تغییر دهیم.
و شاید همین تفاوت اصلی بین «کدنویسی» و «مهندسی نرمافزار» باشد.