Историята на Мел
Изпратена в USENET от нейния автор Ед Нетер на 21 май 1983 г.Наскоро в една статия, посветена на истинския “мъжки” стил на програмиране, се появи смелото и категорично твърдение:
Истинският програмист пише на Fortran.
Може би сега в тази упадъчна ера на светла бира, джобни калкулатори и приятелски интерфейс, но в Доброто Старо Време, когато “софтуер” звучеше непознато и Истинските Компютри бяха направени от барабани и електронни лампи, Истинските Програмисти пишеха на машинен код. Не на Fortran. Не на BASIC. Дори не на Assembler. Машинен код. Груби, прозаични, неразбираеми шестнадесетични цифри. Директно.
За да не израсне цяло едно поколение от програмисти, без да познава това славно минало, аз се чувствам морално задължен да опиша толкова добре, колкото ми позволява разликата в поколенията, как пишеше тогава Истинският Програмист. Ще го наричам Мел, понеже това беше неговото име.
За пръв път срещнах Мел, когато започнах работа при Royal McBee Computer Corp., отдавна несъществуващ филиал на компанията за пишещи машини. Фирмата произвеждаше LGP-30, малък, евтин (за онова време) компютър с барабанна памет и тъкмо започваше да произвежда RPC-4000 – по-усъвършенстван компютър, по-голям, по-добър, по-бърз … с барабанна памет. Магнитните сърцевини струваха твърде много, а и без това не им беше там мястото. (Затова не сте чули нито компанията, нито компютъра.)
Бях нает да напиша компилатор за Fortran за това ново чудо и Мел ме посвещаваше в тайните му. Мел не обичаше компилаторите.
“Ако програмата не може да възпроизведе собствения си код – казваше той – каква е ползата от нея?”
Мел беше написал в шестнадесетичен код най-популярната компютърна програма, която компанията притежаваше. Работеше на LGP-30 и играеше на “21” с потенциалните купувачи по компютърните изложби. Ефектът й винаги беше драматичен. На всяка изложба павилионът на LGP-30 беше пълен, а търговските посредници на IBM стояха отстрани, говорейки помежду си. Дали това се отразяваше на продажбите, беше въпрос, на който никога не сме се спирали.
Работата на Мел бе да преработи програмата за “21” за RPC-4000. (Порт? Какво означава това?) Новият компютър имаше адресна схема “едно плюс едно”, в която всяка машинна инструкция в добавка към кода на операцията и адреса на операнда имаше втори адрес, указващ къде на въртящия се барабан се намира следващата инструкция.
Както бихме казали днес, след всяка инструкция следваше GOTO! Направете от това блок-схема!
Мел обичаше RPC-4000, защото можеше да оптимизира кода си: като подреди инструкциите върху барабана така, че точно когато едната си е свършила работата, следващата да пристигне под четящата глава и да бъде на разположение за незабавно изпълнение. Имаше програма, която правеше точно това – “оптимизиращ асемблер”, но Мел отказваше да я използва.
“Никога не знаеш къде ще сложи нещата – обясняваше той, – така че трябва да ползваш отделни константи.”
Мина много време, преди да разбера тази забележка. Тъй като Мел помнеше шестнадесетичното представяне на код на всяка операция и присвояваше свои собствени адреси от барабанната памет, всяка инструкция, написана от него, би могла да се разгледа като числова константа. Той можеше да вземе предишна инструкция и да я използва като операнд при следващото умножение, ако тя съответстваше на необходимата числена стойност. Програмата му трудно можеше да се променя от друг.
Сравнявал съм ръчно оптимизираните програми на Мел със същия код, преработен от оптимизиращия асемблер. Тези на Мел винаги работеха по-бързо. Причината бе, че методът за програмиране “от вън на вътре” все още не беше измислен, а и Мел едва ли щеше да го използва. Той пишеше първо най-вътрешните цикли в програмата, така че достъпът до тях да е най-бърз. Оптимизиращият асемблер не беше достатъчно умен, за да работи по този начин.
Мел също никога не пишеше закъснителни цикли, дори когато упоритият Flexowriter изискваше закъснение между отделните символи, за да работи както трябва. Той просто разполагаше инструкциите върху барабана така, че всяка следваща беше току-що отминала четящата глава и барабанът трябваше да направи още един цял оборот, преди да я намери. Той беше измислил незабравим термин за тази процедура. Въпреки че “оптимален” е абсолютно определение също като “уникален”, стана практика да се превръща в относителен: “не докрай оптимален”, или “не много оптимален”. Мел наричаше прехода с максимално времезакъснение “най-песимален”.
След като завърши програмата за игра на “21” и я настрои за работа (“Дори инициализацията е оптимизирана” – каза той гордо), се получи Заявка За Промяна от отдела за продажби. Програмата използваше елегантен (оптимизиран) генератор на случайни числа за разбъркване на и раздаване на “картите” от “тестето” и някои от търговските посредници бяха решили, че е прекалено честна, тъй като понякога клиентите губеха. Искаха Мел да преработи програмата така, че със сензорен превключвател на конзолата раздаването да се промени и клиентът да спечели.
Мел се опъна. Той определи това като явна несправедливост, каквато си беше, и като посегателство върху неговата лична почтеност на програмист, какъвто си беше, и отказа да го направи. Търговският директор разговаря с Мел, както и Шефът на фирмата, а по негово настояване и няколко колеги програмисти. Накрая Мел се предаде и написа кода, но беше обърнал условието – когато се включеше сензорният превключвател, програмата играеше нечестно, побеждавайки всеки път.
Мел ахна. Заяви, че подсъзнанието му е неконтролируемо честно, и твърдо отказа по-нататъшни промени.
След като Мел напусна компанията за по-зелени па$бища, Шефът ме помоли да погледна кода и ако успея да намеря проверката да я обърна. Малко неохотно се съгласих да погледна. Да трасираш код написан от Мел, беше истинско приключение.
Винаги съм смятал, че програмирането е изкуство, чиято истинска стойност може да се оцени само от друг, посветен в това тайнство; има прекрасни бисери и поразителни хрумвания, скрити от човешкия поглед и възхищение понякога завинаги поради самото естество на процеса. Можеш да научиш много за един човек само като четеш кода, който е написал, дори в шестнадесетичен вид. Мисля, че Мел беше невъзпят гений.
Може би най-големият шок дойде, когато намерих съвсем невинен цикъл, в който липсваше проверка. Нямаше проверка. “Нищо”. Според здравия разум това би трябвало да бъде безкраен цикъл, където програмата ще остане да се върти завинаги. Изпълнението обаче минаваше през него и продължаваше спокойно. Отне ми две седмици докато го проумея.
RPC-4000 беше осъвременен с т.нар. индексен регистър, позволяващ на програмиста за напише цикъл, който да използва вътре в себе си индексирана инструкция. Всеки път стойността на индексния регистър се прибавя към адреса на тази инструкция, така че да сочи към следващата данна в поредицата. Трябваше само всеки път да се увеличава стойността на индексния регистър. Мел никога не използваше индексния регистър.
Вместо това той изтегляше инструкцията в машинния регистър, добавяше единица към адреса й и я записваше обратно. След това изпълняваше преработената инструкция направо от регистъра. Цикълът беше написан така, че времето за това събиране да бъде точно толкова, колкото е необходимо, за да бъде изпълнена инструкцията, а следващата да се придвижи под четящата глава на барабана, готова за изпълнение. Но цикълът нямаше проверка.
Хванах нишката, когато забелязах, че флагът на индексния регистър, разположен между адреса на инструкцията и кода на операцията в машинната дума, е вдигнат – въпреки че Мел никога не използваше индексния регистър, оставяйки го нулиран през цялото време. Когато лампичката ми светна, едва не ме ослепи.
Той беше разположил данните в горния край на паметта – последното пространство, което инструкциите можеха да адресират, така че, след като последната данна бъде обработена, увеличаването на адреса на инструкцията да го препълни. Преносът ще прибави единица към кода на операцията, превръщайки в следващата команда от набора: jump инструкция. Разбира се следващата инструкция беше разположена на адрес нула и програмата продължаваше щастливо по пътя си.
Не съм се чувал с Мел, така че не знам дали той някога е отстъпил пред промените, залели техниката на програмиране през годините, изминали оттогава. Иска ми се да вярвам че не е. Във всеки случай бях до толкова впечатлен, че се отказах да търся “обърканата” проверка, като казах на Шефа, че не мога да я намеря. Той не бе изненадан.
Когато напуснах компанията, програмата за игра на “21” все още мамеше, ако се натисне сензорният превключвател, и мисля, че така се е редно. Не ми бе приятно да бърникам в кода на един Истински Програмист.