وقتی یک خط کد میلیاردها دلار هزینه داشت!
وقتی از برنامه نویسی صحبت می کنیم، معمولاً تصویر یک برنامه نویس پشت کامپیوتر، چند خط کد و یک نرم افزار را تصور می کنیم. اما در دنیای واقعی، یک خطای نرم افزاری می تواند بسیار بیشتر از یک برنامه را خراب کند؛ گاهی می تواند یک فضاپیما را از بین ببرد، یک شرکت را با ضرر سنگین مواجه کند یا حتی یک پروژه چندصد میلیون دلاری را شکست دهد. نرم افزار امروز تقریباً در همه چیز حضور دارد؛ از بازارهای مالی و خودروها گرفته تا هواپیما، ماهواره و تجهیزات فضایی. به همین دلیل، یک اشتباه کوچک در کد می تواند پیامدهایی بسیار بزرگ داشته باشد.
در ادامه چند مورد از مشهورترین خطاهای نرم افزاری تاریخ را بررسی می کنیم.
آریانا 5؛ یک خطای نرم افزاری و نابودی موشک
در 4 ژوئن 1996، نخستین پرواز آزمایشی موشک Ariane 5 اروپا تنها حدود 40 ثانیه پس از شروع پرواز با شکست مواجه شد.
موشک از مسیر خود منحرف شد و در نهایت سیستم نابودی خودکار آن فعال شد. بررسی های بعدی نشان داد که ریشه این حادثه به خطاهای طراحی و مشخصات نرم افزار سیستم مرجع اینرسی مربوط بوده است. ESA اعلام کرد که از دست رفتن اطلاعات هدایت و وضعیت، حدود 37 ثانیه پس از روشن شدن موتور اصلی رخ داده بود.
ماجرا فقط یک «باگ ساده» نبود. یکی از مشکلات مهم این بود که بخشی از نرم افزار که از نسل قبلی موشک به Ariane 5 منتقل شده بود، در شرایط پروازی جدید به اندازه کافی بررسی نشده بود. خود ESA بعدها بر ضرورت بررسی مجدد نرم افزار و بهبود فرایندهای آزمون تاکید کرد. نتیجه؟ یک پروژه فضایی بسیار پیچیده، به دلیل مشکلی در نرم افزار هدایت و کنترل، در همان نخستین پرواز آزمایشی شکست خورد.

