چگونه یک نرمافزار اختصاصی موفق بسازیم؟ | تجربههای واقعی یک برنامهنویس
مقدمه
در طول سالها فعالیت در حوزه طراحی و توسعه نرمافزار، مشتریان زیادی با من تماس گرفتهاند و گفتهاند که پس از صرف زمان و هزینه قابل توجه، پروژههای نرمافزاری آنها با مشکل مواجه شده است. برخی برای بررسی علت مشکل و دریافت مشاوره به من مراجعه کردهاند و برخی دیگر خواستهاند نرمافزار موجودشان را اصلاح، توسعه یا حتی از ابتدا بازنویسی کنم.
در بسیاری از این پروژهها، ریشه اصلی مشکلات به موضوعاتی برمیگشت که اگر پیش از شروع، بهدرستی مورد توجه قرار میگرفت، میتوانست تا حد زیادی از بروز مشکلات بعدی جلوگیری کند.
این تجربهها به من نشان داد که موفقیت یک پروژه نرمافزاری خیلی قبل از شروع برنامهنویسی شکل میگیرد.
در این مقاله، قصد ندارم درباره اصول طراحی نرمافزار، انتخاب زبان برنامهنویسی یا فناوریهای مورد استفاده صحبت کنم. میخواهم بخشی از تجربههایی را مطرح کنم که در پروژههای واقعی به دست آوردهام؛ تجربههایی که نشان میدهند چگونه بعضی تصمیمها، بیتوجهیها یا حتی مشاورههای نادرست میتوانند مسیر یک پروژه نرمافزاری را تغییر دهند.
هدف این مقاله این است که اگر قرار است یک نرمافزار اختصاصی بسازیم، بدانیم نیازمندیها، فرآیندها، طراحی و تصمیمهای اولیه چگونه میتوانند بر موفقیت یا شکست یک پروژه نرمافزاری تأثیر بگذارند.
بخشی از این تجربهها در همین مقاله آمده است. نمونههای بیشتری از اتفاقات و چالشهای واقعی پروژهها را میتوانید در بخش تجربههای واقعی بخوانید.
۱. چرا پروژههای نرمافزاری شکست میخورند؟
وقتی از شکست یک پروژه صحبت میکنیم، منظور فقط پروژهای نیست که نیمهکاره رها شده یا هیچگاه به مرحله اجرا نرسیده است.
به نظر من، یک پروژه نرمافزاری زمانی شکستخورده محسوب میشود که در نهایت نتواند به هدفی که برای آن تعریف شده است برسد ؛ چه به دلیل صرف زمان و هزینه بیشتر از انتظار، چه به دلیل کیفیت نامناسب نرمافزار یا برآورده نشدن نیاز واقعی مشتری.
مهمترین عوامل شکست پروژههای نرمافزاری عبارتاند از:
- شناخت نادرست نیاز واقعی مشتری
- شروع برنامهنویسی بدون تحلیل کافی
- مشخص نبودن محدوده و تعهدات پروژه
- طراحی نامناسب نرمافزار برای توسعههای آینده
- تغییرات بدون بررسی اثر آنها بر سایر بخشها
- آموزش و پشتیبانی نامناسب
- تشخیص اشتباه علت مشکلات نرمافزار
- بیتوجهی به امنیت، پشتیبانگیری و آمادگی برای شرایط پیشبینینشده
در ادامه مقاله، مهمترین این موارد را با جزئیات بیشتری بررسی میکنیم و در کنار آن، تجربههایی از پروژههای واقعی را نیز مطرح خواهم کرد.
۲. شناسایی نیاز مشتری و تحلیل دقیق قبل از شروع برنامهنویسی
یکی از مهمترین اشتباهاتی که میتواند یک پروژه نرمافزاری را از همان ابتدا وارد مسیر اشتباه کند، شروع برنامهنویسی بدون شناخت دقیق نیاز واقعی مشتری و فرآیند کاری اوست.
مشتری معمولاً کسبوکار خود را بهتر از هر کسی میشناسد، اما ممکن است هنگام توضیح نیاز خود، همه جزئیات فرآیند را بیان نکند. وظیفه برنامهنویس نیز فقط اجرای درخواست اولیه نیست؛ بلکه باید با پرسیدن سؤالهای درست، مسئله و فرآیند واقعی را بهتر بشناسد.
۲.۱. وقتی درخواست اولیه، تمام نیاز مشتری نیست
در یکی از پروژههای سالهای ابتدایی فعالیت حرفهایام، مدیر یک کارخانه از من خواست یک اتوماسیون ساده برای ارسال نامه به واحد اداری طراحی کنم.
پیش از شروع، نرمافزارهای آماده موجود در بازار را نیز پیشنهاد کردم، اما او معتقد بود امکانات آنها بیش از نیازش است و فقط یک سیستم ساده میخواهد.
من هم بدون اینکه فرآیند کامل مکاتبات را بررسی و با او نهایی کنم، نرمافزار را بر اساس همان توضیح اولیه طراحی کردم.
پس از نصب، اولین نامه ارسال شد؛ اما بلافاصله سؤالهای دیگری مطرح شد:
واحد اداری چگونه پاسخ دهد؟ مدیر چگونه پاسخ را ببیند؟ امضا چگونه انجام شود؟ نامه چگونه برای واحد دیگری ارسال و پیگیری شود؟
آنجا متوجه شدم که چیزی که در ابتدا فقط «ارسال یک نامه» به نظر میرسید، در عمل بخشی از یک فرآیند کامل مکاتبات بود.
این تجربه به من یاد داد که آنچه مشتری در ابتدا بیان میکند، همیشه تمام نیاز واقعی او نیست. قبل از شروع برنامهنویسی باید فرآیند واقعی کار را شناخت و درباره آن سؤالهای لازم را پرسید.
۲.۲. وقتی یک فرم ساده، فقط یک فرم نیست
در پروژه دیگری، از من خواسته شد یک فرم آنلاین برای ثبت مشخصات خریداران دستگاههای کارتخوان و فعالسازی دستگاه طراحی کنم.
در نگاه اول، پروژه فقط یک فرم به نظر میرسید؛ اما بررسی فرآیند نشان داد که پشت این فرم، اعتبارسنجی اطلاعات، تطبیق مشخصات دستگاه و خریدار، ارسال کد یکبارمصرف، مدیریت خطاها، امنیت اطلاعات و همچنین پنلهای مدیریتی و مشتریان قرار دارد.
به همین دلیل، زمان اجرای پروژه را بیشتر از چیزی که در نگاه اول تصور میشد برآورد کردم.
این تجربه نشان داد که ظاهر ساده یک درخواست، لزوماً به معنی ساده بودن پروژه نیست. برای تخمین زمان و هزینه، باید فرآیندهای پشت درخواست را نیز شناخت.
جزئیات این تجربه را میتوانید در تجربه «وقتی یک فرم ساده، ۲۰ روز زمان برد» بخوانید.
جمعبندی این بخش
این دو تجربه، هر کدام از زاویهای متفاوت یک نکته مشترک را نشان میدهند:
قبل از نوشتن کد، باید مسئله واقعی و فرآیند کاری را درست فهمید.
گاهی یک درخواست اولیه، فقط بخشی از نیاز واقعی مشتری است و گاهی چیزی که ساده به نظر میرسد، در پشت صحنه پیچیدگی زیادی دارد.
به همین دلیل، تحلیل دقیق قبل از شروع برنامهنویسی، یکی از مهمترین مراحل ساخت یک نرمافزار اختصاصی است.
۳. قبل از شروع پروژه نرمافزاری، چه مواردی باید مشخص و توافق شود؟
یکی از مهمترین کارها در آغاز یک پروژه نرمافزاری، مشخص کردن چارچوب و جزئیات اصلی آن است.
پس از اینکه نیازهای مشتری و فرآیندهای کاری او بهدرستی بررسی شد، باید مشخص کنیم دقیقاً چه چیزی قرار است ساخته شود، چه خروجیهایی باید تحویل داده شوند، مسئولیت هر یک از طرفین چیست، پروژه چه زمانبندی و تاریخ تحویلی دارد و هزینه آن چگونه محاسبه و پرداخت خواهد شد.
هرچه این موارد قبل از شروع برنامهنویسی شفافتر باشند، احتمال اختلاف، تغییرات پیشبینینشده و مشکلات بعدی کمتر خواهد شد.
۳.۱. محدوده پروژه باید مشخص باشد
باید از ابتدا مشخص شود چه امکاناتی در پروژه قرار است پیادهسازی شوند و چه مواردی خارج از توافق اولیه هستند.
در طول پروژه ممکن است درخواستهایی مانند امکانات جدید، گزارشهای اضافی، اتصال به سامانههای دیگر یا نسخه موبایل مطرح شوند. هرکدام از این موارد میتوانند یک قابلیت جدید یا حتی یک پروژه مستقل باشند.
بنابراین باید مشخص باشد چه چیزی جزو پروژه است و چه چیزی درخواست جدید محسوب میشود.
۳.۲. زمانبندی و تاریخ تحویل باید مشخص باشد
زمان اجرای پروژه باید بر اساس حجم کار، پیچیدگی، مراحل اجرا و تعهدات طرفین تعیین شود.
اعلام یک زمان کلی مانند «حدود سه ماه» بدون مشخص کردن مراحل پروژه، میتواند در ادامه باعث اختلاف شود؛ بهخصوص اگر مشخص نباشد تأخیر در کدام مرحله و به دلیل چه عاملی اتفاق افتاده است.
بهتر است زمانبندی پروژه بر اساس مراحل و تعهدات مشخص تعیین شود.
۳.۳. هزینه و نحوه پرداخت باید روشن باشد
از ابتدا باید مشخص شود مبلغ پروژه دقیقاً بابت چه امکانات و خدماتی است، پرداختها در چه مراحلی انجام میشوند و درخواست امکانات جدید چه تأثیری بر هزینه خواهد داشت.
تغییرات پروژه میتوانند زمان و هزینه اجرای آن را تغییر دهند؛ بنابراین نحوه برخورد با تغییرات باید از ابتدا مشخص باشد.
۳.۴. مسئولیتهای دو طرف باید مشخص باشد
یک پروژه نرمافزاری فقط به مسئولیتهای مجری محدود نمیشود.
کارفرما نیز ممکن است وظایفی مانند ارائه اطلاعات صحیح، تأیید فرآیندها، پاسخگویی، آزمایش و تأیید بخشهای تحویلشده را بر عهده داشته باشد.
اگر این مسئولیتها مشخص نباشند، تأخیر در ارائه اطلاعات یا تصمیمگیری میتواند باعث توقف پروژه شود و در نهایت اختلاف ایجاد کند.
۳.۵. حقوق و مالکیت نرمافزار باید از ابتدا مشخص شود
یکی از موضوعاتی که گاهی پس از پایان پروژه باعث اختلاف میشود، مالکیت نرمافزار و سورسکد است.
ممکن است کارفرما تصور کند با پرداخت هزینه و دریافت نرمافزار، سورسکد نیز بهصورت خودکار در اختیار او قرار میگیرد؛ در حالی که این موضوع باید از ابتدا مشخص شده باشد.
بهتر است پیش از شروع پروژه درباره مواردی مانند اینها توافق شود:
- مالکیت نرمافزار با چه کسی است؟
- آیا سورسکد نیز در اختیار مشتری قرار میگیرد؟
- مشتری چه حقی برای استفاده یا توسعه نرمافزار دارد؟
- آیا امکان واگذاری یا انتقال نرمافزار به شخص یا مجموعه دیگری وجود دارد؟
- در صورت تحویل سورسکد، مسئولیت توسعه و نگهداری آن بر عهده چه کسی خواهد بود؟
در یکی از پروژههایی که با چنین موضوعی مواجه شدم، کارفرما هنگام درخواست سورسکد متوجه شد که این موضوع در قرارداد بهروشنی مشخص شده و تحویل سورس جزو تعهدات اولیه پروژه نبوده است.
جزئیات این تجربه را میتوانید در تجربه «وقتی مشتری بعد از تحویل پروژه سورسکد را درخواست کرد» بخوانید.
این تجربه نشان داد که صرف داشتن قرارداد کافی نیست؛ طرفین باید پیش از امضا، مفاد آن را بهدقت مطالعه کنند و دقیقاً بدانند چه حقوق و تعهداتی را میپذیرند.
۳.۶. شرایط تحویل و تعهدات پس از آن باید مشخص باشد
باید مشخص شود منظور از «تحویل پروژه» دقیقاً چیست.
آیا نصب نرمافزار به معنی پایان پروژه است؟ آیا آموزش کاربران جزو تعهدات است؟ آیا مشتری باید امکانات را آزمایش و تأیید کند؟ رفع اشکالات پس از تحویل چگونه انجام خواهد شد؟
همچنین بهتر است وضعیت پشتیبانی و مسئولیتهای طرفین پس از تحویل نیز از ابتدا مشخص شود.
بنابراین مراحل تحویل، نحوه تأیید و تعهدات پس از تحویل باید از ابتدا مشخص باشند.
۳.۷. در نهایت، قبل از شروع پروژه چه چیزهایی باید مشخص باشند؟
بهطور خلاصه، پیش از شروع پروژه بهتر است درباره این موارد به توافق رسیده باشیم:
- مسئله و نیاز واقعی مشتری
- محدوده و امکانات پروژه
- فرآیندها و الگوریتمهای اصلی
- زمانبندی و مراحل تحویل
- هزینه و نحوه پرداخت
- مسئولیتهای مشتری و مجری
- مالکیت نرمافزار و وضعیت سورسکد
- شرایط تحویل و پشتیبانی
- نحوه مدیریت تغییرات و امکانات جدید
این موارد قرار نیست تمام جزئیات یک پروژه نرمافزاری را از همان روز اول مشخص کنند؛ اما کمک میکنند پروژه را با شناخت و توافق کافی آغاز کنیم.
در واقع، قبل از شروع کدنویسی باید درباره خود پروژه، مسئولیتها و حقوق طرفین به توافق رسیده باشیم، نه فقط درباره ایده آن.
۴. طراحی الگوریتم و تأیید آن قبل از کدنویسی
بعد از مشخص شدن نیازمندیهای واقعی پروژه، هنوز نباید وارد مرحله برنامهنویسی شویم.
مرحله بعد، تبدیل نیازمندیها به فرآیند و الگوریتم مشخص است. در این مرحله باید دقیقاً مشخص شود نرمافزار چه مراحلی را طی میکند و بر اساس چه منطقی عمل خواهد کرد.
برای مثال، اگر مشتری بگوید:
«میخواهم یک نرمافزار مدیریت چک داشته باشم.»
این توضیح برای شروع برنامهنویسی کافی نیست.
باید مشخص شود چکها چگونه ثبت میشوند، وضعیت چک برگشتی چگونه مدیریت میشود، انتقال چک چگونه ثبت خواهد شد، سررسیدها چگونه پیگیری میشوند و سوابق و گزارشها چگونه در اختیار کاربر قرار میگیرند.
تا زمانی که پاسخ این پرسشها مشخص نشده باشد، برنامهنویسی زود است.
کد در واقع نتیجه تصمیمهایی است که قبل از آن گرفته شدهاند.
اگر فرآیند درست طراحی نشده باشد، حتی نرمافزاری که از نظر فنی بدون خطا نوشته شده است نیز ممکن است نتواند نیاز واقعی کارفرما را برطرف کند.
به همین دلیل ترجیح میدهم ابتدا فرآیند کاری مشخص شود و پس از بررسی و تأیید آن، وارد مرحله طراحی و کدنویسی شوم.
در پروژههای بزرگتر و پیچیدهتر میتوان برای بررسی و مستندسازی فرآیندها از ابزارهایی مانند Use Case، Activity Diagram و Flowchart نیز استفاده کرد. هدف در اینجا آموزش این نمودارها نیست؛ نکته اصلی این است که منطق و فرآیند نرمافزار باید قبل از شروع کدنویسی مشخص و با افراد مسئول در مجموعه بررسی و تأیید شود.
یک تجربه واقعی؛ وقتی نرمافزار درست بود اما کاربر آن را نمیپذیرفت
در یکی از پروژهها، پس از حدود یک سال استفاده، مشتری اعلام کرد که نرمافزار آن چیزی نیست که انتظار داشته است.
پس از بررسی مشخص شد الگوریتم و فرآیند کاری نرمافزار پیش از اجرا به تأیید مدیریت و کارشناس فنی شرکت رسیده و نرمافزار نیز دقیقاً بر اساس همان فرآیند پیادهسازی شده بود.
در ادامه مشخص شد یکی از کارکنان شرکت سالها به روش سنتی و کاغذی عادت کرده و در برابر تغییر روش کار و استفاده از نرمافزار مقاومت میکند.
این تجربه برای من نشان داد که موفقیت یک پروژه فقط به ساخت نرمافزار درست وابسته نیست؛ کاربران نیز باید تغییر روش کار را بپذیرند و برای استفاده از سیستم جدید آماده باشند.
جزئیات بیشتر این تجربه را میتوانید در تجربه «وقتی مشتری گفت این چیزی نیست که میخواستیم» بخوانید.
چرا تأیید الگوریتم اهمیت دارد؟
برنامهنویس متخصص طراحی و پیادهسازی نرمافزار است، اما تأیید اینکه فرآیند طراحیشده با روش کار و نیازهای مجموعه مطابقت دارد، بر عهده کارفرماست.
برنامهنویس فرآیند مورد توافق را به زبان نرمافزار تبدیل میکند. بنابراین بهتر است قبل از شروع کدنویسی، الگوریتم و منطق اصلی سیستم توسط افراد مسئول بررسی و تأیید شود.
تغییر الگوریتم یعنی تغییر در پروژه
اگر نرمافزار برخلاف الگوریتم تأییدشده عمل کند، این یک اشکال است و باید اصلاح شود.
اما اگر بعداً خود فرآیند تغییر کند، دیگر با یک اصلاح ساده روبهرو نیستیم. تغییر الگوریتم ممکن است روی بانک اطلاعاتی، فرمها، محاسبات، گزارشها و بخشهای مختلف سیستم اثر بگذارد و در نتیجه زمان و هزینه پروژه را نیز تغییر دهد.
مستندسازی؛ حافظه پروژه
نیازمندیها، الگوریتمها، تغییرات و تأییدیههای مهم بهتر است ثبت شوند.
پروژههای نرمافزاری ممکن است ماهها طول بکشند و افراد مختلفی درگیر آنها شوند. حافظه افراد همیشه مرجع دقیقی برای تصمیمات گذشته نیست، اما مستندات میتوانند مشخص کنند:
چه چیزی درخواست شد، چه چیزی توافق شد و چه چیزی در نهایت پیادهسازی شد.
به همین دلیل، یکی از اصولی که در پروژههای نرمافزاری به آن پایبند هستم این است:
قبل از اینکه کد نوشته شود، باید درباره منطق و فرآیندی که قرار است کد آن را پیادهسازی کند، به توافق رسیده باشیم.
۵. طراحی نرمافزار برای تغییرات و توسعههای آینده
یکی از اشتباهات رایج در پروژههای نرمافزاری، طراحی سیستم فقط بر اساس نیازهای امروز است؛ بدون اینکه تغییرات احتمالی آینده در نظر گرفته شود.
البته منظور از طراحی برای آینده این نیست که تمام امکانات احتمالی سالهای بعد را از همان ابتدا پیادهسازی کنیم. منظور این است که ساختار نرمافزار تا حد منطقی قابلیت توسعه و تغییر داشته باشد.
ممکن است یک نرمافزار در زمان تحویل کاملاً درست کار کند، اما چند ماه بعد با تغییر فرآیند کاری، افزایش کاربران یا اضافه شدن یک قابلیت جدید، مشخص شود که ساختار آن برای توسعه مناسب نبوده است. در چنین شرایطی، یک تغییر ساده میتواند به تغییر بخشهای مختلف سیستم و دوبارهکاری زیادی منجر شود.
یکی از تجربههای من در این زمینه مربوط به طراحی سامانهای برای مدیریت شبکه فروش و محاسبه پورسانت یک شرکت بیمه بود. در این پروژه، علاوه بر ثبت بازاریابها و ساختار شبکه، محاسبه پورسانت فروش مستقیم و فروش زیرمجموعهها تا چند سطح نیز بر عهده نرمافزار بود.
از ابتدا مشخص بود که مدل پورسانت ممکن است پس از شروع فعالیت واقعی شبکه تغییر کند. به همین دلیل، پیش از شروع توسعه، جلسات متعددی با مدیران مجموعه برگزار کردم تا علاوه بر نیازهای فعلی، سناریوهای احتمالی تغییر در آینده را بررسی کنم.
در نتیجه، نرمافزار به شکلی طراحی شد که نسخههای مختلف پلن پورسانت قابل مدیریت باشند و سوابق محاسبات دورههای گذشته با تغییر قوانین از بین نروند. همچنین افزایش تعداد بازاریابها و حجم محاسبات نیز در طراحی سیستم در نظر گرفته شد.
در طول حدود یک سال، پلن پورسانت چندین مرتبه تغییر کرد و نرمافزار نیز متناسب با این تغییرات توسعه یافت. اگر ساختار سیستم فقط برای قوانین روز اول طراحی شده بود، هر تغییر میتوانست هزینه و زمان زیادی ایجاد کند.
این تجربه به من نشان داد که تحلیل یک نرمافزار فقط پاسخ دادن به این سؤال نیست که:
«امروز چه امکاناتی نیاز داریم؟»
بلکه باید تا حد منطقی این سؤال را نیز مطرح کنیم:
«اگر نیازهای ما در آینده تغییر کند، این نرمافزار چقدر توانایی تغییر خواهد داشت؟»
البته پیشبینی همه تغییرات آینده ممکن نیست و تلاش برای ساختن نرمافزاری که برای هر شرایط احتمالی آماده باشد، خودش میتواند باعث پیچیدگی و هزینه اضافی شود. هدف، طراحی بیش از حد نیست؛ هدف این است که تصمیمهای فنی امروز، دست ما را برای تغییرات منطقی فردا نبندند.
جزئیات این تجربه را میتوانید در تجربه «وقتی نیاز امروز برای یک سال کافی نبود» بخوانید.
در پروژههایی که حجم اطلاعات نیز بهمرور افزایش پیدا میکند، رشد دادهها میتواند روی عملکرد نرمافزار اثر بگذارد. این موضوع نیز باید در طراحی و توسعه سیستم در نظر گرفته شود.
در این زمینه میتوانید تجربه «وقتی نرمافزار با رشد اطلاعات کند میشود» را نیز بخوانید.
۶. استقرار، آموزش و پشتیبانی؛ پایان برنامهنویسی، پایان پروژه نیست
تولید نرمافزار با تحویل کد و نصب برنامه به پایان نمیرسد. استقرار صحیح، آموزش کاربران و پشتیبانی پس از راهاندازی نیز بخشی از موفقیت پروژه هستند.
نرمافزار در خلأ اجرا نمیشود. سرور، شبکه، بانک اطلاعاتی، تنظیمات سیستم، سطح دسترسی کاربران و سرویسهای وابسته همگی میتوانند بر عملکرد نرمافزار تأثیر بگذارند.
از طرف دیگر، کاربران نیز باید بدانند نرمافزار بر اساس چه قواعدی طراحی شده و چگونه باید از آن استفاده کنند. بسیاری از محدودیتها و الزامهای موجود در نرمافزار برای سختتر کردن کار کاربران نیستند؛ بلکه برای جلوگیری از خطاهای بعدی در نظر گرفته شدهاند.
برای مثال، ممکن است ثبت کد ملی در سیستم اجباری باشد. اگر کاربر به دلیل سرعت بیشتر درخواست حذف این الزام را داشته باشد، شاید در ابتدا کار سادهتر شود؛ اما در ادامه احتمال ثبت چندباره یک مشتری و ایجاد مغایرت در اطلاعات و گزارشها افزایش پیدا میکند.
بنابراین سادگی نرمافزار به معنی بینیازی از آموزش نیست.
وقتی کاربر میگوید «برنامه باگ دارد»
یکی از اشتباهات رایج در زمان بروز مشکل این است که بدون بررسی، مشکل را به کد نرمافزار نسبت دهیم.
در حالی که علت میتواند ورود نادرست اطلاعات، استفاده نادرست از سیستم، تنظیمات سرور، شبکه، سطح دسترسی یا ارتباط با یک سرویس دیگر باشد.
در چنین شرایطی، هر مشکلی را نباید با تغییر کد حل کرد. ابتدا باید علت واقعی مشکل مشخص شود و سپس راهحل مناسب انتخاب شود.
یکی از تجربههای من در این زمینه مربوط به پروژهای بود که نرمافزار باید از طریق API با یک سرور دیگر ارتباط برقرار میکرد. مدتی ارتباط برقرار نمیشد و هر دو طرف معتقد بودند مشکل از طرف مقابل است. با بررسی مرحلهبهمرحله مشخص شد مشکل از تنظیمات سمت سرور بوده است.
جزئیات این تجربه را میتوانید در «وقتی مشتری بین برنامهنویس و کارشناس سرور گرفتار میشود» بخوانید.
این تجربه به من یاد داد که در مشکلات فنی، پیدا کردن مقصر مهم نیست؛ پیدا کردن علت واقعی مشکل مهم است.
تجربه دیگری نیز داشتم که مشتری تصور میکرد نرمافزار در محاسبات مالی اشتباه میکند، اما پس از بررسی مشخص شد اطلاعات اشتباه از قبل و بهصورت دستی وارد سیستم شدهاند. نرمافزار در واقع محاسبه صحیح را انجام میداد و حتی توانسته بود خطاهایی را که در روش قبلی وجود داشت آشکار کند.
جزئیات این تجربه را میتوانید در «وقتی مشکل نرمافزار نیست، اما همه فکر میکنند باگ است» بخوانید.
گاهی نرمافزار مشکل را ایجاد نمیکند؛ بلکه مشکلی را که پیش از آن وجود داشته، آشکار میکند.
پشتیبانی فقط رفع باگ نیست
پشتیبانی مناسب یعنی هر مشکل گزارششده ابتدا بررسی شود تا مشخص شود منشأ آن کجاست.
برای مثال:
- آیا اطلاعات درست وارد شدهاند؟
- آیا کاربر آموزش لازم را دیده است؟
- آیا سطح دسترسیها صحیح است؟
- آیا سرور و شبکه وضعیت مناسبی دارند؟
- آیا ارتباط با سرویسهای دیگر برقرار است؟
- آیا مشکل از تنظیمات یا زیرساخت است؟
- و در نهایت، آیا واقعاً نیاز به تغییر نرمافزار وجود دارد؟
ممکن است پاسخ، اصلاح کد باشد؛ اما گاهی راهحل درست، آموزش کاربر، اصلاح تنظیمات یا تغییر فرآیند کاری است.
به همین دلیل، پروژه نرمافزاری با پایان برنامهنویسی تمام نمیشود. استقرار صحیح، آموزش کاربران و پشتیبانی مناسب کمک میکنند نرمافزار در محیط واقعی نیز همان هدفی را که برای آن طراحی شده است، دنبال کند.
۷. تغییرات و توسعههای پس از تحویل؛ چرا هر تغییر کوچکی ساده نیست؟
بعد از نصب و استفاده واقعی از نرمافزار، معمولاً درخواستهای جدیدی مطرح میشوند. این موضوع طبیعی است؛ زیرا گاهی تنها پس از کار کردن با سیستم مشخص میشود که چه تغییرات یا امکاناتی موردنیاز است.
اما مشکل از جایی شروع میشود که تصور کنیم اضافه کردن هر قابلیت جدید فقط به معنی نوشتن چند خط کد است.
نرمافزار مجموعهای از بخشهای مرتبط با یکدیگر است و تغییر در یک قسمت ممکن است روی بخشهای دیگری مانند بانک اطلاعاتی، محاسبات، گزارشها یا فرآیندهای مرتبط اثر بگذارد.
به همین دلیل، قبل از اجرای هر تغییر بهتر است مشخص شود:
- این تغییر دقیقاً چه مشکلی را حل میکند؟
- چه بخشهایی را تحت تأثیر قرار میدهد؟
- آیا با ساختار فعلی نرمافزار سازگار است؟
- آیا اطلاعات یا محاسبات قبلی تحت تأثیر قرار میگیرند؟
- آیا پس از انجام تغییر، بخشهای مرتبط باید دوباره آزمایش شوند؟
هر درخواست جدید الزاماً رفع اشکال نیست
یکی از موضوعاتی که بهتر است از ابتدا برای آن توافق شود، تفاوت میان رفع اشکال و توسعه جدید است.
اگر نرمافزار مطابق نیازمندیهای تأییدشده تحویل شده باشد و مشتری بعداً تصمیم بگیرد قابلیت یا فرآیند جدیدی به آن اضافه شود، این موضوع معمولاً یک درخواست توسعه است، نه رفع اشکال.
برای مثال، اگر نرمافزار طبق توافق امکان صدور یک نوع فاکتور را داشته باشد و مشتری چند ماه بعد درخواست نوع دیگری از فاکتور را مطرح کند، این یک نیاز جدید محسوب میشود.
شفاف بودن این موضوع از اختلافات بعدی درباره زمان و هزینه جلوگیری میکند.
یک تجربه از نرمافزارهای قبلی مشتریان
برخی از مشتریانی که برای ساخت نرمافزار جدید به من مراجعه کردهاند، درباره نرمافزار قبلی خود جملهای شبیه این میگفتند:
«هر جایی را تغییر میدهیم، جای دیگری خراب میشود.»
در بعضی از این پروژهها، توسعههای متعدد بدون بررسی ارتباط میان بخشهای مختلف انجام شده بود. در نتیجه، هر تغییر جدید میتوانست مشکلات دیگری ایجاد کند و نگهداری نرمافزار را دشوارتر کند.
این تجربه نشان میدهد که توسعه نرمافزار فقط اضافه کردن قابلیت جدید نیست؛ بلکه باید اثر آن بر کل سیستم نیز بررسی شود.
میتوانید جزئیات یکی از این تجربهها را در «وقتی یک تغییر کوچک، کل ساختار نرمافزار را تغییر میدهد» بخوانید.
بیشتر بودن امکانات، الزاماً به معنی بهتر بودن نرمافزار نیست
گاهی تصور میشود هرچه امکانات بیشتری به نرمافزار اضافه شود، نرمافزار بهتر خواهد شد.
اما اضافه کردن قابلیتهای متعدد بدون توجه به نیاز واقعی میتواند نرمافزار را پیچیدهتر و نگهداری آن را دشوارتر کند.
حتی یک تغییر ظاهراً کوچک، مانند اصلاح یک فرمول، ممکن است روی چند گزارش یا محاسبه دیگر اثر بگذارد. بنابراین توسعهدهنده باید پیش از اجرای تغییر، ارتباطات آن را بررسی و پس از انجام آن، بخشهای مرتبط را آزمایش کند.
تغییر را نباید متوقف کرد؛ باید آن را کنترل کرد
نیازهای یک کسبوکار ثابت نمیمانند. فرآیندها تغییر میکنند، کاربران نیازهای جدید پیدا میکنند و شرایط کسبوکار نیز ممکن است عوض شود.
بنابراین هدف، جلوگیری از تغییر نیست؛ بلکه تغییر باید آگاهانه و کنترلشده انجام شود.
برای هر درخواست جدید بهتر است ابتدا نیاز مشخص شود، اثر آن بر نرمافزار بررسی شود، زمان و هزینه آن برآورد شود و سپس درباره اجرای آن تصمیمگیری شود.
اگر تغییر تأیید شد، بهتر است ثبت شود و پس از توسعه نیز بخشهای مرتبط مورد آزمایش قرار گیرند.
در نهایت، یک نکته را نباید فراموش کرد:
هر تغییر کوچک، لزوماً یک تغییر ساده نیست.
قبل از اجرای هر تغییر باید پرسید:
«این تغییر چه چیزی را حل میکند و چه بخشهایی را تحت تأثیر قرار میدهد؟»
توسعه صحیح یعنی نرمافزار را تغییر دهیم، بدون اینکه بخشهایی را که قبلاً درست کار میکردند، قربانی کنیم.
۸. امنیت، پشتیبانگیری و آمادگی برای اتفاقات پیشبینینشده
یک نرمافزار حرفهای فقط برای شرایط عادی طراحی نمیشود.
ممکن است سرور دچار مشکل شود، اطلاعات آسیب ببینند، شبکه مختل شود یا یک حمله امنیتی عملکرد سیستم را تحت تأثیر قرار دهد.
تجربه به من نشان داده است که کیفیت واقعی یک سیستم و نحوه پشتیبانی از آن، گاهی زمانی مشخص میشود که یک اتفاق غیرمنتظره رخ میدهد.
پشتیبانگیری را نباید به روز حادثه موکول کرد
در یکی از پروژهها، بانک اطلاعاتی مشتری دچار مشکل شد و دسترسی به اطلاعات با دشواری جدی مواجه شد. بررسیها نشان داد که مدتی نیز از اطلاعات نسخه پشتیبان تهیه نشده بود.
با صرف زمان و بررسیهای فنی، مشکل برطرف شد و اطلاعات قابل بازیابی به سیستم بازگردانده شد.
این تجربه یک درس مهم داشت:
پشتیبانگیری باید زمانی انجام شود که اطلاعات سالم هستند، نه زمانی که دیگر به اطلاعات اصلی دسترسی نداریم.
جزئیات این تجربه را میتوانید در «وقتی داشتن بکاپ کافی نیست» بخوانید.
Backup فقط کپی کردن یک فایل یا دیتابیس نیست. باید مشخص باشد نسخه پشتیبان با چه فاصلهای تهیه میشود، کجا نگهداری میشود، چه مدت باقی میماند و در صورت بروز مشکل چگونه بازیابی خواهد شد.
مهمتر از همه، فرآیند بازیابی نیز باید آزمایش شود. داشتن یک نسخه پشتیبان که در زمان حادثه قابل استفاده نباشد، عملاً مشکل را حل نمیکند.
امنیت فقط به کدنویسی محدود نمیشود
در یکی دیگر از پروژهها، مجموعه با حملات مخرب مواجه شد و در نتیجه سرعت شبکه بهشدت کاهش پیدا کرد و عملکرد نرمافزار نیز تحت تأثیر قرار گرفت.
از دید کاربر، نرمافزار کند شده بود؛ اما منشأ مشکل در زیرساخت شبکه قرار داشت.
پس از بررسی و اقدامات لازم، مشکل برطرف شد.
این تجربه نشان داد که امنیت یک سیستم فقط به کدنویسی امن محدود نمیشود.
سرور، شبکه، سیستمعامل، تنظیمات دسترسی و نحوه نگهداری اطلاعات نیز بخشی از امنیت یک سامانه هستند.
دسترسی بیشتر همیشه بهتر نیست
گاهی کاربران درخواست دسترسیهای بیشتری دارند، چون تصور میکنند هرچه محدودیت کمتری داشته باشند، کارها سریعتر انجام میشود.
اما هر دسترسی اضافه، مسئولیت و ریسک بیشتری نیز ایجاد میکند.
سطح دسترسی کاربران باید بر اساس وظایف واقعی آنها تعیین شود؛ نه صرفاً بر اساس راحتی کار.
اگر فردا سیستم از کار افتاد چه میشود؟
این سؤال ساده باید از همان زمان طراحی و استقرار نرمافزار مطرح شود:
- اگر سرور از دسترس خارج شد چه میکنیم؟
- اگر بانک اطلاعاتی آسیب دید چه میشود؟
- اگر اطلاعات به اشتباه حذف شد، آیا امکان بازیابی وجود دارد؟
- اگر شبکه دچار مشکل شد، کدام بخشهای سیستم تحت تأثیر قرار میگیرند؟
- آخرین نسخه قابل استفاده از اطلاعات مربوط به چه زمانی است؟
امنیت فقط جلوگیری از حادثه نیست؛ آمادگی برای بازیابی پس از حادثه نیز بخشی از امنیت است.
به همین دلیل، امنیت، پشتیبانگیری و Recovery باید از ابتدای پروژه دیده شوند، نه اینکه بعد از اتمام پروژه به آنها فکر کنیم.
جمعبندی؛ یک نرمافزار موفق از کجا شروع میشود؟
وقتی درباره موفقیت یک پروژه نرمافزاری صحبت میکنیم، معمولاً کیفیت برنامهنویسی، امکانات و فناوریهای استفادهشده مورد توجه قرار میگیرند. اما تجربه سالها فعالیت در طراحی و توسعه نرمافزار به من نشان داده است:
موفقیت یک پروژه خیلی قبلتر از نوشتن اولین خط کد تعیین میشود.
یک نرمافزار موفق نتیجه مجموعهای از تصمیمهای درست است؛ از شناخت مسئله و نیاز واقعی کسبوکار و تحلیل فرآیندها، تا طراحی، توسعه، استقرار و پشتیبانی. حتی پس از تحویل نیز آموزش کاربران، مدیریت تغییرات، امنیت و پشتیبانگیری میتوانند بر موفقیت آن تأثیر بگذارند.
ممکن است یک نرمافزار از نظر فنی بهدرستی کار کند، اما اگر نیاز واقعی مشتری را برطرف نکند یا کاربران نتوانند بهدرستی از آن استفاده کنند، نمیتوان آن را یک پروژه موفق دانست. معیار موفقیت فقط تعداد امکانات یا حجم کدی که نوشته شده نیست؛ مهم این است که نرمافزار بتواند مسئله واقعی کسبوکار را به شکل درست، قابل اعتماد و قابل استفاده حل کند.
در طول سالها فعالیت، دیدهام که بسیاری از مشکلات پروژهها نه از کدنویسی، بلکه از تعریف نادرست نیازمندی، طراحی نامناسب فرآیند، تغییرات بدون بررسی، آموزش ناکافی یا مشکلات زیرساختی ناشی شدهاند. به همین دلیل، موفقیت پروژه فقط به دانش فنی وابسته نیست. مشتری دانش و تجربه کسبوکار خود را دارد و برنامهنویس دانش فنی و تجربه تبدیل این نیازها به نرمافزار را.
شفافیت، مستندسازی و تعهد دوطرفه، پایه اعتماد میان مشتری و مجری پروژه است.
اگر بخواهم تمام تجربههای مطرحشده در این مقاله را در یک جمله خلاصه کنم:
یک نرمافزار موفق فقط با کدنویسی خوب ساخته نمیشود؛ ابتدا باید مسئله درست شناخته شود، نیازها و فرآیندها بهدرستی تحلیل و طراحی شوند و سپس نرمافزار بهگونهای توسعه یابد که قابل استفاده، قابل اعتماد و آماده تغییر و توسعه در آینده باشد.
بنابراین، هنگام شروع یک پروژه نرمافزاری نباید فقط پرسید:
«چه برنامهای میخواهید؟»
باید پرسید:
«چه مشکلی دارید، چگونه کار میکنید و این نرمافزار قرار است دقیقاً چه تغییری در کار شما ایجاد کند؟»
به اعتقاد من، همین سؤال نقطه شروع یک پروژه نرمافزاری موفق است.
تجربههای بیشتر از پروژههای واقعی
آنچه در این مقاله خواندید، بخشی از تجربههایی است که در پروژههای واقعی به دست آوردهام. در مجموعه «تجربههای واقعی»، نمونههای دیگری از چالشها، تصمیمها و اتفاقاتی را که در مسیر طراحی و توسعه نرمافزار با آنها روبهرو شدهام، با جزئیات بیشتری روایت کردهام.
دیدگاه شما
اگر تجربه یا نظری درباره این مقاله دارید، خوشحال میشوم آن را با من و سایر خوانندگان به اشتراک بگذارید.