هنگامی که مهندس نرم افزار برجسته، مارک اندرسون نسبت به خطر بلعیده شدن دنیای ما توسط نرم افزارها هشدار داد، کمتر کسی حرف اورا جدی گرفت. شاید نرم افزارها دنیا را نبلعیده باشند اما روز به روز دنیای ما بیشتر به آنها وابسته میشود. هم زمان پیچیدگی نرم افزارها در حال افزایش است و باگها در هر سیستمی ظاهر میشوند.
برای درک بهتر آنچه که گفته شد، بد نیست اشاره کنیم پروژه آپولو 11 که برای اولین بار در تاریخ انسان را به ماه رساند با نزدیک به 145,000 خط کُد و قدرت پردازشی کمتر از یک چاپ گر امروزی انجام شد. امروزه سیستم عامل ویندوز مایکروسافت از نزدیک به 50 میلیون خط کُد تشکیل شده است. یک هواپیمای بوئینگ 787 به نزدیک به 7 میلیون خط کُد برای پرواز وابسته است اما یک اتومبیل مُدرن امروزی میتواند به 10 الی 100 میلیون خط کُد متکی باشد. تخمین زده میشود زیرساخت خدمات گوگل از نزدیک به 2 میلیارد خط کُد تشکیل شده باشد. در حقیقت هر یک از اینها به یک ارتش از برنامه نویس ها برای تولید و نگه داری نیاز دارند اما روز به روز بر دشواری نوشتن کُدها و تست آنها افزوده میشود.
مطمئناً میلیونها خط کُد اشاره شده یک شبه نوشته نشدهاند و هنگام عرضه یک سیستم یا محصول جدید هم تماماً از نو نوشته نمیشوند. سیستمهای امروزی از لایههای تلنبار شده بر روی هم تشکیل شدهاند که به مروز بر لایههای آن افزوده میشود. غالباً بسیاری از سیستمهای حیاتی امروزی از طریق یک اپلیکیشن پر زرق و برق موبایل قابل کنترل هستند اما ممکن است هسته آنها مبتنی بر کُدهای نوشته شده با قدمت نزدیک به 20 سال باشد.
در حقیقت بسیاری از برنامهها، خدمات و دستگاههای پیرامون ما حاصل سالها کُد نوشته شده هستند و امکان تازه کردن یکباره کدها وجود ندارد. برای نمونه هسته یک سیستم بانکی میتواند 20 سال قدمت داشته باشد اما برای خدمات جدید چون همراه بانک و اینترنت بانک، صرفاً لایههایی به آن اضافه میشود.
تا اینجای کار هیچ مشکلی به چشم نمیخورد اما ظهور رابطهای کاربری و مفاهیم جدید منجر به بروز مشکلاتی در کُدهایی میشود که هرگز برای چنین چیزی طراحی نشدهاند. لایههای جدید، عمیقاً وابسته به لایههای قدیمی پایینتر از خود هستند و احتمالاً دارای API (رابط برنامه نویسی) جدید پیوند خورده با کارکردهای پیشین هستند. به عبارتی دیگر، هسته کُد هیچ تغییری نکرده اما برای کارکردها و رابطهای جدید، لایههای جدید به آن اضافه میشود. مشکل آنجاست که یک باگ یا نقص امنیتی در لایههای زیرین میتواند به بروز باگهای پیشتر مشاهده نشده منجر شود.
پیچیدگی ها به همین جا ختم نمیشود و روز به روز رفع باگ ها و مشکلات کُدها سختتر میشود.
متهم اصلی
برِت ویکتور، پژوهشگر برجسته کامپیوتر، طراح سابق رابط کاربری در اپل و فارغالتحصیل دانشگاه CalTech کالیفرنیا، معتقد است بخشی از پیچیدگی امروزی نرم افزارها ناشی از فاصله گرفتن برنامه نویس ها از هدفی است که برای آن کار میکنند. اغلب کُدهای امروزی از حروف لاتین و نشانهها تشکیل شدهاند. با اینکه کُدهای امروزی به مراتب قابل فهم تر از کُدهای قدیمیتر چون زبانهای اسمبلی و فُرترن هستند، اما هنوز برنامه نویس ها را مجبور میکند تنها بر روی رابطها و خروجی ماژولهای خود تمرکز کنند و نه لزوماً استفادهای که از آنها میشود یا سیستمی که در آن استفاده خواهد شد. در حقیقت اغلب برنامه نویس های امروزی در پروژههای بزرگ چه به صورت انفرادی و چه تیمی، تنها وظیفه تولید و نگه داری ماژول محوله خود را بر عهده دارند و مستقیماً با کل پروژه در ارتباط نیستند.
سال2012 اظهارات آقای ویکتور در خلال یک کنفرانس در دانشکده مهندسی نرم افزار کانادا جنجالی شد. او گفته بود باید برنامه نویس ها قادر باشند تا بهتر آنچه را که میسازند تجسم کنند. در سیستمهای پیچیده که میلیونها خط کُد وجود دارد، الحاق ماژولهای نوشته شده به پروژه اصلی بسیار دشوار است و همانند نوشتن یک اپلیکیشن موبایل نیست که سریعاً برنامه نویس نتیجه کار خود را مشاهده کند. آقای ویکتور در آن زمان گفت معتقد است باید نه تنها ابزارهای برنامه نویسی متحول شوند، بلکه باید برنامه نویس بلافاصله قادر به مشاهده نتیجه کار خود و تأثیر تغییرات بر پروژه باشند.
اگر بخواهیم گفتههای برِت ویکتور را به زبانی سادهتر بیان کنیم، او معتقد است سبک فعلی برنامه نویسی در پروژههای بزرگ ایراد دارد. در پروژههای بزرگ نظیر یک برنامه چون فتوشاپ، هر تیم صرفاً بخشی که به آن واگذار شده است را تولید و نگه داری میکند و مستقیماً با برنامه نهایی در ارتباط نیست. برای نمونه یک تیم صرفاً بر روی رابط کاربری، یک تیم بر روی مدیریت حافظه، یک تیم دیگر بر روی رنگها، تیم دیگری بر روی فیلترها و نظیر آن کار میکند. این تیمها خروجی خود را به صورت جداگانه تحویل میدهند تا توسط تیمهای بالاتر کنار یکدیگر قرار گیرد. ویکتور معتقد است این سبک باعث میشود برنامه نویس درک درستی از کار خود نداشته باشد و صرفاً وظیفه محول شده را انجام دهند.
این پژوهشگر برجسته کامپیوتر، متهم اصلی پیچیدگی نرم افزارها را برنامه نویسی ماژولار میداند.
الگوریتمهای یادگیری ماشین
یادگیری ماشین و هوش مصنوعی میتواند آنچه که "بلعیدن دنیا" خوانده میشود را کامل کند. هم اکنون یادگیری ماشین دارد جایگزین مدل کُد نویسی برای تمامی ورودی و خروجیها در برنامهها میشود. این میتواند سرنوشت ساز باشد، چراکه برنامه نویس ها الگوریتمهای یادگیری طراحی میکنند که در مواجه با مقدار عظیمی از دادهها، خِرد کسب میکند. در کد نویس خطی (معمولی)، برنامه نویس ها تمامی شرایط قابل تصور ممکن و نحوه تعامل با آنها را در کُد برنامه تعریف میکنند. اما در یادگیری ماشین، الگوریتم به مرور و با هر تجربه تازه، به ماشین یاد میدهد چگونه با شرایط مختلف و جدید تعامل کند. این همان چیزی است که به جهش بزرگ در اتومبیلهای بدون راننده انجامیده است. همچنین فیس بوک از این فناوری برای نمایش پستهای متناسب با همان لحظه به شما استفاده میکند.
هرچند یادگیری ماشین هیجان انگیز به نظر میرسد، اما بر پیچیدگی مورد بحث ما، یعنی پیچیدگی نرم افزارها میافزاید. شبکههای عصبی از لایههای متعدد تشکیل شدهاند و توسعه دهندگان الگوریتمهایی طراحی میکنند که خروجی آن را در همه شرایط به درستی نمیدانند. ممکن است یک دستگاه مبتنی بر هوش مصنوعی رفتارهایی از خود نشان دهد که هیچگاه برای طراح آن متصور نبوده است. برنامه نویس ها در برابر این سردرگمی بزرگ تلاش میکنند مصورسازی را به الگوریتمهای مبتنی بر شبکههای عصبی بیفزایند تا درک بهتری از یادگیری ماشین داشته باشند. این کار همانند آن است که از روی الگوهای مغزی انسان در تصمیم گیری، به تفکرات غیر قابل پیش بینی آنها پی برد!
گاهی این الگوریتمها به نتایج پیش بینی نشده میانجامد. برای نمونه نسخه اولیه سرویس تشخیص تصویر گوگل برخی چهرههای آفریقایی- آمریکایی را به عنوان گوریل تشخیص میداد که جدای از بحث نژادپرستی، نشان داد الگوریتم گوگل به تنظیم دقیقتر و البته آزمون و خطای بی شمار (یادگیری) برای کسب خِرد نیاز داشت. در دنیایی که تمایل آن بیشتر به سوی الگوریتمهای یادگیری ماشین است تا کُدهای مشخص و محدود، به مرور کنترل انسانها بر ماشینها و دستگاههای پیرامون ما کمتر خواهد شد. برای فارغ آمدن بر این مشکل نیاز است برنامه نویس ها همچون آموزگارها، درست همانند یک بچه درباره محیطی که در آن کار خواهند کرد و رفتارهای مناسب، به الگوریتمها آموزش بدهند.
چرا دیگر کاری از دست شما بر نمی آید؟
هم زمان که نرم افزارها در حال تسلط بر دنیا هستند، ما به شدت بر چیزهایی متکی میشویم که توسط کُد کنترل میشود. دنیا یاد گرفته کارها را با استفاده از روشهای ماشینی و الکتریکی پیش ببرد. به 30 سال قبل یا بیشتر از آن بازگردیم، در آن زمان تشخیص برخی مشکلات ساده یک اتومبیل برای هرکسی ممکن بود. هنگامی اتومبیل شما وسط راه متوقف میشد، هیچ غیر معمول نبود شمعهای آن را بررسی کنید. اما حالا چطور؟ ممکن است یک اتومبیل صرفاً بر اساس اطلاعات دریافتی از یک حسگر یا اتصالی در سیم کشی خاموش شود و تنها چیزی که به شما نشان میدهد روشن شدن یک نشانگر خطا یا کُد خطا است. اگر گوشی شما هنگ کند، تنها کاری که میتوانید انجام دهید راه اندازی مجدد آن است و هیچ ایدهای ندارید که مشکل از کجاست یا چگونه میتوانید آن را برطرف کنید. با شدت گرفتن روز افزون به روزرسانی های تحت فضای ابری و پنهان کردن جزئیات توسط سازنده، بسیار دشوار است کاربر بتواند مشکلات احتمالی را شناسایی و برطرف کند. امروزه بروز هرگونه نقص در دستگاههای رایج تنها یک راه حل دارد و آن مراجعه به خود سازنده است، دیگر کاری از دست خودتان بر نمیآید.
دستگاههای پیرامون ما روز به روز بیشتر بر کُدها متکی میشوند و نه خود ما. در حالت اول باید کیفیت ارتقا یابد. لزلی لامپورت، دانشمند کامپیوتر که حالا برای بخش پژوهش مایکروسافت کار میکند، معتقد است کُدهایی که برنامه نویس ها مینویسند با سرعت بسیار بیشتر از طراحی و معماری برنامهها در حال پیشرفت است. همچنین او معتقد است امروزه باید برنامه نویس ها درک بهتری از ریاضیات پیشرفته داشته باشند که اساس تئوری های سیستم و الگوریتمها است.
امروزه شاهد سبکی از برنامه نویسی هستیم که میتوان آن را مبتنی بر "انگیزه و پاداش" نامید، در این سبک برنامه نویس ها بدون داشتن درک درستی از معماری کامپیوتر، صرفاً برنامههای هدف خود را طراحی میکنند که اتفاقاً میتواند با بازخورد مثبت نیز همراه باشد. برنامههای آنها درست همان کاری را انجام میدهد که برای آن طراحی شدهاند و کاربر نهایی هم خرسند است. اما از آنجایی که برنامههای آنها اصولی نوشته نشدهاند و شناخت خوبی هم از علوم کامپیوتر ندارند، انواع مشکلات و از همه مهمتر عملکرد ضعیف گریبان گیر اغلب آنها است. نمونه مشهود این دست از برنامه ها را در اکوسیستم اندروید مشاهده میکنید که یک برنامه نسبتاً ساده در وجود منابع سخت افزاری رؤیایی چون پردازندههای 8 هسته ای و 4 گیگابایت حافظه رم، عملکرد بسیار ضعیفی دارد.
بخش قابل توجه ای از این برنامه نویس ها صرفاً از روی علاقه یا حتی با انگیزه کسب درآمد به یادگیری یک زبان برنامه نویسی و تولید برنامه پرداختهاند که به رغم موفق بودن، از علوم کامپیوتر بی بهره ماندهاند، آنها صرفاً چیزی که به آن میاندیشند را پیاده میکنند و درک درستی از چگونگی آن ندارند. ممکن است این برنامه نویس های پر انرژی در کمترین زمان ممکن پیچیدهترین متدهای برنامه نویسی روز را یاد بگیرند اما از آنجایی که با علم مهندسی نرم افزار غریبهاند، مشکلات عدیدهای را پدید میآورند.
اگر قرار باشد دنیای ما تا این اندازه بر نرم افزار متکی باشد، باید به خوبی بدانیم آنها چه کاری انجام میدهند. اگر یک نرم افزار مبتنی بر الگوریتمهای یادگیری ماشین است، باید نسبت به آنچه که یاد میگیرد اطمینان حاصل کرد و بدانیم چگونه به آن یاد دهیم. مهمتر از همه ممکن است ما برای ساخت سیستمهای آینده به ماژولهای بهتری نیاز داشته باشیم.