یادداشت مترجم
کتاب «Coders at Work » نوشته پیتر سیبل در سال 2009 به چاپ رسیده و با وجودی که مدّت زیادی از انتشار آن نمیگذرد مورد استقبال زیادی از سوی طراحان نرمافزار و برنامهنویسان قرار گرفته است. پیتر سیبل، که نام کتابش را از کتابهای معروف و پیشین «Writers at Work » و «Founders at Work » اقتباس کرده، در این کتاب به مصاحبه با پانزده تن از برجستهترین و سرشناسترین برنامهنویسان و دانشمندان رایانه، با پیش زمینه تحصیلی و علاقهمندیهای متفاوت در این حوزه، پرداخته و خواننده را با ایدههای آنها درباره زندگی و برنامهنویسی آشنا ساخته است.
اغلب برنامهنویسان به تنهایی و یا در گروههای کوچک به فعالیت میپردازند و جالبترین بخش فعالیتی که انجام میدهند در مغز آنها اتفاق میافتد که به دور از چشم دیگران است. تنها پنجرهای که به کار برنامهنویسان وجود دارد، رفتار برنامههایی است که توسط آنها نوشته شده و بر روی رایانهها اجرا میشود. بنابراین، اغلب برنامهنویسان تنها خودشان، و احتمالاً چند همکار معدودشان، میدانند که چگونه برنامه نویسی میکنند و چگونه این کار را فرا گرفتهاند. پیتر سیبل به دلیل آن که خود با حرفه برنامهنویسی آشنایی کامل دارد، سعی نموده است تا با طرح پرسشهای جالب و تخصصی، این گوشههای پنهان را برای خواننده آشکار سازد.
ترجمه این کتاب جذاب و خواندنی، به صورت یک سلسله مقاله دنبالهدار، به خوانندگان گرامی گزارش کامپیوتر تقدیم میگردد. امید است این پاورقی جدید نیز همچون پاورقیهای قبلی مجله، مورد استقبال خوانندگان قرار گیرد و در انتها در قالب یک کتاب منتشر و در اختیار علاقهمندان گذاشته شود.
* * *
در بین تمام کسانی که در این کتاب با آنها مصاحبه کردهام، شاید دونالد کنوث کمتر از بقیه نیاز به معرفی داشته باشد. او در چهار دهه گذشته بر روی شاهکار چند جلدیش، کتاب هنر برنامهنویسی رایانه ، کار کرده است. کتابی که میتوان آن را کتاب «مقدس» الگوریتمهای بنیادی و ساختمان دادهها نام نهاد و آمریکن ساینتیست آن را همراه با آثاری از راسل و وایتهد، اینشتین، دیراک، فین من و فون نویمان جزء 12 کتاب علوم فیزیکی قرن قرار داده است. او استفاده از علامت O (رتبه آماری ) را برای تحلیل الگوریتمها متداول ساخت، تجزیه LR را ابداع کرد و از جملات go to در مقابل انتقادهای دایکسترا دفاع کرد.
کنوث تنها یک نظریه پرداز نیست. او پس از خاتمه جلد سوم کتاب هنر برنامهنویسی رایانه در سال 1967، یکسال مرخصی گرفت تا نرمافزار حروف چینی TeX و METAFONT را بنویسد تا بتواند کتابش را آن طور که دلخواهش بود حروف چینی کند. امّا این کار ده سال طول کشید و او در این مدّت علاوه بر آن، سبک جدیدی از برنامهنویسی را به نام «برنامهنویسی ادیبانه » و الگوریتمی را برای شکستن پاراگرافهای متن به خطوط برای حروف چینی ابداع کرد که هنوز نیز جزء پیشرفتهترین الگوریتمهاست.
از جمله جوایز متعددی که کنوث دریافت کرده است میتوان به نخستین جایزه گریس موری هاپر انجمن ماشینهای رایانشی (ACM )، جایزه تورینگ (1974) و نشان ملّی علوم (1979) اشاره کرد. او در سال 1990 استفاده از پست الکترونیکی را متوقف کرد و چنین توضیح داد که کارش این نیست که در رأس همه چیز باشد بلکه میخواهد در پایینترین سطح هر چیز قرار گیرد تا بتواند محدودههای وسیعی از دانش رایانه را به طور عمیق درک کند و در کتابهایش توضیح دهد.
در این مصاحبه با او درباره شور و شوقش برای برنامهنویسی ادیبانه و تأسف او به خاطر تأکید بیش از حدّ بر روی نرمافزارهای قابل باز به کارگیری صحبت کردهایم.
* * *
سیبِل: برنامهنویسی را چه موقع یاد گرفتید؟
کنوث: من دانشجوی سال اول در مرکز فناوری کیس بودم. پائیز 1956 بود و در آن ترم آنها یک رایانه گرفتند.
سیبِل: آیبیام 650 بود؟
کنوث: بله، آیبیام 650 بود. این نخستین رایانهای بود که آیبیام بیش از صد دستگاه از آن را تولید کرده بود. فکر میکنم هزاران دستگاه از آن تولید شد امّا به ده هزار نرسید. به هر حال، نخستین رایانهای بود که به تولید انبوه رسید و کیس هم یکی از آنها را گرفت.
من برای کمک به تأمین هزینههای تحصیلم، علاوه بر بورسی که داشتم، در آزمایشگاه آمار استخدام شده بودم و کارم مرتب کردن کارتها بود. من باید دادهها را برای آماردانان جدولبندی میکردم. این اتاق در طبقه اوّل قرار داشت و پنجرهای داشت که من میتوانستم از پشتش آن ماشین را ببینم. چراغهای زیادی داشت که دائماً روشن و خاموش میشدند و خیلی جلب توجه میکرد.
یک روز بعد از ظهر، یک نفر در آزمایشگاه پای تخته سیاه رفت و به ما سه نفر دانشجوی سال اوّل توضیح داد که این ماشین چکار میکند. من جزوه راهنمای آن ماشین را به دست آوردم و در آن به عنوان مثال چند برنامه 10 خطی نوشته شده بود. به نظر من خیلی احمقانه آمد زیرا روش بهتری برای نوشتن همان برنامههای 10 خطی نیز وجود داشت.
و بعد معلوم شد که میتوان شبها به اتاق رایانه رفت و با آن ماشین کار کرد. این خیلی غیر معمول و نامتداول بود. فکر میکنم کیس و دارتموث تنها دانشگاههایی بودند که اجازه میدادند دانشجویان دوره کارشناسی به ماشین نزدیک شوند. در جاهای دیگر، افراد حرفهای متصدّی ماشین بودند و شما باید بسته کارتهایتان را تحویل میدادید و روز بعد جوابتان را تحویل میگرفتید. امّا در دانشگاه ما فقط به ما میگفتند «مواظب این باشید، نباید آن کار را بکنید، ... چون ماشین خراب میشود.» در نتیجه ما این فرصت را داشتیم که با آن کار کنیم.
بگذریم. من یکبار تغییرات کوچکی در یکی از برنامههایی که در جزوه راهنمای ماشین نوشته شده بود دادم تا ببینم برنامه من هم درست کار میکند یا نه. همین طور هم شد. پیش خود گفتم «خیلی عجیب است. من که هنوز دانشجوی سال اوّل هستم، بهتر از نویسنده این کتاب میتوانم برنامه بنویسم. پس لابد برای این کار استعداد دارم.» البته این نتیجهگیری من درست بود امّا نه به طریقی که من فکر میکردم زیرا تقریباً هر کسی در این دنیا میتوانست برنامهای بهتر از آن برنامهای که در جزوه راهنمای آیبیام 650 نوشته شده بود بنویسد.
آن ماشین یک ماشین دهدهی بود و لازم نبود که من محاسبات دودویی یاد بگیرم، هر چند هنگامی که در دبیرستان بودم، مقدار کمی محاسبات دودویی کار کرده بودم. امّا این واقعیت که دهدهی بود، کار کردن با آن را انسانیتر و راحتتر میساخت. من هنوز زبان آن ماشین را به یاد دارم. 65 معادل reset-add-lower بود. من اکنون از آنها برای انتخاب گذرواژه استفاده میکنم!
سیبل: اوه، اوه. شما برخی از چیزهای مخفیتان را فاش کردید.
کنوث: بله، درست است. بعد من تصمیم گرفتم برنامه کوچکی برای محاسبه عوامل اوّل یک عدد بنویسم. در حدود 100 خط شد. سپس یک شب که هیچکس با ماشین کار نمیکرد به اتاق رایانه رفتم و برنامهام را اجرا کردم. بیش از 100 خطا در آن برنامه 100 خطی پیدا شد. امّا 2 هفته بعد، من برنامهای داشتم که عوامل اوّل هر عدد 10 رقمی را که از طریق سوئیچهای پیشانه وارد میکردید حساب میکرد.
بدین ترتیب بود که من برنامهنویسی را یاد گرفتم- یعنی در واقع، گرفتن یک برنامه که خودم نوشته بودم و نشستن پای ماشین در یک دوره چند هفتهای و آن را بهتر و بهتر کردن.
دومین برنامه من تبدیل بین دودویی و دهدهی بود. امّا سومین برنامهای که نوشتم، برنامه دوزبازی بود و این برنامهای بود که در واقع مرا برنامهنویس کرد.
برای نوشتن این برنامه مجبور بودم از ساختمان دادهها استفاده کنم. من سه گونه دوزبازی نوشتم که یکی از آنها قابلیت خودیادگیری داشت به نحوی که بدون هیچ دانشی درباره بازی شروع میکرد و سپس هر بار که میباخت به یاد میسپرد که حرکتهایش احتمالاً بد بوده و حرکتهای رقیبش خوب بوده است و بدین ترتیب کیفیت بازی خود در یک وضعیت را بهبود میبخشید و این کار را برای وضعیتهای قبل تکرار میکرد و پس از آن که 400 بار با آن بازی میکردید، میتوانست به خوبی دوزبازی را انجام دهد.
سیبِل: به نظر میرسد بسیاری از کسانی که با آنها مصاحبه کردهام، هنگامی که شروع به برنامهنویسی کردهاند دسترسی مستقیم به ماشین داشته اند. با وجود این، دایکسترا در مقالهای که شما هم مطمئناً آن را خواندهاید چنین اظهار داشته که نباید گذاشت دانشجویان دانش رایانه (علوم کامپیوتر) در چند سال اوّل آموزششان به رایانه نزدیک شوند و باید تمام وقتشان را صرف کار کردن با نمادها کنند.
کنوث: امّا خودش هم این طور یاد نگرفته است. او حرفهای عالی و الهام بخش زیادی زده است امّا همه حرفهایش درست نیست. خود من هم همین طور. نظر من در این مورد این است: دانشمندی را در یک رشته علمی در نظر بگیرید. این دانشمند پیر میشود و میگوید «بعضی از کارهایی که من انجام دادهام نتیجه عالی در بر داشته و بقیه چیزها را دیگر به کار نمیگیرم. من نمیگذارم دانشجویانم وقتشان را برای آن چیزها تلف کنند. من در مورد کارهای سطح پایین با آنها صحبت نمیکنم. آنها باید گامهای بزرگ بردارند و اشتباهات مرا تکرار نکنند. این که من چگونه به این نقطه رسیدم را فراموش کنید.»
به نظر من این یک خطای بنیادی توسط دانشمندان در هر رشتهای است. آنها فراموش میکنند که هنگامی که شما یک چیز را یاد میگیرید باید آن را در تمام سطوح ببینید. شما باید پیش از آن که سقف را بسازید، کف را ببینید. همه این اطلاعات وارد مغز میشوند و پائینتر و پائینتر فرستاده میشوند به نحوی که افراد سالمند فراموش میکنند که به آنها نیاز داشتند.
سیبِل: من از تمام کسانی که در این کتاب با آنها مصاحبه کردهام پرسیدهام که کتاب «هنر برنامهنویسی رایانه» را چقدر خواندهاند. اغلب آنها از آن به عنوان یک کتاب مرجع استفاده کردهاند امّا چند نفر هم گفتند که آن را از آغاز تا پایان خواندهاند. آیا به نظر خود شما، هر برنامهنویس باید قادر باشد کتابهای شما را بخواند؟ مطالب ریاضی عمیقی دارد.
کنوث: من خودم هم بعضی وقتها میترسم که نتوانم آنها را بخوانم. من تلاش کردهام دانش و خردی که پیرامون مطالب مورد بحث وجود دارد را سازماندهی کنم و آنها را از جاهای مختلفی که به صورت تکهتکه وجود داشته جمعآوری کردهام و به صورت یکپارچه در آوردهام تا بتواند به پیش رانده شود و خطاها و ابهامات در منابع اصلی را برطرف کردهام.
همانند بخشهایی که هم اکنون سرگرم نوشتن آنها هستم، معمولاً با مطالبی که در مجلات ریاضی نوشته شده آغاز میکنم، مطالبی که انتظار ندارم هیچ برنامهنویسی هرگز آنها را فرا بگیرد و سپس سعی میکنم آنها را از آن زبان نامفهوم خارج سازم تا حداقل خودم بتوانم درکشان کنم. تلاش میکنم ایدههای کلیدی را به دست آورم و تلاش میکنم تا جایی که میتوانم آنها را ساده کنم. امّا اتفاقی که میافتد این است که هر پنج صفحه از کتاب من، برابر میشود با حاصل کلّ کار یک نفر.
به عبارت دیگر، در پشت هر پنج صفحه از کتاب من، مطالب بسیار زیاد دیگری وجود دارد که ارزش یک عمر مطالعه داشته است. علتش این است که دانش رایانه چنین گستردگی و وسعتی دارد. دانش رایانه محدود به یک سری چیزهای ساده نمیشود. اگر دانش رایانه این قدر ساده بود که شما فقط نیاز داشتید 50 چیز را به خوبی یاد بگیرید، در این صورت هر کسی در این دنیا باید آن 50 چیز را فرا میگرفت و آنها را به طور کامل میدانست.
امّا این طور نیست. من هزاران صفحه مطلب و تمرین جمعآوری کردهام و آنها را در کتاب نوشتهام تا مجبور نباشم همه آنها را به خاطر بسپارم. من باید به آنها مراجعه کنم و دوباره یاد بگیرم. و من پاسخ تمرینها را برای خودم نوشتهام زیرا میدانم که ده سال بعد چگونگی حلّ بعضی از آنها را به یاد نخواهم آورد و حل کردن دوباره آنها زمان زیادی خواهد گرفت.
من همیشه به هنگام نوشتن کتاب، دو اظهار نظر متضاد از جلوی چشمانم گذر میکند. یکی این که «این خیلی پیچیده است و بهتر است اصلاً دربارهاش صحبت نکنی» و دیگری این که «این مطلب خیلی بدیهی است و چیز به درد خوری ندارد.» من در هر لحظه با این پرسش روبرو هستم که بهتر است مطلب را همین جا درز بگیرم یا باید کمی فراتر بروم.
من تلاش کردهام در کتابم همه چیزهای سادهای که در نصف صفحه قابل توضیح دادن بودهاند را در همان نصف صفحه بیاورم. چیزهایی که به نظرم میرسیده حیف است به آنها اشارهای نشود. امّا مثلاً بخشی که درباره نمودارهای تصمیمگیری دودویی نوشتهام، بیش از 260 تمرین دارد زیرا چیزهای بیشتر و بیشتری به نظرم رسید که برای خواننده بدیهی نیستند. البته من نمیگویم که همه خوانندگان کتاب مخاطب آن 260 تمرین هستند. امّا میدانم که هر یک از آن تمرینها، برای خود، طرفداران زیادی دارد.
برای خود من هم جالب است که بعضیها از آغاز تا پایان کتابهای من را خوانده باشند. تا جایی که من میدانم اغلب افراد فقط بخشهای مورد علاقهشان را میخوانند. امّا آنها میدانند که اگر عمیقتر به مطالعه کتاب بپردازند، اطلاعاتی را به دست خواهند آورد که چنانچه من این کتابها را ننوشته بودم، یافتن آن اطلاعات برایشان بسیار سختتر بود. همین مرا سر ذوق میآورد.
همچنین، من تلاش میکنم به گونهای قلمروهای تازه را کشف کنم که بیشتر به درد برنامهنویسان عملی بخورد. من دوست ندارم مثل بعضی از افراد دانشگاهی، صرفاً برای بالا بردن وجهه و اعتبار علمی خود، مطلبی را به چاپ برسانم که از لحاظ نظری جالب باشد امّا در یک برنامه واقعی قابل استفاده نباشد.
چیزهایی که من کنار میگذارم و رها میکنم مثلاً این است که یک نفر ساختمان دادهای داشته باشد که چنانچه n بیشتر از 2 به توان یک میلیون شود، با ضریب loglogn صرفهجویی شود. مقالات علمی بسیار زیادی درباره موضوعاتی نظیر این نوشته میشود. امّا من حتی از الگوریتمهایی مثل درخت متوازن یا درخت AVL (درخت متوازن، یک درخت دودویی است که عمق فرزندان هیچ گرهی در آن، یکی با هم بیشتر اختلاف نداشته باشد. درخت AVL یک درخت جستجوی دودویی متوازن است. مترجم) هم در برنامههایم استفاده نمیکنم مگر این که بدانم درخت خیلی بزرگ میشود.
سیبِل: پس از چه چیزی استفاده میکنید؟
کنوث: از درخت جستجوی دودویی معمولی با یک شگرد کوچک در مورد تصادفیسازی آن.
سیبِل: صحبت از کارهای عملی شد، شما در میانه کار نوشتن کتاب هنر برنامهنویسی رایانه، کارتان را متوقف کردید و در فاصلهای که ده سال به درازا کشید، سیستم حروف چینی TeX را نوشتید. تا جایی که من میدانم شما نخستین گونه TeX را بر روی کاغذ و کاملاً به دور از رایانه نوشتهاید.
کنوث: هنگامی که من در سال 1977 و 1978 نسخه اولیه TeX را نوشتم، هنوز برنامهنویسی ادیبانه را در اختیار نداشتم امّا برنامهنویسی ساختیافته در اختیار بود. من آن را با مداد در یک دفترچه یادداشت بزرگ نوشتم.
شش ماه بعد، پس از آن که به طور کامل درگیر آن پروژه شدم، شروع به وارد کردن آن به داخل رایانه کردم. و اشکالزدایی آن را در مارچ 1978 انجام دادم. نوشتن برنامه را در اکتبر 1977 آغاز کرده بودم. کدی که با مداد نوشته بودم اکنون در بایگانی دانشگاه استنفورد قرار دارد. البته هنگامی که آن را وارد رایانه کردم یکی از زیر برنامهها را تغییر دادم.
این نسل اوّل سیستم بود. معماریهای دیگری نیز برای آن میتوانست در نظر گرفته شود امّا من ترجیح دادم آنها را کنار بگذارم و مدتی با همان سیستم اولیه کار کنم تا درک بهتری از آنچه باید باشد به دست آورم. مثل مسئله مرغ و تخممرغ بود. شما تا خانواده حروف نداشتید نمیتوانستید حروف چینی کنید و از سوی دیگر تا حروف چینی نمیکردید نمیتوانستید خانواده حروف داشته باشید.
امّا برنامهنویسی ساختیافته ایده مقادیر ثابت حلقهها را به من داد و دانستم که چگونه میتوانم جعبههای سیاه را در داخل برنامه بسازم به نحوی که بتوانم آنها را درک کنم. به همین جهت، اطمینان داشتم که کدی که به صورت دستی نوشتهام، پس از اشکالزدایی، کار خواهد کرد. من حس کردم که اگر برنامه را به طور کامل بنویسم و منتظر آزمایش کردن آن نشوم، صرفهجویی زمانی خوبی خواهد بود. من به قدر کافی مطمئن بودم که کدی که مینویسم تقریباً درست است.
سیبِل: صرفهجویی زمانی به خاطر این بود که وقت صرف ساختن پودمانهای مجازی برای آزمایش کدهای ناکامل نمیکردید؟
کنوث: درست است.
سیبِل: بجز این واقعیت که کتاب شما اکنون به نحو زیبایی حروف چینی شده است، آیا فکر میکنید اگر 10 سال صرف نوشتن TeX نمیکردید، کتابهایتان خیلی فرق میکردند؟
کنوث: پرسش خوبی است. تجربه به کارگیری برنامهنویسی ساختیافته در یک برنامه بزرگ واقعی- و نه در برنامههای کوچک کلاسهای درس دانشگاهی- احتمالاً تأثیر زیادی بر چگونگی توصیف الگوریتمها در مطالب جدیدی که بعد از آن نوشتهام، داشته است. یا اگر نداشته، باید میداشته است.
هنگامی که من جلدهای اول، دوم و سوم کتابم را مینوشتم، هنوز برنامهای مانند TeX ننوشته بودم. یعنی تجربه برنامهنویسی بزرگ نداشتم. بنابراین، نوشتن TeX ، دید تازهای نسبت به اعداد و کمیتها به من داد.
خیلی جالب است که وقتی دارید کتابی مینویسید، چیزی بر انتخاب واژگانی که به کار میبرید تأثیر بگذارد. این اتفاق در مورد من افتاد. مهمترین تأثیر نوشتن TeX این بود که ذهنیت مرا عوض کرد و در نتیجه، جملات متفاوتی در ذهنم نقش میبست. انگار با لحن مطمئنتری می نوشتم.
سیبِل: آیا فکر میکنید که هنگامی که TeX را به پایان رساندید، نسبت به موقعی که نوشتن آن را آغاز کردید، برنامهنویس خیلی بهتری شده بودید؟
کنوث: خوب، بله. به خاطر برنامهنویسی ادیبانه.
سیبِل: شما ابزارهای بهتری داشتید امّا آیا مهارتتان هم بیشتر شده بود؟
کنوث: من در هنگام نوشتن TeX چیزهای زیادی آموختم. یکی از چیزهایی که یاد گرفتم این بود که چقدر نرمافزار مغز انسان را اشغال میکند. بسیار پیچیدهتر از آن چیزی بود که انتظارش را داشتم. من نمیتوانستم هم به صورت تمام وقت تدریس کنم و هم نرمافزار بنویسم. من میتوانستم به صورت تمام وقت تدریس کنم و همزمان با آن کتاب هم بنویسم امّا نوشتن نرمافزار، نیازمند تمرکز و توجه زیادی به جزئیات بود. تقریباً تمام مغز مرا پر کرده بود. در نتیجه، احترام خاصی نسبت به کسانی که پروژههای بزرگ نرمافزاری انجام میدهند پیدا کردم. تا خودم به طور عملی دست به کار نرمافزارنویسی نشده بودم، هرگز حدس نمیزدم که چه کار دشواری است.
سیبِل: پس برنامهنویسی سختتر از کتابنویسی است. در جایی خواندم که شما گفته بودید برآورد این که نوشتن کتاب چقدر طول میکشد غیر ممکن است. آیا میتوان نتیجه گرفت که تخمین این که نوشتن یک نرمافزار چقدر طول میکشد حتی سختتر است؟
کنوث: بله، درست است. نتیجهگیری خیلی خوبی است.
امسال من سه برنامه بزرگ نوشتهام که هر کدام تقریباً صد صفحه کد داشتهاند. دو تا از آنها به هم وابسته بودند. پس تقریباً میتوانم بگویم 5/2 برنامه بزرگ. و در حدود 150 برنامه کوچک. احتمالاً تعداد برنامههایی که امسال نوشتهام بیشتر از پارسال بوده است. بنابراین، بیشتر برنامههایی که امسال نوشتهام برنامههای کوچک بودهاند امّا بعضی از آنها هم یک ماه یا بیشتر طول کشیدند.
سیبِل: و انتظارش را داشتید که یک ماه طول بکشند؟
کنوث: خوب، من انتظار داشتم یکی از آنها یک ماه طول بکشد. میدانستم که آسان نخواهد بود امّا نمیدانستم چه غنایی پیدا خواهد کرد. در نتیجه، ویژگیهای بیشتری به آن افزودم. من فکر میکنم کسی که مدیریت برنامهنویسان را بر عهده دارد نباید انتظار داشته باشد که کارش قابل پیشبینی باشد.
سیبِل: شما علاوه بر نوشتن کتاب هنر برنامهنویسی رایانه و نرمافزار TeX ، پدید آورنده و طرفدار سرسخت برنامهنویسی ادیبانه هم هستید- شیوهای برای کدنویسی که به آسانی توسط افراد قابل خواندن باشد. و شما WEB و CWEB ، ابزارهایی برای پیادهسازی زبانهای برنامهنویسی ادیبانه بر پایه پاسکال و C را نوشتید.
کنوث: شما گفتید «طرفدار سرسخت». من فقط میگویم این شیوه خوبی برای برنامه نویسی است. من از آن آدمهایی هستم که از نصیحت کردن یا تلاش برای تغییر دادن دیگران خوشم نمیآید. من فکر میکنم برنامهنویسی شبیه اعتقادات مذهبی است. هر کس اعتقادات خودش را دارد. بعضیها دوست دارند که اعتقاداتشان را به دیگران تحمیل کنند. بعضیها هم میگویند این چیزی است که من به آن اعتقاد دارم، نمیتوانم ثابت کنم که بهترین چیز است امّا مطمئناً برای من خیلی خوب است. بعد شما امیدوارید که دیگران نیز آن را امتحان کنند و به نتیجهگیری مشابهی برسند. امّا من دوست ندارم به مردم بگویم که چه اعتقادی باید داشته باشند.
سیبِل: پس شاید بتوانید توضیح دهید که چرا این قدر آن را دوست دارید و چه تفاوتی با برنامهنویسی غیرادیبانه دارد.
کنوث: نخستین قانون نگارش این است که مخاطبان خود را بشناسید. هر چه بهتر خوانندگانتان را بشناسید، بهتر میتوانید بنویسید. قانون دوم، برای نگارش فنّی، این است که هر چیز را دو بار و به دو شکل مکمّل هم بیان کنید تا خواننده بتواند ایدهها را به نحوی که هر کدام دیگری را تقویت کند در مغزش جای دهد.
بنابراین در نگارش فنّی معمولاً افزونگی وجود دارد. مطالب هم به صورت رسمی و هم غیر رسمی گفته میشود. و یا شما تعریفی را ارائه میکنید و بعد میگویید «بنابراین، چنین و چنان» که در این صورت چنانچه تعریف را درک کرده باشید میتوانید آن نتیجهگیری را هم درک کنید.
بنابراین، برنامهنویسی ادیبانه بر پایه این ایده است که بهترین شیوه ارتباطی این است که مطالب را هم به صورت رسمی و هم به صورت غیر رسمی که به هم مربوط باشند، بیان کنیم. و بدین ترتیب یک چهارچوب طبیعی برای تغییر وضعیت بین زبان طبیعی، انگلیسی، و زبان رسمی، C یا لیسپ یا هر زبان برنامهنویسی دیگر، و در کنار هم قرار دادن این دو، فراهم میکند. این از جهت مستندسازی هم بسیار مطلوب است.
و نکته دیگر این که هنگامی که برنامه مینویسم، نباید به شکل مورد انتظار مترجم (کامپایلر) آن را ارائه کنم بلکه آن را به راحتترین شکلی که خواننده درک کند ارائه میکنم.
شما میتوانید کدتان را پایین به بالا بنویسید و زیربرنامههایی بسازید که چیزهای بزرگتر و بزرگتری را در اختیارتان قرار دهند و اطمینانتان افزایش یابد زیرا اکنون کارهای بیشتری میتوانید بکنید. بعضیها هم برنامههایشان را بالا به پایین مینویسند. آنها چنین شروع میکنند «خوب، این مسئله را داریم که باید حل کنیم. پس اوّل این کار را میکنیم و بعداً آن کار را میکنیم.»
هنگامی که من برنامه ادیبانه مینویسم میتوانم آن طور که دلخواهم باشد بین این دو گزینش کنم. و تقریباً همیشه شیوهای که برنامه نهایی من بیرون میآید به همان ترتیبی است که خودم دربارهاش فکر کرده بودم. بنابراین من در آغاز میگویم «مسئلهای است که باید حل کنم، پس ابتدا باید این را حل کنم و سپس باید آن را حل کنم.» بعد میگویم «اکنون بد نیست بعضی ابزارها را پایین به بالا بسازم.» یعنی هدف را در ذهن دارم امّا چند ابزار را به صورت پایین به بالا میسازم و سپس دوباره برمیگردم و مقداری کار به صورت بالا به پایین میکنم. امّا به چه ترتیبی این کار را میکنم؟ نخست درباره کاری که در روز اوّل فکر میکنم باید بر روی این مسئله انجام دهم مینویسم. و سپس، فصل بعد، چیزهایی خواهد بود که تصمیم میگیرم بعداً به سراغشان بروم. من در آغاز به سراغ چیزهایی میروم که بیشتر برایم نگران کننده هستند امّا من آمادگی حل کردنشان را دارم. به جای به تعویق انداختن کارها، اگر آمادگی انجامش را داشته باشم، همان موقع از سر راه بر میدارمشان. امّا این یک ترتیب دیگر است- نه پایین به بالاست و نه بالا به پایین. من کاری را انتخاب میکنم که انجام دادنش از نظر روانی بیشتر از بقیه کارها برایم ارضاء کننده باشد و آمادگی انجام دادنش را داشته باشم. به همین خاطر، آزادی برنامهنویسی به ترتیب قابل فهم برای انسان، اهمیت زیادی برایم دارد.
اکنون این پرسش پیش میآید که چرا این شیوه در سراسر جهان گسترش نیافته و همگان از آن استفاده نمیکنند؟ مطمئن نیستم چه کسی این جمله را بیان کرده است، فکر میکنم از جان بنتلی باشد. حرف او به طور خلاصه این است که «تنها دو درصد از مردمی که به دنیا میآیند برنامهنویس خوبی میشوند و تنها دو درصد از مردمی که به دنیا میآیند نویسنده خوبی میشوند. و کنوث انتظار دارد که همه جزء هر دو دسته باشند.»
من فکر نمیکنم که بخواهیم تعداد کلّ برنامهنویسان در دنیا را به بیش از دو درصد برسانیم- منظورم برنامه نویسان حرفهای است. امّا اکنون که بیشتر مردم به وبنویسی میپردازند، شاهد افزایش چشمگیری در توانایی افراد معمولی به بیان مقصودشان بودهام. بنابراین، دومین بخش آن اظهار نظر دیگر به قوّت سابق نیست.
من دفعات محدودی برنامهنویسی ادیبانه را در استنفورد امتحان کردهام. یکبار با گروهی از دانشجویان دوره کارشناسی کار میکردم که میخواستند پروژه برنامهنویسیشان را در تابستان انجام دهند. من ایده برنامهنویسی ادیبانه را به آنها معرفی کردم. آنها هفت نفر بودند و شش نفر از آنها آنچنان شیفته آن شدند که هنوز هم تا امروز از آن استفاده میکنند. نفر هفتم از آن بدش آمد. او میگفت نوشتن یک برنامه ادیبانه مثل این است که یک برنامه معمولی را بگیریم و لفافی دور آن بپیچیم و بگوئیم «این پودمان اوّل است» و به همین ترتیب. البته استنفورد دانشجویانی را میپذیرد که نویسندگان خوبی هستند. بنابراین، این یک نمونه تصادفی نبود.
سیبِل: آیا تاکنون برنامه ادیبانهای نوشتهاید که برای توضیحش مجبور شده باشید به ترتیب کاملاً متفاوتی آن را تجدید سازماندهی کنید؟ تصوّر این مطلب که ترتیب به ذهن رسیدن موضوعات «همیشه» بهترین ترتیب برای سازماندهی آنهاست، برایم دشوار است.
کنوث: خیلی به ندرت اتفاق افتاده است. من به یاد ندارم که به عقب برگشته باشم و ترتیب فصلها را تغییر داده باشم. همیشه مثل این بوده است که تنها یک گزینه برای این که در مرحله بعد به سراغش بروم وجود داشته است.
سیبِل: آیا هنگامی که بجز خودتان کس دیگری قرار نیست به برنامهای که مینویسید رجوع کند، باز هم از برنامهنویسی ادیبانه استفاده میکنید؟
کنوث: حتماً. برنامهنویسی ادیبانه به همین خاطر خیلی خوب است. من میتوانم چند سال بعد برنامهای را بخوانم و دقیقاً بفهمم که چه فکری کرده بودم.
سیبِل: آیا همیشه مؤثر است؟
کنوث: خوب، معمولاً درک یک برنامه بعد از چند سال دشوار است. امّا باید با حالتی مقایسه کرد که این نوشتهها موجود نبود. چیزهای پیچیده را واضح و بدیهی نمیکند ولی از بقیه روشهایی که میشناسم بهتر است.
یکی از روشهایی که این روزها تولیدکنندگان بستههای نرمافزاری به کار میبرند، پیروی از قراردادهای مربوط به استفاده از جملات توضیحی است. هم در برنامه و هم در ساختمان دادهها. جملاتی که توضیح میدهند چه کاری انجام میشود. این هم سبک دیگری از برنامهنویسی است.
با وجود این، من هنوز فکر میکنم برنامهنویسی ادیبانه دستاوردهای بیشتری دارد. به خاطر بسیاری چیزهای نامحسوس که نمیتوانم برایتان اثبات کنم. بیشترین چیزی که مرا متقاعد میکند این است که برنامههایی نوشتهام که بدون برنامهنویسی ادیبانه هرگز نمیتوانستم آنها را بنویسم. نمونهاش شبیهساز MMIX است. به قدری چالشهای ذهنی داشت که اگر مجبور بودم به شیوه متعارف آن را بنویسم، فکر نمیکنم هرگز میتوانستم آن را به پایان برسانم. تنها این که برنامه را به زیر برنامهها بشکنم، برای ساده کردن مسئله به نحوی که از لحاظ ذهنی قابل مدیریت شود، کافی نبود.
این شبیهساز، مشخصات عمومی یک رایانه از قبیل تعداد واحدهای کارکردی ، تعداد دستورالعملهای قابل اجرا در یک زمان، راهبردهای نهانسازی ، نحوه کارکرد گذرگاه عمومی ، چگونگی کارکرد خروجی و امثال آن را میگیرد و بدون آن که نیاز به ساختن ماشین داشته باشید به شما میگوید که اگر چنین ماشینی موجود بود آیا میتوانستید اعداد اوّل را سریعتر محاسبه کنید؟
من نمیگویم شکستن این برنامه به زیربرنامهها غیر ممکن است امّا من نمیتوانستم به این روش آن را به پایان برسانم. این برنامه 170 صفحه است و به خوبی قابل درک است و من تنها کسی در دنیا نیستم که آن را درک میکند.
سیبِل: من پیادهسازی دوباره شما از بازی ادوِنچر به روش ادیبانه را خواندم و به نظرم تا حدودی یکپارچه آمد. به نظر میآید که در سبک برنامهنویسی ادیبانه، چون به شما اجازه درونیابی چیزها را میدهد، فکرتان را از شکستن برنامه به زیربرنامهها دور میکند.
کنوث: بله، درست است. به جای فراخوانی زیربرنامه، شبیه این است که شما زیربرنامههای خطی (همراستا و پشت سر هم) داشته باشید. ایده زیربرنامه وجود دارد امّا در برنامه نهایی شما به شکل زیربرنامه نیست. بیشتر شبیه یک کلان دستور است. ولی نکتهای که وجود دارد این است که در سطح مفهومی، ساز و کار فراخوانی زیربرنامه، چنانچه شیوه دیگری برای انجام آن در زبان مورد استفاده داشته باشید، ضرورت ندارد.
در ادونچر فکر نمیکنم که زیربرنامهها را از برنامه فرترن دان وود حذف کرده باشم. تنها کاری که کردم این بود که برنامه فرترن او را گرفتم و آن را در قالب زبان C و انگلیسی قرار دادم. امّا این حرف شما درست است که اگر به کد من برای TeX نگاه کنید، تعداد زیربرنامههایی که درون آن میروید 4 یا 5 تا بیشتر نیست حال آن که اگر کس دیگری میخواست آن را به شکل دیگری غیر از برنامهنویسی ادیبانه بنویسد، ممکن بود این تعداد به 50 یا 100 تا میرسید.
چیزی که من تلاش میکنم روی آن کار کنم، واحدهایی هستند که با شیوهای که من در سر دارم مطابقت دارند، نه شیوهای که مثلاً یک منطقدان ممکن است بخواهد در یک سیستم صوری داشته باشد. برنامههای من قرار است با شهود و شمّ من تطابق بیشتری داشته باشند تا با چهارچوب خشک و سفت و سخت یک نفر دیگر.
البته نهایتاً برنامههای من نیز باید وارد رایانه شود که چهارچوب سفت و سخت و قواعد درکی دقیق خاص خود را دارد. امّا برای من، یک برنامه درست، برنامهای است که تا حدّ امکان به شیوه تفکّر من نزدیک باشد، نه برنامهای که تا حدّ امکان مطابقت بیشتر و نزدیکتری با ماشین داشته باشد. من باید راهی برای این تبدیل بیابم امّا کد برنامه من تلاش میکند که به مغز من نزدیکتر بماند تا ماشین.
من همچنین اعتقاد دارم که برنامهنویسی ادیبانه، سبک قدرتمندی برای مستند سازی است و میتواند برای برقراری ارتباط بین گروههای مختلف به کار گرفته شود. من افراد زیادی را میشناسم که کد TeX را به خوبی درک کردهاند. فکر میکنم تعداد افرادی که این برنامه را فهمیده اند بیشتر از هر برنامه دیگری با این اندازه باشد.
سیبِل: آیا هرگز پیش آمده است که با وجود رعایت برنامهنویسی ادیبانه، هنوز عدّهای پرسشهایی را مطرح کنند که شما را به فکر بیندازد که چیزی را از قلم انداختهاید؟ یا آنها نکتهای را درک نکردهاند؟
کنوث: البته. این همیشه پیش میآید و اشتباه در نحوه بیان من بوده است. بگذارید مثال سادهای برایتان بزنم. در کتاب هنر برنامهنویسی رایانه، درباره تاریخچه عملیات بیتگرا صحبت کردهام و این جمله را نوشتهام: «رایانه مارک 1 دانشگاه منچستر تقریباً همزمان با EDSAC ساخته شد و نه تنها شامل AND بیتی بود بلکه ORو XOR (یای انحصاری) نیز داشت. هنگامی که آلن تورینگ نخستین جزوه راهنمای برنامهنویسی را در 1950 نوشت، خاطر نشان ساخت که NOT بیتی میتواند با استفاده از XOR در ترکیب با سطری از یکها به دست آید.»
من در جمله «آلن تورینگ نخستین جزوه راهنمای برنامهنویسی را نوشت»، منظورم نخستین جزوه راهنمای برنامهنویسی برای ماشین مارک 1 منچستر بود. امّا چند نفر از خوانندگان با من تماس گرفتند و گفتند بهتر بود مینوشتم «هنگامی که آلن تورینگ نخستین جزوه راهنمای برنامهنویسیاش را در 1950 نوشت...».
خوب، او جزوات راهنمای دیگری نیز نوشته بود. بنابراین، چیزی که من نوشته بودم درست بود امّا توسط بعضیها سوء تعبیر شده بود. در چاپهای بعد، آن جمله را چنین نوشتم «هنگامی که آلن تورینگ نخستین جزوه راهنمای برنامهنویسی برای مارک 1 را در 1950 نوشت...».
در مورد مطالب ریاضی نیز گاهی پیش آمده است که افراد نکتهای را درست درک نکردهاند. من به خودم میگویم بیان من درست بوده امّا باید تغییرش دهم که بهتر شود.
سیبِل: وقتی شما یک برنامه ادیبانه را تمام میکنید، نوعاً به شکل نهایی است. این جمله معروف از شماست که «بهینهسازی زودرس و شتاب زده، ریشه شیطانی دارد.» امّا زمانی که شکل نهایی برنامه را به دست میآورید دیگر بهینهسازی را نمیتوان زودرس نامید و ممکن است بخواهید بعضی بخشها را بهینهسازی کنید. پرسش من این است که با این کار، خواندن کد شما دشوارتر نمیشود؟
کنوث: نه. یک برنامه ادیبانه خوب، سابقهاش را نشان میدهد. یک برنامه ادیبانه خوب میگوید «این روش بدیهی انجام کار است امّا چرا آن مسیر را دنبال نکنیم؟»
وقتی نکتههای ظریفی در برنامهتان وجود داشته باشد، برنامهنویسی ادیبانه درخشش خاصی پیدا میکند زیرا نه تنها این نکته در کد شما جای دارد بلکه در مستنداتتان نیز هست. شما میگویید «من این شگرد را اینجا به کار بردم زیرا ...» و سپس به دقت دلایل و فرضیاتتان را اظهار میکنید.
من به دو دلیل از شگردها استفاده میکنم. یکی هنگامی که باعث بهبود کارایی شود و برنامه من از آن برنامههایی باشد که بهبود کارایی برایش ارزش زیادی داشته باشد. و یا این که شگرد قشنگی باشد و من نتوانم در مقابل به کار بردنش مقاومت کنم. بعضی روزها آدم از به کار بردن حقههای برنامهنویسی خوشش میآید. به هر حال، من آن را مستند میکنم و نمیگذارم فقط در کد باقی بماند.
سیبِل: این بیشتر در قسمت نثر برنامهنویسی ادیبانه است؟
کنوث: بله در بخش نثر است. من کدهایی که بیرون میآورم را نشان نمیدهم. البته میتوانستم این کار را هم بکنم.
سیبِل: آیا در CWEB امکانی برای گنجاندن کدی که بخشی از برنامه کاربردی نیست وجود دارد؟ مثلاً به جای آن که آن را فقط در بخش نثر مستندسازی کنید بتوانید بگویید «اینگونه پیشین این تابع است.»
کنوث: شما کدی دارید که هیچگاه از آن استفاده نمیکنید. میتوانید در مستندات بگویید که این کد هیچگاه استفاده نمیشود.
سیبِل: پس فقط یک تکه برنامه است که هیچگاه به آن ارجاع داده نمیشود؟
کنوث: بله. من همچنین کدهایی در آنجا دارم که میتوانم از برنامه اشکالزدا آنها را فراخوانی کنم. میتوانم بگویم «این و آن زیربرنامه را با این و آن پارامتر فراخوانی کن.» زیربرنامه هیچگاه در خود برنامه فراخوانی نمیشود امّا در مستندات وجود دارد. بنابراین، من میتوانم یک برنامه را در میانههای اجرایش متوقف کنم و این زیربرنامه را فراخوانی کنم و ببینم چگونه دارد عمل میکند.
سیبِل: پس شما میتوانید بنویسید «بخش اوّل- پیادهسازی ابتدایی و ساده الگوریتم. بخش دوم- گونه کمی بهبود یافته بخش اوّل. و بخش سوم- گونهای که در واقع استفاده میکنیم و شما بدون خواندن دو بخش پیشین آن را درک نخواهید کرد.»
کنوث: دقیقاً. من برنامههایی بر روی وب برای حل مسئله 15 پازل دارم. (مسئله 15 پازل، یک مربع 4×4 است با 16خانه که بر روی 15 خانه آن اعداد 1 تا 15 به طور تصادفی قرار دارند و یک خانه مربع خالی است. حل این مسئله عبارت است از پیدا کردن دنبالهای از جابجاییهای خانههای پر با خانه خالی به نحوی که اعداد یک تا پانزده به صورت سطری یا ستونی پشت سر هم قرار گیرند. مترجم) و هر یک از آنها سه نسخه دارد. و من میگویم «نسخه 1 را بخوان وگرنه نسخه 2 را نخواهی فهمید. و نسخه 2 را بخوان وگرنه نسخه 3 را درک نخواهی کرد.»
من برنامههای گوناگونی مینویسم. گاهی اوقات برنامهای مینویسم که نگران کارآئیش نیستم و فقط میخواهم که جواب را به دست آورم. بنابراین نیازی نیست از خودم هوشمندی نشان دهم و به بهینهسازی بپردازم. اغلب برنامهها در همین مرحله متوقف میشوند زیرا قرار نیست میلیونها بار اجرا شوند. برخی از الگوریتمهایی که من در کتاب هنر برنامهنویسی رایانه نوشتهام نیز از همین نوعند و صرفاً برای چاپ شدن در یک کتاب نوشته شدهاند.
امّا الگوریتمهای ترکیباتی که اکنون بر روی آنها کار میکنم، طبق تعریف، مسائلی با اندازه بسیار بزرگ هستند. بنابراین، برای آن که مثالهای جالبی در کتابم بیاورم، باید برنامههایی برای حل مسائل بنویسم که خوانندگان بگویند «اوه، با روشهای ساده این کار عملی نبود و در نتیجه باید برای انجام دادنش، هنر برنامهنویسی را آموخت وگرنه حل آن با روشهای قدرت مدارانه (روشی برای حل مسئله که در آن به جای نوشتن برنامههای کار آمدتر، به قدرت پردازشی خود کامپیوتر چشم دوخته میشود. مترجم) 100 سال طول میکشد.»
الگوریتمهای ترکیباتی بسیار جالبند زیرا یک ایده خوب میتواند باعث دهها مرتبه صرفهجویی در زمان اجرا شود. هنگامی که قرار باشد برنامهای میلیونها بار اجرا شود، ایدههایی که تنها بیست درصد صرفهجویی در زمان اجرا به بار میآورند نیز قابل اعتنا و احترامند. به طور مثال، اگر شما بتوانید تنها صد نانو ثانیه در حلقهای که یک تریلیون (1012) بار اجرا میشود صرفهجویی کنید، فکر میکنم به اندازه یک روز کامل صرفهجویی خواهد شد. از همه این حرفها میخواهم این نتیجه را بگیرم که اگر کدی به دفعات خیلی زیاد اجرا میشود، به کار بردن حقّهها و شگردهایی که درکشان آسان نیست، مجاز میشود.
تقریباً یکسال پیش، در بخش معرفی کتاب در مجلّه کامپیوتینگ ریویو، کتابی معرفی شده بود به نام «حقّههای برنامهنویسی» یا چیزی شبیه آن. و کسی که کتاب را معرفی کرده بود، در پایان نوشته بود«هرگاه متوجه شوم که یکی از برنامهنویسانی که برای من کار میکند از این حقّهها استفاده میکند، بیدرنگ اخراجش میکنم.» این گفته نظر مرا جلب کرد و باعث شد که کتاب را بخوانم زیرا فکر کردم«این کتابی است که میتوانم چیزهایی از آن یاد بگیرم. متأسفانه شگردهای معرفی شده، شگردهای خوبی نبودند.»
سیبِل: ارزش اخراج کردن نداشتند؟
کنوث: خیلی ضعیف بودند و به نحو سازمان یافتهای ارائه نشده بودند. به عقیده من خیلی بدیهی بودند. کسی که گفته بود افراد را اخراج میکند حتماً خوب بودن یا نبودن برنامه- از لحاظ سرعت و کارایی- برایش مهم نبوده و معیارهای دیگری برایش ارضاء کننده بوده است.
بعضیها ایدههای عجیب و غریبی دارند. میخواهند برنامههایی بنویسند که هر کس بتواند صرفاً با قرار دادن چند پارامتر، هر کاری که میخواهد برنامه برایش انجام دهد. بدین ترتیب، فقط تعداد معدودی برنامه نویس لازم خواهد بود که روالهای کتابخانهای بنویسند، تعداد معدودی که جزوات راهنما برای این روالها بنویسند و بقیه مردم هم فقط کافیست که از آنها استفاده کنند.
مشکل این است که اگر کلّ کاری که میتوانید بکنید فراخوانی روالهای کتابخانهای باشد، در این صورت اگر خودتان نتوانید روالهای کتابخانهای بنویسید دیگر برنامهنویسی لذتبخش و سرگرم کننده نخواهد بود. اگر کار برنامهنویسی فقط یافتن ترکیب درستی از پارامترها باشد دیگر چه کسی تمایل خواهد داشت که این کار را به عنوان شغل و حرفه خود برگزیند؟
تأکید بسیار زیادی که بر روی بازبهکارگیری نرمافزار می شود باعث شده که افراد به سراغ باز کردن جعبه و نگاه کردن به داخل آن نروند. داشتن این جعبه سیاهها خوب است امّا اگر بتوانید به داخل جعبه نگاه کنید، تقریباً همواره خواهید توانست آن را بهبود ببخشید و کارایی آن را بهتر کنید. امّا متأسفانه این لفافها به دور همه چیز پیچیده میشود و آنچه به برنامهنویسان در سراسر جهان ارائه میشود همین جعبههای دربسته است و برنامهنویسان نیز مجاز به گشودن آنها نیستند. تنها کاری که میتوانند بکنند، سر هم کردن این قطعات است. کار برنامهنویسان همین شده است.
سیبِل: بسیاری با شما هم عقیدهاند که اگر خودشان کد بنویسند لذتبخشتر و سرگرم کنندهتر است. امّا مسئله که فقط لذت بردن یا سرگرم شدن برنامهنویس نیست.
کنوث: بحث فقط بر سر لذت بردن و سرگرم شدن نیست. کار یک ریاضیدان، اثبات کردن است امّا تقریباً هیچگاه هنگامی که در حال حل یک مسئله ریاضی هستید، قضیهای را پیدا نمیکنید که فرضیاتش دقیقاً همانهایی باشند که شما برای مسئله خود نیاز دارید. تقریباً همیشه مسئلهای که رویش کار میکنید به نوعی شبیه قضیهای است که در کتاب وجود دارد. بنابراین، کاری که میکنید این است که به اثبات آن قضیه در کتاب نگاه میکنید و میگویید «باید این اثبات را به این شکل تغییر دهم تا بتوانم فرضیهای که اینجا دارم را اثبات کنم.» کتابهای ریاضی مملو از قضیه هستند امّا تنها یک درصد امکان دارد که درست همان قضیهای را که میخواهید در آنها بیابید. من فکر میکنم در مورد نرمافزار هم دقیقاً چنین است.
سیبِل: فکر میکنم این جمله از خود شماست که نرمافزار پیچیدهترین چیزی است که بشر تاکنون خلق کرده است. این طور نیست؟
کنوث: فکر میکنم این جمله را نخستین بار دایکسترا گفته باشد. به هر حال، من هم با آن موافقم زیرا پیچیدگی سر هم کردن چیزهای مختلف، بسیار نایکنواخت است. ریاضیات محض به دنبال این است که چند قانون داشته باشد که به طور عام و همه جا قابل به کار بستن باشند- سه یا چهار اصل موضوع برای توصیف یک سیستم. برنامههای رایانهای بخشهای متعددی دارند- گام اول متفاوت از گام دوم و گام دوم متفاوت از گام سوم است. برنامه همه این چیزها را کنار هم میآورد و آنها باید به صورت درهم بافته و ظریفی جفت و جور شوند.
سیبِل: بنابراین با توجه به این پیچیدگی، به نظر میرسد بعضی وقتها باید برنامهنویس این جعبه سیاهها را بگیرد و بگوید «خوب، ما میدانیم این چگونه کار میکند، پس میتوانیم از آن استفاده کنیم.» اگر مجبور بودیم که به داخل هر جعبه سیاهی نگاه کنیم، کار هیچوقت به پایان نمیرسید.
کنوث: حرف من این نیست که جعبه سیاهها بیفایده و بهدرد نخور هستند. من میگویم که اگر اجازه نداشته باشم که آنها را باز کنم، و اگر مجبور باشم که همه کارها را از طریق فراخوانی روالهای کتابخانهای انجام دهم، به نتایج بسیار بسیار بدتر و کندتری دست خواهم یافت.
سیبِل: کندتر از نظر اجرا یا از نظر زمان تولید؟
کنوث: هر دو. ممکن است به نظر برسد که تولید برنامه سریعتر میشود امّا در واقع باید زمان بیشتری را صرف جستجوی جزوات راهنما و یافتن قطعات مناسب بکنم. بیشتر یک مسئله جستجوست تا مسئله خلاقانه و مبتکرانه.
سیبِل: چندی پیش، کسی که مجموعه روالهای کتابخانهای استاندارد جاوا را نوشته است، در مقالهای از خطایی که به مدّت 9 سال در پیادهسازی آنها برای جستجوی دودویی وجود داشته پرده برداشت. آنها کمترین مقدار و بیشترین مقدار را میگرفتند، با هم جمع میکردند و تقسیم بر دو میکردند. امّا چنانچه جمع کردن آن دو عدد باعث سر ریز میشد، خطا پیش میآمد. البته این که کتابخانه استاندارد دارای خطا باشد خیلی بد است و آنها نیز سرانجام خطا را یافتند و اصلاح کردند، امّا اگر هر کس خودش جستجوی دودویی را مینوشت، درصد برنامههایی که خطا داشتند احتمالاً بسیار بیشتر میبود.
کنوث: درست است. و این فقط یکی از صدها یا شاید هزاران مورد است. جستجوی دودویی یکی از مثالهای خاصی بود که ما در دهه 1970 کلاسهای برنامهنویسیمان را با آن شروع میکردیم. در روز اول کلاس، هر کس برنامهای برای جستجوی دودویی مینوشت و ما برنامههای آنها را جمع میکردیم و دستیارم آنها را تصحیح میکرد. و معمولاً کمتر از ده درصد آنها کاملاً درست بودند. چهار یا شش نوع خطای مختلف وجود داشت. و البته خطای سر ریز که شما اشاره کردید جزء آنها نبود. در کلاسهای من اتفاق نیفتاد که ما فکر کنیم جمع کردن دو عدد میتواند مشکلساز باشد.
امّا من چرا این قدر از ایده نرمافزار به عنوان جعبه سیاه نفرت دارم؟ بگذارید یک مثال برایتان بزنم. فرض کنید برنامهای دارید برای ضرب دو ماتریس. یک جعبه سیاه برای ضرب کردن دو ماتریس. و بعد شما نوع داده را از حقیقی به مختلط تغییر میدهید و در نتیجه، یک جعبه سیاه برای ضرب دو ماتریس مختلط به دست میآورید که این عمل را در 3n ×4 مرحله، به جای 3n مرحله، انجام میدهد. اگر ضرب دو ماتریس متشکل از اعداد حقیقی، زمانی معادل t بگیرد، ضرب دو ماتریس از اعداد مختلط، زمانی معادل t 4 میگیرد. امّا اگر شما مجاز به گشودن این جعبه باشید، فقط به سه عمل ضرب ماتریس حقیقی به جای 4 تا نیاز خواهید داشت زیرا یک اتحاد ریاضی وجود دارد که حاصل ضرب دو ماتریس مختلط را توصیف میکند. این یک مثال ساده بود. شبیه این بسیار است.
سیبِل: چقدر شیوه تفکّر شما درباره برنامهنویسی نسبت به روزهای اوّل تغییر کرده است؟
کنوث: ما پیش از این درباره برنامهنویسی ادیبانه با هم صحبت کردیم. این یک تغییر نگرش عمده برای من بود. من اکنون خودم را یک «شرح دهنده» میدانم تا فردی که فقط تلاش میکند تا دستورالعملهای صحیح را کنار هم بگذارد. دایکسترا هم به چنین تکاملی رسید. برنامههای او در این اواخر حتی از برنامههای من نیز ادیبانهتر بود، از این نظر که حتی وارد ماشین هم نمیشدند.
و او یکی از کسانی بود که مسئولیت عمدهای در برنامهنویسی ساختیافته داشت. در آن روش، الگوهایی دیدیم که توانستیم از آنها برای بزرگتر کردن برنامهها استفاده کنیم. شما برنامهای مینویسید که ده برابر بزرگتر است امّا نباید برای نوشتن آن، ده برابر بیشتر بیخوابی بکشید زیرا ابزارهایی در اختیار دارید که به شما اجازه میدهند چیزها را در یک سیستم بزرگتر با اطمینان کنار هم قرار دهید. و این یک رویکرد کاملاً متفاوت بود.
بنابراین، ایده مجرّدسازی یکی از جنبههای مهم است. مجرّدسازی به ما اجازه میدهد که به سیستمهای بزرگ بپردازیم و مطمئن باشیم که همه چیز را زیر کنترل داریم و میدانیم که داریم چکار میکنیم، حتی اگر آن سیستمها بسیار پیچیده باشند.
چیزهای زیاد دیگری هم هستند که تغییرات مهمی به نظر میرسند امّا به عقیده من تفاوتهای زیادی به وجود نیاوردهاند. اینها بیشتر تغییرات روبنایی هستند، مثل انواع مختلف قواعد نحوی زبانها که مناسب ذوق و سلیقه افراد مختلف میباشند. مثلاً بعضی افراد نسبت به من آدمهای منطقیتری هستند. آنها دوست دارند که پرانتزهای زیادی در اختیار داشته باشند و چیزها را با هم انطباق دهند و بگویند «حالا میخواهم یک چیز را آغاز کنم» و در خاتمه بگویند «حالا میخواهم تمامش کنم.» و این برای من جذابیتی ندارد. من این گونه فکر نمیکنم. امّا خیلیها این گونه فکر میکنند و هیچ طرز تفکّری را نمیتوان بهترین نامید.
از نظر من یکی از مهمترین انقلابها در زبانهای برنامهنویسی، استفاده از اشارهگرها در زبان C بود. هنگامی که ساختمان دادههای غیر واضحی داشته باشید، غالباً نیاز دارید که یک بخش از ساختمان داده به بخش دیگر اشاره کند و پیش از مطرح شدن اشارهگرها، افراد به شیوههای متفاوتی این کار را در زبانهای سطح بالا انجام میدادند. برای مثال، تونی هور سیستم قشنگ و پاکیزهای داشت امّا چیزی که زبان C اضافه کرد- که من در ابتدا فکر میکردم اشتباه بزرگی است ولی بعد عاشقش شدم- این بود که اگر x یک اشارهگر باشد و شما بگوئید 1+x ، این به معنی یک بایت بعد از x نیست بلکه یعنی یک گره بعد از x ، بر حسب این که x به چه چیزی اشاره میکند: اگر یک گره بزرگ باشد، 1+x مقدار زیادی حرکت میکند و چنانچه x به چیز کوچکی اشاره کند، 1+x فقط کمی به جلو منتقل میشود. این برای من یکی از جالبترین پیشرفتها در علامتگذاری است.
سیبِل: این البته در مقایسه با امکانات قبلی ابزار قوی و قدرتمندی است. امّا از آن زمان تاکنون، بسیاری از افراد به این نتیجه رسیدهاند که داشتن اشارهگرهای خام به حافظه، بسیار خطرناک است و به جای آنها از ارجاعاتی استفاده میکنند که شبیه اشارهگرها عمل میکنند امّا بعضی خطرات آنها را ندارند.
کنوث: اشارهگرها اکنون دیگر جذابیتی ندارند. مثلاً در همین رایانه 64 بیتی که من دارم، اگر بخواهم از قابلیتها و امکانات ماشین استفاده کنم، بهتر است به سراغ اشارهگرها نروم زیرا ماشینی دارم که ثبّاتهای 64 بیتی دارد امّا حافظهاش فقط 2 گیگا بایت است. بنابراین، یک اشارهگر نمیتواند بیش از 32 بیت با معنی داشته باشد. ولی هر زمان که از اشارهگر استفاده کنم، 64 بیت برایم هزینه دارد و اندازه ساختمان دادههایم را دو برابر میکند. از آن بدتر، وارد حافظه نهان میشود و نیمی از آن را اتلاف میکند. حافظه نهان گران قیمت است.
در نتیجه، من باید به جای اشارهگرها از آرایهها استفاده کنم. من کلاندستورهای پیچیدهای نوشتهام که به نظر میرسد دارم از اشارهگرها استفاده میکنم امّا در واقع، چنین نیست. با وجودی که هم اکنون اشارهگرها از مد افتادهاند امّا به نظر من ایده مهمی در علامتگذاری در سطوح پایینتر بودند. هنگامی که برنامهنویسی و اشکالزدایی میکنم، هنوز خیلی سپاسگزار تامپسون و ریچی (به وجود آورندگان زبان C . مترجم) هستم. من نمیدانم این ایده برای نخستین بار به ذهن کدامیک از آنها رسیده بود.
سیبِل: آیا در ابزارگان برنامهنویسی شما چیزهای مهم دیگری هم وجود دارد؟
کنوث: پرونده تغییرات چیزی است که من با برنامهنویسی ادیبانه به دست آوردهام و ابزاری مشابه آن را در ابزارگان هیچ برنامهنویس دیگری نمیشناسم. پس اجازه دهید کمی درباره آن توضیح دهم.
من TeX و متافونت را نوشته بودم و خیلیها شروع به سؤال کردن درباره آن میکردند. و آنها 200 یا 300 ترکیب مختلف از زبانهای برنامهنویسی و سیستمعامل و رایانه داشتند. بنابراین، من میخواستم وفق دادن کدم با سیستمهای مختلف آنها را آسان سازم. در نتیجه، به این راه حل رسیدم که یک برنامه اصلی نوشتم که در استنفورد کار میکرد و بعد این افزایه به نام «پرونده تغییرات» که میتوانست برنامه اصلی را برای ماشین هر کس دیگر مناسبسازی کند.
پرونده تغییرات چیز بسیار سادهای است. شامل تعدادی تغییرات کوچک میباشد. هر تغییر با چند خط کد آغاز میشود. شما پرونده تغییرات را با پرونده اصلی انطباق میدهید تا به نخستین خطی در پرونده اصلی که با نخستین خط تغییرتان انطباق دارد برسید. هنگامی که به انتهای بخش تغییر رسیدید که قرار بود با پرونده اصلی انطباق داشته باشد، بخشی میآید که میگوید «آن را با این خطوط جایگزین کن.» شما باید تغییرات را به ترتیب بنویسید. کار هوشمندانهای برای انطباق نمیکند. فقط جلو میرود تا نخستین خط تغییر بعدی را که باید با یک خط در پرونده اصلی انطباق داشته باشد پیدا کند.
برنامهنویسی این سیستم یک ساعت بیشتر زمان نبرد و برای منظور ما کفایت میکرد. از آن پس، تمام ابزارهایی که برای برنامهنویسی ادیبانه داشتیم، پرونده اصلی و پرونده تغییرات را دریافت خواهند کرد.
بنابراین، هر از گاهی من باید یک برنامه اصلی جدید عرضه کنم. تمام افرادی که در سراسر جهان از برنامهنویسی ادیبانه استفاده میکنند، پروندههای تغییرات خود را دارند. شاید دیگر انطباق قبلی آنها از بین رفته باشد. بنابراین آنها نیز باید تغییرات کوچکی به عمل آورند. البته این کار زیاد اتفاق نمیافتد. هر گاه که من خطایی را اصلاح میکنم، بلافاصله و به طور خودکار عمل میکند و این اصلاحیه بر روی برنامههای آنان نیز اعمال میشود. بدین ترتیب مشکل حل شد و همه توانستند آن را درک کنند.
اکنون من به طور مرتب از پرونده تغییرات استفاده میکنم زیرا برنامههای زیادی برای خودم مینویسم تا در کتابی که در دست نوشتن دارم از آنها استفاده کنم. مسائل زیادی هست که میخواهم حل کنم و میخواهم گونههای مختلف آن را آزمایش کنم. مثلاً همین دیروز، میخواستم ببینم یک مدار بولی برای ضرب اعداد n بیتی چقدر بزرگ است. من برنامهای دارم که هر تابع بولی را میگیرد و میزان بزرگی BDD (نمودار تصمیمگیری بولی) آن را محاسبه میکند.
در برنامه اولیه من، شما جدول درستی تابع را به صورت برخط وارد میکنید. برنامه میگوید «جدول درستی را به من بده» و من اعداد را در مبنای شانزده وارد میکنم زیرا توابع کوچک بسیاری داشتم که به عنوان مثال از آنها استفاده میکنم. امّا این فقط برای توابع کوچک کار میکند، توابعی که میخواهم وارد جدول درستی کنم.
سپس تابع بزرگی در اختیار گرفتهام مثل «تمام جفت اعداد 8 بیتی را ضرب کن.» این یک تابع 16 متغیره است- 8 بیت در x و 8 بیت در y . بنابراین، یک پرونده تغییرات کوچک نوشتم که این گفتگوی تعاملی را با برنامهای که یک جدول درستی برای ضرب درست میکند، جایگزین میسازد.
سپس آن را بدین ترتیب تغییر دادم که «بیتها را به جای چپ به راست، از راست به چپ بخوان،که به شما BDD متفاوتی میدهد.» یا «تمام توابع بولی با 6 متغیر را امتحان کن و ببین کدام یک دارای بزرگترین BDD است.» همه اینها نوعی سفارشیسازی است.
من در حدود 15 گونه مختلف آن برنامه را خواهم داشت که همگی به سادگی قابل درکند. این یک محصول جانبی غیر منتظره از برنامهنویسی ادیبانه بود زیرا باید پروندههای اصلی را برای تعداد زیادی که آنها را برای سیستمهای خود تغییر داده بودند، میفرستادیم. من اکنون به گونه کاملاً متفاوتی از آن استفاده میکنم.
سیبِل: در نوع کاری که شما دارید میکنید، مفید بودن این ابزار بدیهی به نظر میرسد زیرا شما میخواهید تغییرات زیادی را بر روی زمینههای متفاوت انجام دهید.
کنوث: بله، در حال نوشتن کتاب هستم.
سیبِل: آیا فکر میکنید این ساز و کار در سطح گستردهتری هم قابل به کارگیری است؟
کنوث: دقیقاً نمیدانم. مطمئن نیستم اگر در یک تیم 50 نفره بودم، این چطور کار میکرد. امّا امیدوارم این ایده که یک برنامهنویس منفرد، برنامههایی مینویسد تا چیزی یاد بگیرد، منسوخ نشده باشد.
سیبِل: شما در روزگار اولیه به زبان ماشین برنامه مینوشتید. سپس به برنامهنویسی ساختیافته روی آوردید که ساختاری برای سازماندهی برنامهها فراهم میکرد. و بعد از آن برنامهنویسی ادیبانه را ابداع کردید که شیوه دیگری را برای ساختدهی برنامهها در اختیارتان قرار داد. پس از ابداع برنامهنویسی ادیبانه، آیا چیز دیگری بوده است که به نحو چشمگیری طرز تفکّر شما درباره برنامهنویسی را تغییر داده باشد؟
کنوث: ابزارهای اشکالزدایی بهتری برای برنامهنویسی ادیبانه به دست آوردهام. فقط همین.
سیبِل: خیلی خوب، اجازه دهید درباره اشکال زدایی صحبت کنیم. اکنون چه ابزارهای بهتری در اختیار دارید؟
کنوث: یکی از امکانات خوبی که اشکالزدایی سیستمعامل GDB در اختیار میگذارد این است که شما میتوانید چیزهای سطح پایین را به کد مبدأ سطح بالا در یک زبان کاملاً متفاوت مربوط کنید. بنابراین من در CWEB برنامهنویسی میکنم امّا هیچ نیازی به نگاه کردن به چیزهای سطح پایین ندارم زیرا در همان کد مبدأ CWEB خودش را نشان میدهد.
سیبِل: یعنی این امکانی است که در GDB وجود دارد و CWEB از آن استفاده میکند؟
کنوث: این امکانی است که در GDB قرار داده شده زیرا در C گذاشته شده تا _LINE_ directives داشته باشد. ( _LINE_ directive به پیش پردازنده میگوید که شماره خط و نام پرونده ذخیره شده درونی برنامه مترجم را به یک شماره خط و نام پرونده مفروض تغییر دهد. برنامه مترجم از شماره خط و نام پرونده برای مراجعه به خطاهایی که در خلال ترجمه پیدا میکند، استفاده میکند. شماره خط معمولاً به خط ورودی جاری و نام پرونده به پرونده ورودی جاری اشاره میکند. شماره خط پس از پردازش هر خط افزایش مییابد. مترجم) استفاده از _LINE_directive آسان نیست و کمی کار میبرد امّا خیلی قشنگ عمل میکند. رایانه یک دستورالعمل دودویی در اختیار دارد امّا GDB میداند که این از جایی در پرونده مبدأ WEB من آمده، حتی با وجودی که WEB ده بیست سال پس از C به وجود آمده است. بنابراین، آیندهنگری خیلی خوبی در طراحی آنها وجود داشته که این چنین کار میکند.
سیبِل: پس شما از GDB استفاده میکنید. دیگر از چه روشهایی برای اشکالزدایی استفاده میکنید؟
کنوث: من مقدار زیادی کد برای بررسی این که ساختمان دادههایم به درستی عمل میکنند یا نه، اضافه میکنم. اگر این بررسی خوشفکری را فعّال کنم میتواند همه چیز را تا 100 برابر کندتر کند. (بررسی خوشفکری یا آزمون خوشفکری یک نوع آزمون ابتدایی برای ارزیابی سریع درستی یک ادّعا یا نتیجه یک محاسبه است. یک نوع بررسی ساده برای مشاهده این که آیا محصول تولید شده، معقول است یا نه. نکتهای که در آزمون خوشفکری وجود دارد، جلوگیری از ردههای خاصی از نتایج واضحاً اشتباه است. مزیت آزمون خوشفکری بر یک آزمون کامل یا دقیق، سرعت آن است. مترجم).
برای مثال، من ساختمان دادههای پیچیدهای داشتم که شامل شمارش ارجاعات بود. من در حال نوشتن برنامههای بسیار پیچیدهای بودم و به دست آوردن مقدار صحیح این شمارش ارجاعات گیج کننده بود. هر از گاهی مجبور میشدم یکی به شمارنده اضافه کنم یا کم کنم. هنگامی که یک اشارهگر در یک ثبات قرار دارد یا پارامتر یک زیربرنامه است آیا به عنوان یک ارجاع در ساختمان دادهها شمرده میشود یا خیر؟ به این خاطر من یک آزمون خوشفکری نوشتم که به درون میلیونها شمارش میرفت تا ببیند واقعاً چند ارجاع به عمل آمده و آیا عددها صحیح هستند؟ بعد من مقداری محاسبه کردم تا همه چیز را بررسی کنم. به این ترتیب، خطاها خیلی پیش از آن که باعث خرابی و فروپاشی سیستم شوند، کشف میگردند.
برنامهای بود که عمل ضرب را به شیوه تازهای انجام میداد. من آن را به طور جامع مورد آزمایش قرار دادم. 256 عدد را در نظر گرفتم و هر یک را در بقیه آنها ضرب میکردم و پس از هر عمل ضرب، یک آزمون خوشفکری انجام میدادم. 2 را در 3 ضرب کردم و جواب اشتباه داد! پس آن را اصلاح کردم. و بعد یکی دیگر. و همین طور تا سرانجام به جایی رسیدم که تمام آن 256 در 256 عمل ضرب درست کار میکرد و پاسخ درست میداد.
این یک روش مهم اشکالزدایی برای من است. در حدود 10 درصد کدهای من مربوط به چیزی است که به آن نیازی ندارم مگر بخواهم اشکالزدایی کنم. و کد مربوط به آزمون خوشفکری، ساختمان دادهها را مستندسازی نیز میکند.
من همچنین برنامهای مینویسم که شکل نمادین قشنگی از ساختمان دادهها را به دست میدهد و بنابراین نیازی به رمزگشایی از همه چیزهای دودویی نخواهم داشت. سپس، اگر لازم باشد، میتوانم یک ساختمان داده را به شکل ساختیافته و آراستهای چاپ کنم و یا آن را در یک پرونده بریزم و سپس برنامه دیگری بنویسم که آن را تحلیل کند و پیدا کند چه اشتباهی روی داده است.
سیبِل: در رابطه با مقادیر ثابت و انواع حکمهای تأکیدی ، افرادی مانند دایکسترا معتقدند که ما باید در هر بخش از برنامه، حکمهای صوری قرار دهیم به نحوی که بتوانیم درستی برنامه را اثبات کنیم. من در جایی خواندم که شما درباره اثبات «غیرصوری» درستی برنامهها صحبت کرده بودید. نظرتان درباره این که باید یک گام از آن فراتر رفت و به اثبات صوری درستی برنامهها پرداخت چیست؟
کنوث: به نظر من اثبات درستی یک برنامه غیرممکن است. یک نفر ممکن است بگوید که برنامهای دارد که درستی آن اثبات شده است. معنی این حرف این است که به نظر یک نفر بررسی کننده، این برنامه با مشخصاتش مطابقت میکند. امّا هم ممکن است مشخصات دارای خطا بوده و هم ممکن است آن فرد بررسی کننده خطا کرده باشد. بنابراین شما هیچگاه نمیدانید که یک برنامه درست است یا نه. البته شما دلایل بیشتری برای این که باور کنید درست است به دست میآورید امّا هرگز به اطمینان صد در صد دست نمییابید. از لحاظ نظری غیر ممکن است.
من در برنامههایی که مینویسم نمیدانم چگونه همه حکمهای تأکیدی را بیان کنم. اطمینان من در مورد حکم تأکیدی بیشتر از اطمینانی که به برنامهام دارم نیست.
یا مثلاً در مورد TeX که برای استفاده انسانها نوشته شده نه برای استفاده رایانهها، تعریف دقیق این که درستی آن چه معنی میدهد، غیر قابل درک است. برخی از روشهای معناشناسی صوری آن قدر پیچیده هستند که هیچکس نمیتواند تعریف صحّت یا درستی را درک کند.
سیبِل: هنگامی که شما بر روی TeX کار میکردید، آزمونهای فوقالعاده زیاد و حتی میتوان گفت عذابآوری برای برنامه نوشتید.
کنوث: درست است.
سیبِل: چطور به ذهنتان رسید که این کار را بکنید؟ برنامهنویسان غالباً تمایل دارند که بچهشان را محافظت کنند و بدین خاطر، آن را به طور جدّی و سخت مورد آزمایش قرار نمیدهند.
کنوث: خوب، من در تمام عمرم آدم ایرادگیری بودهام. در مورد آزمایش برنامههایی که مینویسم، سعی میکنم فراموش کنم که خودم نویسنده برنامه بودهام و سعی میکنم تصوّر کنم که نویسنده آن فرد دیگری بوده است. در این صورت، به سادگی در حالت حملهای قرار میگیرم. نمیدانم چرا.
برای مثال، یکی از بهترین کارهایی که برای شرکت باروز کردم، اشکالزدایی از طراحیهای سختافزاری آنها بود. مهندسان آنها مشخصات رایانههایشان را به من نشان میدادند و من به آنها نگاه میکردم و سعی میکردم مثالهایی برای نشان دادن خطاهایشان پیدا کنم. من بیش از 200 خطا در ماشینهای سری B5000 آنها پیش از آن که به خط تولید سپرده شود پیدا کردم و جالب اینجاست که طراحیهای آنها مرحله آزمایش با شبیهسازها را نیز با موفقیت گذرانده بود.
سیبِل: یعنی شما برنامههایی طراحی میکردید که از نظر معناشناسی زبان درست بودند امّا هنگامی که بر روی ماشین اجرا میشدند پاسخ نادرست میدادند؟
کنوث: درست است. مثلاً اگر مدار ممیز شناور آنها حاصلضرب دو عدد را درست محاسبه نمیکرد، من سعی میکردم مثالهایی از دو عدد با ممیز شناور پیدا کنم که این خطای آنها را نشان دهد. در بقیه موارد نیز همین طور. من سناریوهایی پیدا میکردم که نشانگر اشتباهات طراحی و پیادهسازی آنها باشند.
سیبِل: آیا شما روش سیستماتیکی برای انجام این کار دارید؟ مثالهای نقض را چگونه پیدا میکنید؟
کنوث: آیا من آدم خبیثی هستم؟ نمیدانم. من هنگامی که میخواهم چیزی را اثبات کنم، مثلاً یک قضیه ریاضی، به جای آن که درستیش را اثبات کنم، معمولاً برایم آسانتر است که بگویم «خوب، یک مثال نقض پیدا کن.» اگر بتوانم خطایی در آن پیدا کنم یا بتوانم توضیح دهم که چرا درست کار نمیکند، از نظر روانی بسیار ارضاء میشوم. امّا اگر نتوانستم، آنگاه به سراغ اثباتش میروم.
من فکر میکنم این جزئی از شخصیت من است که روحیه تهاجمی دارم و دوست دارم خطاها را بیابم. همیشه دوست دارم به جای آن که بگویم «چرا این چیز درست کار میکند؟» سعی کنم نشان دهم که چرا درست کار نمیکند.
سیبِل: جالب است که این شیوه شما را در زندگی حرفهایتان به پیش رانده است. به هر حال، کارهایی که شما کردهاید خود به خوبی گویای همه چیز هستند. آیا فکر میکنید که این رویکرد در نحوهای که چیزهای مختلف را توضیح میدهید هم اثر گذاشته است؟
کنوث: تنها چیزی که درباره نحوه توضیح دادنم میتوانم ادعا کنم این است که سعی میکنم به منظور درک بهتر یک چیز، همزمان به دو شیوه متفاوت به آن نگاه کنم. این کار با فرایند طبیعی مغز من سازگارتر است. فکر میکنم نکته کلیدی، داشتن نگاهی دو جانبه به جای نگاهی یک بعدی است. نمیدانم این چقدر بر رویکرد من در مورد اشکالزدایی تأثیرگذار بوده است.
وقتی شما حالت تهاجمی داریدـ مثلاً وقتی دارید با یک نفر بازی میکنید و سعی میکنید او را شکست دهید- هورمونهایی در بدنتان ترشح میشوند که مغز را تحریک میکنند که برای دستیابی به هدف، همه راهها را امتحان کند. یک توضیح خوب هم همین طور است. یک توضیح خوب، ترکیبی است از دیدگاههای مختلف.
سیبِل: چیز دیگری که مربوط به کار شما در تولید TeX است و شما آن را در «خطاهای TeX » توضیح دادهاید این است که گفتهاید هر خطایی را که در برنامه مییافتید ثبت میکردید. افرادی مانند کسانی که در مؤسسه مهندسی نرمافزار کار میکنند میگویند که بخشی از فرایند بلوغ در مهندسی نرمافزار، ردیابی تمام خطاها و یادگیری چگونگی جلوگیری از بروز خطاهای مشابه در آینده است. امّا شما گفتهاید که نگهداری سابقه خطاها کمکی به شما در جلوگیری از خطاهای آینده نکرد.
کنوث: بله. ثبت خطاها کمکی به این که برنامهنویس بهتری شوم نکرد.
سیبِل: این احساس در شما به وجود نیامد که «آها، حالا که این خطا را دیدم، دیگر تکرارش نمیکنم»؟
کنوث: من فقط گناهانم را تشخیص میدادم. اگر با اصطلاحات دینی آشنا باشید، به این میگویند تقاضای آمرزش!
سیبِل: پس شما بعد از یافتن یک خطا در برنامههایتان میگوئید «اوه، باز هم همان خطای پیشین را تکرار کردم»؟
کنوث: بله.
سیبِل: چرا این چنین است؟ آیا ارتباطی به طبیعت اشتباهات دارد که درس گرفتن برای جلوگیری از تکرار آنها در آینده را دشوار میسازد؟
کنوث: من فکر میکنم احتمالاً بیشتر به خاطر این است که من همیشه به کارهایی سختتر از کارهای پیشین میپردازم. چنانچه به عقب بازگردم و بخواهم همان برنامههای قبلی را دوباره بنویسم، مطمئناً آنقدر اشتباه نمیکنم. امّا همان طور که گفتم همیشه سعی میکنم برنامههای دشوارتری نسبت به برنامههای قبلی بنویسم و علت بروز خطاها هم همین است. اگر بخواهم همیشه در همان محدوده راحت قبلی بمانم، دیگر جنبه سرگرم کنندهاش را برایم از دست خواهد داد.
سیبِل: منظورتان این است که مثلاً اگر میخواستید تا پایان عمرتان سیستمهای حروفچینی بنویسید؟
کنوث: بله. اگر ما خودمان را محدود به انجام کارهای ساده بکنیم، ارضاء کننده نیست زیرا تمایل بشر همواره به فراتر بردن مرزهاست. بنابراین، به ناچار همیشه با خطاهایی روبرو خواهیم شد، مگر آن که نخواهیم برنامهای بنویسیم که تواناییهایمان را گسترش دهد. و جالب اینجاست که هر سه سال یکبار هم یک ایده جدید مطرح میشود و مدّعی میگردد که تمام این مسایل و مشکلات را حل میکند. برنامهنویسی مفرط یکی از همین ایدهها بود که دو یا سه سال پیش سر زبانها افتاد. پیش از آن نیز یک چیز دیگر بود. هر از گاهی یک نفر با یک ایده نجاتبخش پیدا میشود و بسیاری از برنامهنویسان نیز سوار قطار او میشوند و پس از چندی دوباره در مییابند که «مشکل همچنان باقیست.»
سیبِل: آیا نوع افرادی که میتوانند برنامهنویس خوبی شوند، در طول زمان تغییر کرده است؟
کنوث: در دوران طولانی فعالیت حرفهای من، از هر صد نفری که دیدهام، بجز کسانی که در دانشگاه رشته دانش رایانه (علوم کامپیوتر) را خواندهاند، تنها 2 نفر از آنها برنامهنویس واقعی بودند و این نسبت تقریباً همیشه ثابت باقی مانده است. یعنی در یک شهری که 10 هزار نفر جمعیت داشته باشد، حدوداً 200 برنامهنویس وجود خواهد داشت.
سیبِل: پس اجازه دهید پرسشم را این گونه مطرح کنم که آیا برنامهنویسی آنقدر تغییر کرده است که نوع افرادی که در آن 2 درصد قرار میگیرند، تغییر کرده باشد؟ یا هنوز مثل قبل است؟
کنوث: نمیدانم. شما میتوانید واژه «برنامهنویسی» را به معانی متفاوتی به کار ببرید. ما همیشه ابزارهایی درست میکنیم که تطابق بین مغز انسان و کاری که در داخل رایانه انجام میشود را بیشتر کنند. منظورم نحوهای است که ماشین واقعاً کار میکند نه گرفتن جواب از آن.
ما اکنون ماشینهایی داریم که آنقدر قدرتمندند که افرادی که برنامهنویس خوبی نیستند- حداقل از دید من- هم قادرند جوابهایی از آنها بگیرند که گرفتن این جوابها بر روی ماشینهای قدیمی نیاز به افراد کاملاً خبره داشت. امّا با ماشینهای جدید، همین افرادی که من دارم دربارهشان صحبت میکنم مسایلی را انجام میدهند که بر روی ماشینهای قدیمی قابل انجام نبود.
بنابراین، میتوان گفت چنین تغییری صورت گرفته است و همچنین تغییر دیگری که من جداً نگرانش هستم و آن این که شیوهای که امروزه بسیاری از افراد برنامهنویسی میکنند دیگر به هیچوجه لذتبخش و سرگرم کننده نیست زیرا صرفاً عبارت است از سر هم کردن نرمافزارهایی که دیگران نوشتهاند برای به دست آوردن برنامه مورد نظرشان. دیگر خلاقیت و نوآوری چندانی در کار نیست. نگرانی من از این است که برنامهنویسی کار بسیار کسل کنندهای شود زیرا شما دیگر بخت چندانی برای انجام یک کار جدید ندارید. خوشحالی شما صرفاً از دیدن جوابهای زیبایی است که از ماشین بیرون میآید نه از نوع خوشحالی که من همیشه از تولید یک چیز جدید به دست میآوردم. خوشحالی شما اکنون بعد از یک کار کسل کننده به دست میآید. در گذشته، خودِ کار هم کسل کننده نبود.
سیبِل: آیا هنوز نوعی از برنامهنویسی وجود دارد که برایتان جالب باشد؟
کنوث: اوه، البته که وجود دارد. این نیاز من برای برنامهنویسی است. من صبح با جملهای از یک برنامه ادیبانه بیدار میشوم و باید پای رایانه بروم و یک پاراگراف بنویسم تا پس از آن بتوانم چیزی بخورم. اطمینان دارم که شاعران این حس مرا درک میکنند. نوعی وسواس است. باید این را بپذیرم.
خوب، بگذارید برنامهای که دیروز نوشتم را به شما نشان دهم. من برنامهای برای ضرب اعداد صحیح بسیار بزرگ نوشتم. این اعداد آنقدر بزرگ هستند که با سیستم علامتگذاری عادی نمیتوان آنها را نمایش داد. من این اعداد را درهم ضرب کردهام و آنها را به توان 2 رساندهام تا ببینم مربعشان چه شکلی میشود. من در مورد این که چه اتفاقی میافتد خیلی ابهام دارم امّا این کار برایم جالب است.
سیبِل: شما آدم دانشگاهی هستید و در عین حال بر روی سیستمهای بزرگ کار کردهاید و تجربیاتی نیز در صنعت دارید. ارتباط بین دانش رایانه آن گونه که در دانشگاه تدریس میشود و آن گونه که در صنعت به کار برده میشود را چگونه میبینید؟
کنوث: بالا و پایین داشته است. در دهه 1960 دانشگاه خیلی جلوتر از صنعت بود و برنامههایی که در صنعت تولید میشد، شاید بجز سیستمهای ذخیره بلیت هواپیما، برای افراد دانشگاهی خندهآور بود.
در 1980 وضعیت کاملاً برعکس شده بود و برنامههایی که در دانشگاهها نوشته میشدند مورد تمسخر افرادی که در صنعت بودند قرار میگرفتند زیرا دانشگاهها گرفتار بحثهای نظری شده بودند و مثلاً شما اجازه نداشتید از جملات go to در برنامههایتان استفاده کنید. من عملاً مبالغه میکنم که مطلب را سادهتر کنم امّا واقعاً محدودیتها و موانع زیادی در برنامههای دانشگاهی وجود داشت که دست افراد را بسته بود در حالی که افرادی که در بخش صنعت کار میکردند، هیچ نگران آنها نبودند.
امّا بعد در دانشگاهها، افراد به ایدههای بهتری درباره شبکهسازی و کار با دادههای حجیم و امثال آن دست یافتند و دوباره از صنعت جلو افتادند. بنابراین، همان طور که گفتم بالا و پایین داشته است. امّا نکتهای که مایلم بگویم این است که دانشگاهها از لحاظکارهای انتزاعی در بعضی زمینهها راه افراط را پیمودهاند. بسیاری از کارهای دانشگاهی با زندگی واقعی ارتباطی نداشته است. انگار برای دنیای دیگری طراحی شدهاند.
من نمیدانم چرا این قدر برایم اهمیت دارد که هر چیز با دنیای واقعی و تجربه عملی ارتباط داشته باشد. ریاضیدانانی هستند که هرگز درباره یک چیز متناهی فکر نکردهاند. آنها مقالات علمی جالبی هم چاپ میکنند که برایشان کاملاً ارضاء کننده است. در مورد الگوریتم هم چنین وضعیتی وجود دارد. امّا برای من، ایدههایی که بتوانم آنها را بر روی ماشینم به کار ببرم، هیجانانگیزتر و جالبترند.
سیبِل: در سال 1974 شما گفته بودید که تا سال 1984 ما نوعی زبان برنامهنویسی کامل خواهیم داشت که جایگزین کوبول و فرترن خواهد شد و گفته بودید که نشانههایی وجود دارد که شکلگیری چنین زبانی به کندی صورت خواهد گرفت. اکنون چند دهه از 1984 گذشته و چنین چیزی اتفاق نیفتاده است.
کنوث: نه، اتفاق نیفتاده است.
سیبِل: آیا صرفاً یک خوش خیالی دوران جوانی بود؟
کنوث: هنگامی که این مطلب را نوشتم به زبان سیمولا و روندی که در برنامهنویسی شیءگرا وجود داشت فکر میکردم. فکر میکنم اتفاقی که میافتد این است که هر زمان که زبان جدیدی بیرون میآید، چیزهایی که درباره زبانهای قدیمیتر فهمیده شده بود را پاکسازی میکند و بعد یک چیز اضافه میکند و به همین ترتیب، و هیچکس هرگز به نقطهای نمیرسد که یک زبان برنامهنویسی جدید داشته باشد و بخواهد در همانجا متوقف شود. این فزونخواهی همیشه وجود دارد.
شاید یک روز یک نفر بگوید «نه، من نمیخواهم نوآور باشم. فقط میخواهم ساده و تمیز باشم و به همین که هست بسنده کنم.» زبان پاسکال با همین فلسفه آغاز شد ولی ادامه نیافت. شاید زمانی برسد که یک نفر بگوید «بهتر است توقعاتمان را پایین بیاوریم و سعی کنیم چیزی بسازیم که پایدار باشد.» این ایده خوبی میتواند باشد.
سیبِل: وقتی در یک زبان ویژگیهایی در نظر گرفته نمیشود، دیگران سعی میکنند که با طراحی یک زبان دیگر، جای خالی آن ویژگیها را پر کنند.
کنوث: بله، درست است. زبان باید به نوعی توسعهپذیر باشد. مثلاً جاوا به نحو مناسبی خودش را توسعهپذیر نکرده است.
سیبِل: شما خودتان هم چند زبان را طراحی کردهاید که احتمالاً TeX بیشتر از بقیه مورد استفاده قرار گرفته است.
کنوث: البته TeX یک زبان برنامهنویسی است امّا من مجبور شدم برخی از ویژگیها را در آن بگنجانم. وقتی گای استیل، تری وینوگراد، لسلی لمپورت و افراد مختلف از TeX به عنوان پایانه تحریر مستقیم (تحریر مطلب در رایانه که در اصل به منظور ذخیره اطلاعات حرفهای است امّا در ضمن، حروف چینی متن نیز محسوب میشود و مرحله حروفچینی را حذف میکند. مترجم) استفاده میکردند، به ویژگیهایی نیاز داشتند. فکر میکنم تری وینوگراد داشت کتابی درباره قواعد نحوی زبانهای طبیعی مینوشت و کلاندستورهای قدرتمندی داشت که میخواست برای تولید نمودارهای کتابش بنویسد. این درخواستها TeX را در روزهای اولیه به سمت یک زبان برنامهنویسی سوق داد.
سیبِل: آیا فکر نمیکردید بهتر بود بر روی طراحی TeX به عنوان یک زبان، تمرکز بیشتری میکردید؟
کنوث: نمیدانم. شاید. من از این که هر زبانی، عمومی باشد بیزارم زیرا این خصیصه در هر زبانی به یک شکل پیادهسازی میشود. کمی شبیه یونیکس است که دارای 30 تعریف برای عبارتهای منظم در زیر یک سقف است. بسته به این که از کدام بخش یونیکس استفاده میکنید، تعبیر کاملاً متفاوتی از عبارتهای منظم خواهید داشت. من فکر میکردم هر چه ویژگیهای برنامهنویسی بیشتری در TeX بگنجانم، از مأموریت اصلیش که حروفچینی است دورتر میشود.
هنگامی که محاسبه اعداد اوّل را در جزوه راهنمای TeX قرار میدادم، به آن به عنوان روش استفاده از TeX فکر نمیکردم. فکر میکردم «همان طور که سگها میتوانند روی پاهای عقبیشان بایستند، TeX هم میتواند اعداد اوّل را محاسبه کند.»
سیبِل: امّا مردم از این واقعیت که یک زبان برنامهنویسی کامل است برای انجام محاسبات مربوط به حروفچینی استفاده میکردند. اگر یک زبان برنامهنویسی کامل نبود آنها نمیتوانستند آن کارها را انجام دهند.
کنوث: بله، درست است. من در دهه 1960 یک زبان برنامهنویسی برای شبیهسازی نوشتم که بعداً مجبور شدم برای از بین بردنش تلاش زیادی بکنم زیرا کاربران زیادی داشت امّا هنگامی که زبان سیمولا عرضه شد، من از آن بیشتر از زبان خودم خوشم آمد و به مردم گفتم استفاده از زبان SOL را متوقف کنند. به نظرم رسید که استعداد خوبی برای طراحی زبان ندارم.
در مورد TeX من در تعامل با صدها سال تاریخ بشر بودم و نمیخواستم تمام چیزهایی که طراحان کتاب در طول قرنها یاد گرفتهاند را کنار بگذارم و از نو شروع کنم. در این مورد، کاری که باید انجام میشد عبارت بود از گرفتن یک مسئله فوقالعاده پیچیده و یافتن مجموعه نسبتاً کوچکی از عناصر اوّلیه برای پشتیبانی از آن. به جای داشتن 1000 عنصر اوّلیه، من 100 تا یا چیزی نزدیک آن داشتم. امّا اگر میخواستم آن را به 50 یا 10 عنصر اوّلیه تقلیل دهم- که از نظر ریاضی امکانپذیر بود- از لحاظ عملی مشکلزا میشد. مسئله تولید کتاب هم جزء آن دسته از پیچیدگیهای این جهان است که نمیخواهند سادهسازی شوند.
سیبِل: من آمار دقیقی ندارم امّا به نظر میرسد امروزه بخش عمدهای از مقالات ریاضی و علمی با TeX حروفچینی میشود. باید یک چیزی وجود داشته باشد که وقتی شما مطلبی را که با TeX حروفچینی شده میبینید به خودتان بگوئید «برنامه من هم در این نقش داشته است.»
کنوث: خوب، اثبات قضیه آخر فرما یکی از آنهاست. این یکی از معروفترین مقالات ریاضی است. و بارها برای من پیش آمده که کتابهایی را دیدهام و به این نتیجه رسیدهام که اگر نویسندگانشان میخواستند از همان شیوههای قدیمی برای حروفچینی آنها استفاده کنند، هرگز آن کتابها نوشته نمیشدند.
عادت بر این بود که شما چیزی را مینوشتید و آن نزد حروفچین میرفت و بعد نمونه چاپی برای غلطگیری به شما بازگردانده میشد و به همین ترتیب. در این فرایند افراد مختلفی روی نوشته شما کار میکردند که هیچکدام ریاضیدان نبودند و شما جرئت نداشتید کاری کنید که آنها را دچار ابهام سازد.
امّا اگر خودتان بتوانید ببینید که آنچه نوشتهاید چه شکلی میشود و بتوانید نمادهایی را بسازید که برای مقاله شما و انتقال مفاهیم آن به خواننده مناسبترند، تشویق میشوید که کارهای خیلی بهتری بکنید.
بنابراین، دانستن این که افراد قادر بودهاند این فرایند را کوتاه کنند و خلاقیتشان را مستقیماً به خواننده منتقل کنند، برای من بسیار ارضاء کننده است.
سیبِل: آیا احساس میکنید که برنامهنویسان و دانشمندان رایانه به قدر کافی با تاریخچه و پیشینه رشته ما آشنایی دارند؟ هر چند تاریخچه کوتاهی هم دارد.
کنوث: تعداد پژوهشگران زیاد نیست. حتی هنگامی که من در سال 1963 شروع به نوشتن کتابهایم کردم، فکر نمیکردم که مردم بدانند در سال 1959 چه اتفاقی افتاده است. هفته گذشته مقالهای در مجله آمریکن ساینتیست میخواندم درباره افرادی که الگوریتم به دست آمده توسط بویر و مور در سال 1980 را دوباره به دست آوردهاند. بسیار اتفاق میافتد که افرادی تاریخ پر افتخاری که ما داریم را باور ندارند. برای بسیاری از برنامهنویسان جوان، عجیب است که در دهه 1970 هم کسانی بودهاند که مختصر معلوماتی داشتهاند.
در چنین رشته و حوزه پیچیدهای این که مردم چیزهایی را نادیده بگیرند گریزناپذیر است. امیدوارم با چیزهایی مانند ویکی پدیا، دیگر دستاوردهای گذشته، آنچنان که پیش از این روی میداد، به بوته فراموشی سپرده نشود. امّا آرزوی من این است که بتوانم عشق و علاقهای را که به خواندن منابع اصلی و دست اوّل دارم، به افراد هر چه بیشتری منتقل کنم. به نظر من این فقط کافی نیست که بدانیم فلان کس در گذشته چکار کرده است بلکه خوب است به گذشته برگردیم و ببینیم آن شخص به زبان خودش چه گفته است. فکر میکنم این یک روش عالی برای بهبود مهارتهای خودمان باشد.
این که بتوانیم به درون طرز فکر یک نفر راه پیدا کنیم و نمادگذاریها و واژگانش را بشناسیم، خیلی اهمیت دارد. اگر بتوانیم چیزی درباره شیوه تفکر آنها و نحوهای که به کشفی نائل شدهاند درک کنیم، به ما کمک میکند که خودمان به کشفیات تازه بپردازیم. من غالباً مطالب اصلی که در گذشته توسط افراد برجسته رشته ما نوشته شده است را میخوانم. هر چند با قراردادها و قاعدههای امروزی به شیوه نامعمولی بیان شدهاند امّا برای من از لحاظ ورود به دنیای نمادگذاریهای آنها و راهیابی به درونمایه ایدههایشان، بسیار ارزشمند است.
برای مثال، من زمان زیادی را صرف نگاه کردن به دست نوشتههای بابلی کردم تا دریابم آنها چگونه در 4000 سال پیش به توصیف الگوریتمها میپرداختند و دربارهاش چه فکری میکردند؟ آیا حلقههای while و چیزهایی شبیه به آن داشتند؟ آن را چگونه توصیف میکردند؟ برای من این کار به لحاظ درک چگونگی کار مغز و نیز این که آنها چگونه چیزهای تازه را کشف کرده بودند، خیلی با ارزش بود.
چند سال پیش، یک متن قدیمی به زبان سانسکریت مربوط به قرن سیزدهم پیدا کردم که درباره ریاضیات ترکیباتی بود. تقریباً هیچکس از بین کسانی که نویسنده آن متن میشناخت متوجه نشده بودند که او درباره چه چیزی دارد حرف میزند. امّا من ترجمه آن متن را به دست آوردم و دیدم که انگار دارد با من حرف میزند. من هم هنگامی که تازه برنامهنویسی رایانه را شروع کرده بودم، تفکرات مشابهی داشتم. و بدین ترتیب، خواندن منابع اصلی باعث غنای بیشتر زندگی و خلاقیت من میشود.
من اعتراف میکنم که نتوانستهام این شور و علاقه را به دانشجویانم منتقل کنم. هنوز افرادی در بین دانشمندان رایانه هستند که به این کار میپردازند. امّا تعداد کسانی که مانند من به منابع اصلی علاقهمند باشند از تعداد انگشتان یک دست تجاوز نمیکند.
من مجموعه مفصّلی از کدهای مبدأ دارم. من کد مبدأ برنامههای مترجم (کامپایلر) شرکت دیجیتک در دهه 1960 را دارم که به شیوه خیلی جالبی نوشته شده است. آنها زبان خاص خود را داشتند و از شناسههایی به طول 30 نویسه استفاده میکردند که خیلی توصیفی بودند و برنامههای مترجم آنها در آن زمان، یعنی سال 1963 یا 1964، جزء پیشرفتهترین مترجمها بودند. و نیز کد مبدأ سیستمعامل THE دایکسترا را به دست آوردهام. هنوز آن را به دقّت نخواندهام. فقط نگاهی به آن انداختهام امّا مطمئنم که اگر وقت پیدا کنم، خواندنش برایم جالب خواهد بود.
یکبار که به دلیل افتادن از دوچرخه دستم شکسته بود و یکماه دستم در گچ بود و کار چندانی نمیتوانستم بکنم، به خواندن کد مبدأیی که شنیده بودم ایدههای هوشمندانهای در آن وجود دارد که مستندسازی نشده است پرداختم. فکر میکنم تجربه بسیار مهمی برای من بود.
سیبِل: شما کد مبدأ را چگونه میخوانید؟ حتی خواندن یک برنامه که به زبان برنامهنویسی سطح بالا نوشته شده است نیز غالباً دشوار و پردردسر است.
کنوث: امّا به خاطر آن چه که در مغز شما به وجود میآورد، واقعاً ارزشمند است. پرسیدید من چطور این کار را میکنم؟ ماشینی بود به اسم بانکر رامو 300 و یک نفر به من گفت که مترجم فرترن این ماشین به نحو شگفتانگیزی سریع است امّا هیچکس نمیداند چگونه کار میکند. من یک نسخه از لیست کد مبدأ آن را گرفتم. جزوه راهنمای آن ماشین را هم نداشتم و حتی مطمئن نبودم که زبان ماشینش چیست.
من به آن به عنوان یک چالش جالب نگاه میکردم. توانستم حدس بزنم که چه چیزی معادل BEGIN است و سپس شروع به کدگشایی کردم. کدهای دستورالعمل دو حرفی بودند و من شروع کردم به حدس زدن این که «این احتمالاً دستور بارگیری و آن احتمالاً دستور پرش است.» و چون میدانستم که مترجم فرترن است، از روی شماره ستونی که دستورها شروع شده بودند فهمیدم که آنچه نوشته شده یک دستور است یا توضیحات .
پس از سه ساعت توانستم تصوّر اندکی از ماشین به دست آورم. سپس به این جدولهای بزرگ انشعابزنی رسیدم. مثل یک معمّا بود و من برای خودم نمودارهای کوچکی رسم میکردم و کارم شبیه یک مأمور امنیتی بود که سعی میکند یک کد مخفی را رمزگشایی کند. البته من میدانستم که مترجم فرترن است و درست کار میکند- این طور نبود که انگار عمداً رمزگذاری شده است. مشکل این بود که جزوه راهنمایی از آن ماشین نداشتم.
سرانجام توانستم بفهمم که چرا این برنامه مترجم این قدر سریع کار میکند. متأسفانه به خاطر این نبود که الگوریتم خیلی جالبی داشت، بلکه به خاطر این بود که از برنامهنویسی غیرساختیافته استفاده کرده بود. البته بهینهسازی هم شده بود.
در اصل مثل این بود که شما بخواهید یک معمای ناشناخته را حل کنید. جدولها و نمودارهایی درست کنید و کمی اطلاعات بیشتر از اینجا و آنجا به دست آورید و حدسی بزنید. به طور کلّی، هنگامی که من یک مقاله فنی میخوانم هم چالش مشابهی برایم وجود دارد. سعی میکنم به درون ذهن نویسنده راه یابم و سعی میکنم مفهوم مقاله را دریابم. به نظر من، هر چه بیشتر یاد بگیرید که مطالب دیگران را بخوانید، بیشتر قادر خواهید شد که در آینده به ابداع و نوآوری بپردازید.
ما باید کدها را منتشر کنیم. باید از اپل تشکر کرد که برنامههای بیل اتکینسون را در دسترس عموم قرار داده است و طولی نخواهد کشید که ما قادر به خواندن آنها خواهیم شد. این برنامهها به خوبی مستندسازی شدهاند و حاوی تعداد زیادی الگوریتمهای گرافیکی پیشتازانه هستند.
سیبِل: مطمئناً با رویکردی که به نرمافزارهای متن باز وجود دارد کدهای بیشتری هم نسبت به گذشته برای خواندن وجود خواهد داشت.
کنوث: بله، درست است. امّا آگاهی از انواع گوناگون نمادگذاریها هنوز بسیار مفید است. تنها کد کسانی را که مثل خودتان برنامه مینویسند نخوانید.
منبع:
* "Coders at Work", Peter Seibel, Apress, 2009
|