Mars Climate Orbiter؛ وقتی متر و فوت با هم قاطی شدند
یکی از معروف ترین نمونه های خطای نرم افزاری در تاریخ ناسا، فضاپیمای Mars Climate Orbiter است. این فضاپیما در سال 1998 به سمت مریخ پرتاب شد، اما در سال 1999 در زمان نزدیک شدن به مریخ از دست رفت.
علت چه بود؟
بخشی از نرم افزار زمینی از واحدهای امپریال استفاده می کرد، در حالی که نرم افزار داخل فضاپیما با واحدهای متریک کار می کرد. این ناسازگاری باعث ایجاد خطا در محاسبات مسیر شد و فضاپیما بیش از حد به مریخ نزدیک شد و در جو آن از بین رفت. ناسا این موضوع را به عنوان علت اصلی شکست مأموریت ثبت کرده است.
برآوردهای ناسا در یک گزارش مهندسی، هزینه توسعه و عملیات این مأموریت را در مجموع حدود 327.6 میلیون دلار نشان می دهد. گاهی بزرگ ترین مشکلات نرم افزاری از پیچیده ترین الگوریتم ها به وجود نمی آیند؛ گاهی یک تفاوت ساده در واحد اندازه گیری کافی است.
Knight Capital؛ 45 دقیقه ای که بیش از 460 میلیون دلار هزینه داشت
در اول آگوست 2012، شرکت Knight Capital یکی از معروف ترین حوادث نرم افزاری بازارهای مالی را تجربه کرد. یک مشکل در استقرار کد جدید باعث شد بخشی از سیستم معاملاتی خودکار شرکت رفتار غیرمنتظره ای داشته باشد. در 45 دقیقه نخست بازار، سیستم بیش از 4 میلیون سفارش را در حالی وارد بازار کرد که در تلاش برای تکمیل تنها 212 سفارش مشتری بود.
در نتیجه، شرکت بیش از 397 میلیون سهم معامله کرد و موقعیت های معاملاتی ناخواسته ای به ارزش چندین میلیارد دلار ایجاد شد. SEC اعلام کرد که Knight Capital در نهایت بیش از 460 میلیون دلار زیان متحمل شد. نکته جالب تر این است که پیش از شروع بازار، سیستم داخلی شرکت 97 ایمیل خودکار تولید کرده بود که به مشکل مربوط به سیستم اشاره می کرد؛ اما این هشدارها در آن زمان جدی گرفته نشدند.
پس مشکل فقط «یک خط کد» بود؟ نه دقیقاً.
این داستان ها نشان می دهند که در پروژه های بزرگ، یک حادثه معمولاً حاصل یک عامل واحد نیست. طراحی، تست، استقرار، مستندسازی، کنترل تغییرات، نظارت و حتی تصمیم های مدیریتی می توانند در کنار کد نرم افزار قرار بگیرند و نتیجه نهایی را رقم بزنند. در واقع، چیزی که از این حوادث می توان یاد گرفت این است که کد خوب به تنهایی کافی نیست.
یک نرم افزار مهم باید تست شود، شرایط واقعی آن شبیه سازی شود، تغییرات آن کنترل شود و برای زمانی که چیزی اشتباه پیش می رود، راه برگشت و سیستم های ایمنی وجود داشته باشد.
یک اشتباه کوچک، یک نتیجه بزرگ
برنامه نویس ها معمولاً با خطا و باگ غریبه نیستند. یک برنامه ممکن است به خاطر یک اشتباه کوچک اجرا نشود و با اصلاح همان خط، مشکل حل شود. اما وقتی همان نرم افزار بخشی از یک موشک، مأموریت فضایی یا سیستم معاملاتی باشد، مقیاس خطا کاملاً تغییر می کند.
به همین دلیل است که در پروژه های حساس، تست نرم افزار، بازبینی کد، کنترل نسخه، مانیتورینگ و طراحی سیستم های ایمن، فقط کارهای جانبی نیستند؛ آن ها بخشی از خود مهندسی نرم افزار هستند. شاید یک خط کد به تنهایی ارزش چند میلیارد دلار نداشته باشد، اما سیستمی که آن خط کد در آن قرار گرفته می تواند چنین ارزشی داشته باشد.
Therac-25؛ وقتی خطای نرم افزاری جان انسان ها را به خطر انداخت
دستگاه پرتودرمانی Therac-25 در دهه 1980 در چند حادثه، دوزهای بسیار بالاتر از مقدار موردنیاز به بیماران رساند. بررسی ها مشکلات نرم افزاری و طراحی سیستم ایمنی را از عوامل اصلی دانستند. این نمونه از سه مورد فعلی متفاوت تر است، چون نشان می دهد باگ فقط خسارت مالی ایجاد نمی کند و ممکن است مستقیماً جان انسان ها را تهدید کند.
سامانه پاتریوت؛ خطایی که با گذشت زمان بزرگ تر شد
در سال 1991، یک خطای محاسباتی مرتبط با نمایش زمان در سامانه پاتریوت باعث شد محاسبه موقعیت موشک ورودی به تدریج دقت خود را از دست بدهد. در حادثه ای در ظهران عربستان سعودی، سامانه نتوانست موشک اسکاد را رهگیری کند و 28 سرباز آمریکایی کشته شدند. این اتفاق نمونه مهمی از تأثیر خطاهای عددی و محدودیت های طراحی نرم افزارهای بلادرنگ است.
باگ سال 2000؛ بحرانی که می توانست بسیار بزرگ تر باشد
بسیاری از سیستم های قدیمی برای ذخیره سال فقط دو رقم در نظر گرفته بودند؛ بنابراین احتمال داشت سال 2000 با 1900 اشتباه گرفته شود. این مشکل به تنهایی یک فاجعه جهانی ایجاد نکرد، اما سازمان ها مجبور شدند هزینه و زمان زیادی برای بررسی و اصلاح نرم افزارهایشان صرف کنند. جذابیت این داستان در این است که برخلاف موارد قبلی، بخش مهمی از خطر با پیشگیری و اصلاح پیش از وقوع بحران کنترل شد.
بوئینگ 737 MAX؛ نرم افزار، طراحی و تصمیم های انسانی
در دو سانحه مرگبار این هواپیما در سال های 2018 و 2019، سامانه کنترل پرواز MCAS و اتکای آن به داده های یک حسگر، در کنار مشکلات طراحی، آموزش و فرایندهای نظارتی، نقش مهمی داشتند. این مورد را بهتر است صرفاً «یک باگ نرم افزاری» معرفی نکنیم؛ بلکه نمونه ای از این بدانیم که چگونه تصمیم های مهندسی و مدیریتی می توانند در کنار نرم افزار به فاجعه منجر شوند.
🛠️ چطور از تکرار چنین خطاهایی جلوگیری کنیم؟
البته نمی توان تمام خطاهای نرم افزاری را حذف کرد؛ اما می توان احتمال وقوع آن ها و میزان خسارتشان را کاهش داد.
تست شرایط غیرعادی: فقط بررسی نکنیم که نرم افزار در حالت معمول درست کار می کند؛ ورودی های نامعتبر، داده های بسیار بزرگ، قطع ارتباط و شرایط پیش بینی نشده را هم آزمایش کنیم.
بازبینی کد: بررسی کد توسط یک برنامه نویس دیگر می تواند فرضیات اشتباه و خطاهایی را آشکار کند که نویسنده کد متوجه آن ها نشده است.
انتشار مرحله ای: تغییرات جدید را ابتدا روی محیط آزمایشی یا گروه محدودی از کاربران بررسی کنیم و سپس به تدریج گسترش دهیم.
امکان بازگشت به نسخه قبلی: اگر نسخه جدید مشکل ایجاد کرد، باید بتوان آن را سریع و مطمئن به نسخه سالم قبلی برگرداند.
ثبت و بررسی هشدارها: تولید هشدار کافی نیست؛ باید مشخص باشد چه کسی مسئول بررسی آن است و در صورت بروز مشکل چه اقدامی باید انجام دهد.
طراحی برای شکست: فرض کنیم که بخشی از سیستم بالاخره خراب خواهد شد. سیستم باید بتواند خطا را تشخیص دهد، خسارت را محدود کند و در صورت نیاز به وضعیت امن برود.
نکته مهم این است که کیفیت نرم افزار فقط به درست کار کردن آن در شرایط عادی وابسته نیست؛ بلکه به این هم بستگی دارد که هنگام بروز خطا چه اتفاقی می افتد.

Therac-25؛ وقتی خطای نرم افزاری جان انسان ها را به خطر انداخت
دستگاه پرتودرمانی Therac-25 در دهه 1980 در چند حادثه، دوزهای بسیار بالاتر از مقدار موردنیاز به بیماران رساند. بررسی ها مشکلات نرم افزاری و طراحی سیستم ایمنی را از عوامل اصلی دانستند. این نمونه از سه مورد فعلی متفاوت تر است، چون نشان می دهد باگ فقط خسارت مالی ایجاد نمی کند و ممکن است مستقیماً جان انسان ها را تهدید کند.
تست شرایط غیرعادی: فقط بررسی نکنیم که نرم افزار در حالت معمول درست کار می کند؛ ورودی های نامعتبر، داده های بسیار بزرگ، قطع ارتباط و شرایط پیش بینی نشده را هم آزمایش کنیم.
بازبینی کد: بررسی کد توسط یک برنامه نویس دیگر می تواند فرضیات اشتباه و خطاهایی را آشکار کند که نویسنده کد متوجه آن ها نشده است.
انتشار مرحله ای: تغییرات جدید را ابتدا روی محیط آزمایشی یا گروه محدودی از کاربران بررسی کنیم و سپس به تدریج گسترش دهیم.
امکان بازگشت به نسخه قبلی: اگر نسخه جدید مشکل ایجاد کرد، باید بتوان آن را سریع و مطمئن به نسخه سالم قبلی برگرداند.
ثبت و بررسی هشدارها: تولید هشدار کافی نیست؛ باید مشخص باشد چه کسی مسئول بررسی آن است و در صورت بروز مشکل چه اقدامی باید انجام دهد.
طراحی برای شکست: فرض کنیم که بخشی از سیستم بالاخره خراب خواهد شد. سیستم باید بتواند خطا را تشخیص دهد، خسارت را محدود کند و در صورت نیاز به وضعیت امن برود.

درباره این مطلب دیدگاهی بنویسید...
آدرس پست الکترونیک شما منتشر نخواهد شد.