(Бұл мақала жаңа тілге арналған өзіндік бизнес-жоспар ретінде жазылған. Сондықтан мұнда жақсы бағдарламалау тілінің ең маңызды қасиеті: өте қуатты абстракциялар қасиеті жоқ (өйткені ол әуел бастан солай болуы тиіс деп қабылданған).)
Бір досым кезінде операциялық жүйелер саласындағы көрнекті сарапшыға өте жақсы бағдарламалау тілін жасағысы келетінін айтыпты. Сарапшы оған бұл уақытты босқа өткізу екенін, бағдарламалау тілдерінің танымал немесе танымал емес болуы олардың артықшылықтарына байланысты еместігін, сондықтан оның тілі қаншалықты жақсы болса да, оны ешкім қолданбайтынын айтқан. Әйтеуір, өзі жасаған тілдің тағдыры дәл солай болған екен.
Тілді шынымен не танымал етеді? Танымал тілдер өз танымалдығына лайық па? Жақсы бағдарламалау тілін анықтауға тырысудың мәні бар ма? Мұны қалай істер едіңіз?
Меніңше, бұл сұрақтардың жауабын хакерлерді бақылап, олардың не қалайтынын білу арқылы табуға болады. Бағдарламалау тілдері хакерлер үшін арналған, және бағдарламалау тілі ретіндегі жақсы тіл (айталық, денотативтік семантика немесе компилятор дизайны бойынша жаттығу емес) тек хакерлерге ұнаған жағдайда ғана жақсы болып саналады.
1 Танымалдық механикасы
Әрине, адамдардың көпшілігі бағдарламалау тілдерін тек олардың артықшылықтарына қарап таңдамайтыны рас. Бағдарламашылардың көпшілігіне қай тілді қолдану керектігін біреу айтып отырады. Дегенмен, менің ойымша, мұндай сыртқы факторлардың бағдарламалау тілдерінің танымалдығына тигізетін әсері кейде ойлағандай онша үлкен емес. Негізгі мәселе мынада деп ойлаймын: хакердің жақсы бағдарламалау тілі туралы түсінігі тіл жасаушылардың көпшілігінің түсінігімен сәйкес келмейді.
Екеуінің ішінде маңыздысы — хакердің пікірі. Бағдарламалау тілдері теорема емес. Олар — адамдар үшін жасалған құралдар, және аяқкиім адамның аяғына шақ етіп жасалуы керек сияқты, олар да адамның мықты әрі әлсіз тұстарына бейімделіп жасалуы тиіс. Егер аяқкиімді кигенде аяғыңызды қысса, ол мүсін өнері тұрғысынан қаншалықты әсем болса да, бәрібір жаман аяқкиім.
Бағдарламашылардың көпшілігі жақсы тілді жаман тілден ажырата алмауы мүмкін. Бірақ бұл кез келген басқа құралға да қатысты. Бұл жақсы тіл жасауға тырысу уақытты босқа өткізу дегенді білдірмейді. Сарапшы хакерлер жақсы тілді бірден таниды және оны қолданады. Сарапшы хакерлер өте азшылық екені рас, бірақ барлық жақсы бағдарламалық жасақтаманы жазатын осы шағын азшылық, және олардың ықпалы соншалық, қалған бағдарламашылар олар қай тілді қолданса, соны қолдануға бейім болады. Шынында да, бұл көбінесе жай ғана ықпал емес, тікелей бұйрық болып келеді: көбінесе сарапшы хакерлер басшы немесе ғылыми жетекші ретінде басқа бағдарламашыларға қай тілді қолдану керектігін айтатын адамдардың дәл өзі болып шығады.
Сарапшы хакерлердің пікірі бағдарламалау тілдерінің салыстырмалы танымалдығын анықтайтын жалғыз күш емес — ескірген бағдарламалық жасақтама (Cobol) мен жасанды даңғаза (Ada, Java) да рөл атқарады — бірақ меніңше, ұзақ мерзімді перспективада бұл ең қуатты күш. Бастапқы сыни масса мен жеткілікті уақыт берілсе, бағдарламалау тілі өзі қаншалықты лайық болса, шамамен соншалықты танымал болады. Ал танымалдық жақсы тілдерді жамандарынан одан әрі ажырата түседі, өйткені нақты қолданушылардың кері байланысы әрқашан жақсартуларға әкеледі. Кез келген танымал тілдің өз өмірінде қаншалықты өзгергеніне қараңызшы. Perl мен Fortran — төтенше мысалдар, бірақ тіпті Lisp те көп өзгерді. Мысалы, Lisp 1.5 нұсқасында макростар болмаған; олар кейінірек, MIT хакерлері нақты бағдарламалар жазу үшін Lisp-ті екі жылдай қолданғаннан кейін пайда болды. [1]
Сондықтан тілдің танымал болуы үшін жақсы болуы міндетті ме, жоқ па, меніңше, тіл жақсы болу үшін танымал болуы керек. Және жақсы болып қалу үшін ол танымал болып қалуы тиіс. Бағдарламалау тілдеріндегі заманауи деңгей бір орында тұрмайды. Дегенмен, біздегі бүгінгі Lisp нұсқалары 1980-жылдардың ортасында MIT-де болған нәрсеге әлі де қатты ұқсайды, өйткені Lisp-тің соңғы рет жеткілікті деңгейде үлкен әрі талапшыл қолданушылар базасы болған кезі сол еді.
Әрине, хакерлер тілді қолдану үшін алдымен ол туралы білуі керек. Олар қайдан естиді? Басқа хакерлерден. Бірақ басқалар ол туралы естуі үшін де тілді қолданып жүрген хакерлердің қандай да бір бастапқы тобы болуы керек. Бұл топ қаншалықты үлкен болуы керек екен; сыни массаны қанша қолданушы құрайды? Ойланбастан айтсам, жиырма дер едім. Егер бір тілдің жеке-жеке жиырма қолданушысы болса, яғни оны қолдануды өз бетінше ұйғарған жиырма қолданушысы болса, мен оны нақты бар деп есептер едім.
Бұған қол жеткізу оңай болмасы анық. Нөлден жиырмаға жету жиырмадан мыңға жеткеннен қиынырақ болса, мен таңғалмас едім. Сол алғашқы жиырма қолданушыны тартудың ең жақсы жолы — трояндық атты қолдану шығар: адамдарға олар қалаған, әрі кездейсоқ жаңа тілде жазылған қолданбаны беру.
2 Сыртқы факторлар
Бағдарламалау тілінің танымалдығына шынымен әсер ететін бір сыртқы факторды мойындаудан бастайық. Танымал болу үшін бағдарламалау тілі танымал жүйенің скрипт тілі болуы керек. Fortran және Cobol алғашқы IBM мейнфреймдерінің скрипт тілдері болды. C тілі Unix жүйесінің, ал кейінірек Perl соның скрипт тілі болды. Tcl — Tk жүйесінің скрипт тілі. Java және Javascript веб-шолғыштардың скрипт тілі болуға арналған.
Lisp аса қатты танымал тіл емес, себебі ол аса қатты танымал жүйенің скрипт тілі емес. Оның әлі де сақталған танымалдығы 1960 және 1970 жылдардан бастау алады, ол кезде ол MIT жүйесінің скрипт тілі болатын. Сол кездегі көптеген ұлы бағдарламашылардың бір кездері MIT-мен байланысы болған. Ал 1970 жылдардың басында, C тіліне дейін, MIT-дің MacLisp деп аталатын Lisp диалектісі байсалды хакер қолданғысы келетін бірден-бір бағдарламалау тілдерінің бірі еді.
Бүгінде Lisp шамалы ғана танымал екі жүйенің — Emacs пен Autocad-тың скрипт тілі болып табылады, сондықтан бүгінде жасалатын Lisp бағдарламалауының көпшілігі Emacs Lisp немесе AutoLisp тілінде жасалады деп шамалаймын.
Бағдарламалау тілдері оқшау өмір сүрмейді. Хакерлік ету (to hack) — сабақты етістік, яғни хакерлер әдетте бір нәрсені хактейді, ал іс жүзінде тілдер нені хактеу үшін қолданылатынына қарап бағаланады. Сондықтан, егер сіз танымал тіл жасағыңыз келсе, сіз не тілден де артық нәрсе ұсынуыңыз керек, не болмаса тіліңізді қолданыстағы қандай да бір жүйенің скрипт тілін алмастыратындай етіп жобалауыңыз қажет.
Common Lisp-тің танымал болмауының бір себебі — оның жетім қалуында. Ол басында хактейтін жүйесімен бірге келген болатын: ол — Lisp Machine. Бірақ Lisp машиналары (параллель компьютерлермен бірге) 1980-жылдары әмбебап процессорлар қуатының артуы салдарынан тас-талқан болды. Common Lisp егер Unix үшін жақсы скрипт тілі болғанда, танымал болып қала берер еді. Өкінішке қарай, ол бұл рөлге мүлде жарамайтын өте жаман тіл болып шықты.
Бұл жағдайды сипаттаудың бір жолы — тіл өзінің жеке артықшылықтарына қарап бағаланбайды деу. Тағы бір көзқарас — бағдарламалау тілі бір нәрсенің скрипт тілі болмаса, ол шын мәнінде бағдарламалау тілі де емес. Бұл күтпеген жағдай болса ғана әділетсіз болып көрінеді. Меніңше, бұл бағдарламалау тілінен, айталық, қандай да бір жүзеге асырылуды (implementation) талап етуден артық әділетсіздік емес. Бұл жай ғана бағдарламалау тілінің табиғатының бір бөлігі.
Әрине, бағдарламалау тіліне жақсы жүзеге асырылым қажет, және ол тегін болуы тиіс. Компаниялар бағдарламалық жасақтама үшін ақша төлейді, ал жеке хакерлер төлемейді, ал сізге дәл сол хакерлерді тарту керек.
Сондай-ақ тіл туралы кітап болуы керек. Кітап жұқа, жақсы жазылған және жақсы мысалдарға толы болуы қажет. Бұл тұрғыда K&R — мінсіз үлгі. Дәл қазір мен тілдің O'Reilly баспасынан шыққан кітабы болуы керек деп айтуға дейін барар едім. Бұл хакерлер үшін маңыздылықтың сынағына айналып келеді.
Сондай-ақ онлайн құжаттама да болуы керек. Шын мәнінде, кітап алдымен онлайн құжаттама ретінде басталуы мүмкін. Бірақ мен физикалық кітаптар әлі ескірді деп ойламаймын. Олардың форматы ыңғайлы, және баспагерлер қоятын де-факто цензура мінсіз болмаса да, пайдалы сүзгі болып табылады. Кітап дүкендері — жаңа тілдер туралы білуге болатын ең маңызды орындардың бірі.
3 Қысқалық
Кез келген тілге қажет үш нәрсені — тегін жүзеге асырылымды, кітапты және хактейтін бірдеңені ұсына аласыз делік, ал хакерлерге ұнайтын тілді қалай жасайсыз?
Хакерлерге ұнайтын бір нәрсе — қысқалық. Хакерлер жалқау келеді, математиктер мен модернист сәулетшілер қалай жалқау болса, олар да солай: олар кез келген артық нәрсені жек көреді. Бағдарлама жазғалы жатқан хакер қай тілді қолдану керектігін, тым болмаса бейсаналы түрде, өзі теруге тиіс таңбалардың жалпы санына қарап шешеді десек, шындықтан алыс кетпейміз. Егер хакерлер тура солай ойламаған күннің өзінде де, тіл жасаушы дәл солай екен деп әрекет еткені абзал.
Ағылшын тіліне ұқсатуға арналған ұзақ-сонар тіркестермен пайдаланушыны мәпелеуге тырысу — қателік. Cobol дәл осы кемшілігімен аты шыққан. Хакер
z = x+y
орнына
add x to y giving z
деп жазуды талап етуді өзінің ақыл-ойына жасалған қорлау мен Құдай алдындағы күнәнің ортасындағы бірдеңе деп қабылдар еді.
Кейде Lisp тілінде car мен cdr орнына first және rest қолданылуы керек, себебі бұл бағдарламаларды оқуды жеңілдетеді деп айтылып жатады. Мүмкін, алғашқы бір-екі сағатта солай шығар. Бірақ хакер car дегеннің тізімнің бірінші элементін, ал cdr қалғанын білдіретінін тез-ақ үйреніп алады. first және rest қолдану теруді 50%-ға көбейтеді. Сондай-ақ олардың ұзындықтары әртүрлі, яғни car мен cdr жиі болатындай қатар келген жолдарда шақырылғанда, аргументтер бір түзудің бойына түспейді. Мен кодтың бетте қалай түзіліп тұрғанының маңызы өте зор екенін байқадым. Lisp коды ені өзгермелі қаріппен жазылғанда, оны әрең оқимын, ал достарым бұл басқа тілдерге де қатысты екенін айтады.
Қысқалық — қатаң типтелген тілдер жеңілетін тұстардың бірі. Барлық басқа жағдайлар тең болғанда, ешкім бағдарламаны үйме-жүйме сипаттамалардан бастағысы келмейді. Астарлы (жасырын) болуы мүмкін кез келген нәрсе солай болуы тиіс.
Жеке токендер де қысқа болуы керек. Perl және Common Lisp бұл сұрақта қарама-қарсы полюстерде орналасқан. Perl бағдарламалары түсініксіз дерлік тығыз болуы мүмкін, ал Common Lisp-тің кірістірілген операторларының атаулары күлкілі дәрежеде ұзын. Common Lisp жасаушылары пайдаланушыларда бұл ұзын атауларды өздері теріп беретін мәтіндік редакторлар болады деп күткен шығар. Бірақ ұзын атаудың құны оны жай ғана теру құнымен шектелмейді. Оны оқу құны және экранда алатын орнының да құны бар.
4 Хактеуге икемділік
Хакер үшін қысқалықтан да маңыздырақ бір нәрсе бар: ол — қалаған нәрсесін істей алу мүмкіндігі. Бағдарламалау тілдерінің тарихында бағдарламашыларға орынсыз деп саналған нәрселерді істетпеуге таңқаларлықтай көп күш жұмсалды. Бұл — қауіпті әрі өркөкірек жоспар. Бағдарламашыға не істеу керек болатынын тіл жасаушы қайдан білсін? Меніңше, тіл жасаушылар өздерінің мақсатты пайдаланушысын өзін-өзі қорғауды қажет ететін ебедейсіз біреу деп емес, өздері ешқашан күтпеген нәрселерді істеуге мұқтаж болатын данышпан деп санағаны дұрысырақ болар еді. Ебедейсіз адам бәрібір өз аяғына өзі оқ атады. Сіз оны басқа пакеттегі айнымалыларға жүгінуден құтқарарсыз, бірақ қате мәселені шешу үшін нашар жобаланған бағдарлама жазып, оған шексіз көп уақыт кетіруінен құтқара алмайсыз.
Жақсы бағдарламашылар жиі қауіпті әрі жағымсыз нәрселерді істегісі келеді. Жағымсыз деп мен тіл ұсынуға тырысып жатқан қандай да бір семантикалық қасбеттің тасасына өтуді айтамын: мысалы, қандай да бір жоғары деңгейлі абстракцияның ішкі көрінісіне қол жеткізу. Хакерлер хактегенді ұнатады, ал хактеу дегеніміз — ішкі жағына үңілу және бастапқы жасаушының шешімін күмәнге алып, өзінше жасау.
Өз шешіміңізді түзетуге жол беріңіз. Кез келген құрал жасаған кезде, адамдар оны сіз ойламаған жолдармен пайдаланады, және бұл бағдарламалау тілі сияқты өте күрделі құралға ерекше қатысты. Көптеген хакерлер сіздің семантикалық моделіңізді сіз ешқашан ойламаған түрде өзгерткісі келеді. Менің айтарым: оларға ерік беріңіз; қоқыс жинағыш (garbage collector) сияқты орындалу жүйелеріне қауіп төндірмей, бағдарламашыға мүмкіндігінше көп ішкі дүниеге қол жеткізуге рұқсат етіңіз.
Common Lisp-те мен құрылымның (struct) өрістерін жиі аралап шыққым келетін — мысалы, жойылған нысанға сілтемелерді тазарту немесе инициализацияланбаған өрістерді табу үшін. Мен бұл құрылымдардың астында жай векторлар жатқанын білемін. Дегенмен мен кез келген құрылымда шақыра алатын әмбебап функция жаза алмаймын. Мен өрістерге тек аты бойынша ғана қол жеткізе аламын, өйткені құрылымның мәні солай болуы керек деп ұйғарылған.
Хакер үлкен бағдарламада заттардың белгіленген моделін бір немесе екі рет қана бұзғысы келуі мүмкін. Бірақ соны істей алу мүмкіндігі қандай үлкен айырмашылық тудырады десеңізші. Және бұл жай ғана мәселені шешуден де артық болуы мүмкін. Мұнда да өзіндік бір рақат бар. Хакерлер хирургтың қорқынышты ішкі органдарды ақтарғандағы жасырын рақатын, жасөспірімнің безеуді сыққандағы жасырын рақатын бөліседі. [2] Әйтеуір ұлдар үшін қорқыныштың кейбір түрлері қызықты болып келеді. Maxim журналы постер-сұлулар мен қорқынышты апаттар араласқан фотосуреттердің жыл сайынғы томын шығарады. Олар өз аудиториясын біледі.
Тарихи тұрғыдан алғанда, Lisp хакерлерге өз дегенін істеуге мүмкіндік беруде жақсы болды. Common Lisp-тің саяси дұрыстығы — қалыптан ауытқу. Алғашқы Lisp нұсқалары барлық нәрсеге қол сұғуға мүмкіндік беретін. Сол рухтың едәуір бөлігі, бақытымызға орай, макростарда сақталған. Бастапқы кодқа кез келген өзгертулер енгізе алу қандай керемет нәрсе.
Классикалық макростар — нағыз хакердің құралы: қарапайым, қуатты және қауіпті. Олардың не істейтінін түсіну өте оңай: сіз макростың аргументтерінде функцияны шақырасыз және ол не қайтарса, соның бәрі макрос шақыруының орнына қойылады. Гигиеналық макростар (hygienic macros) бұған қарама-қарсы қағидатты ұстанады. Олар сізді олардың не істеп жатқанын түсінуден қорғауға тырысады. Мен гигиеналық макростардың бір сөйлеммен түсіндірілгенін ешқашан естіген емеспін. Және олар — бағдарламашылардың нені қалауына рұқсат етілгенін шешудің қауіптілігінің классикалық мысалы. Гигиеналық макростар мені, басқалармен қатар, айнымалыны басып алудан (variable capture) қорғауға арналған, бірақ айнымалыны басып алу — кейбір макростарда дәл менің қалайтын нәрсем.
Шынымен жақсы тіл әрі таза, әрі лас болуы керек: жақсы түсінікті және өте ортогоналды операторлардың шағын ядросымен таза жобаланған, бірақ хакерлерге оны өз қалауынша қолдануға мүмкіндік беретін мағынада лас. C тілі осындай. Алғашқы Lisp нұсқалары да сондай болды. Нағыз хакердің тілінде әрқашан аздап бұзақы мінез болады.
Жақсы бағдарламалау тілінде «бағдарламалық инженерия» деген сөз тіркесін қолданатын адамдарды жақтырмай басын шайқауға мәжбүр ететін мүмкіндіктер болуы тиіс. Континуумның екінші шетінде Ada және Pascal сияқты тілдер тұр, олар — оқытуға ғана жақсы, басқа ештеңеге жарамайтын әдептілік үлгілері.
5 Бір реттік бағдарламалар
Хакерлерді қызықтыру үшін тіл олар жазғысы келетін бағдарлама түрлерін жазуға ыңғайлы болуы керек. Ал бұл, таңқаларлық болуы мүмкін, бір реттік бағдарламаларды жазуға ыңғайлы болуы керек дегенді білдіреді.
Бір реттік бағдарлама — бұл қандай да бір шағын тапсырма үшін тез жазатын бағдарламаңыз: қандай да бір жүйелік әкімшілендіру тапсырмасын автоматтандыруға, модельдеуге арналған сынақ деректерін жасауға немесе деректерді бір форматтан екінші форматқа түрлендіруге арналған бағдарлама. Бір реттік бағдарламалардың таңқаларлық ерекшелігі — Екінші дүниежүзілік соғыс кезінде көптеген америкалық университеттерде салынған «уақытша» ғимараттар сияқты, олар көбінесе лақтырылмай қалады. Көбі нақты мүмкіндіктері мен нақты қолданушылары бар нақты бағдарламаларға айналады.
Менің ойымша, ең жақсы үлкен бағдарламалар Гувер бөгеті сияқты басынан бастап үлкен болып жобаланбай, өмірін дәл осылай бастайды. Нөлден үлкен нәрсе құру — қорқынышты. Адамдар тым үлкен жобаны қолға алғанда, олар абдырап қалады. Жоба не тұралап қалады, не оның нәтижесі жансыз әрі жасанды болып шығады: нағыз қала орталығының орнына сауда орталығы, Римнің орнына Бразилиа, C тілінің орнына Ada сияқты.
Үлкен бағдарламаға қол жеткізудің тағы бір жолы — бір реттік бағдарламадан бастап, оны үнемі жетілдіріп отыру. Бұл тәсіл соншалықты қорқынышты емес, және бағдарламаның дизайны эволюцияның пайдасын көреді. Меніңше, егер зерттеп қараса, үлкен бағдарламалардың көпшілігі дәл осылай дамығаны анықталар еді. Ал осылай дамығандар, бәлкім, әлі күнге дейін алғаш қай тілде жазылса, сонда қалып қойған, себебі саяси себептер болмаса, бағдарламаның басқа тілге көшірілуі сирек кездеседі. Сондықтан, парадоксальды түрде, егер сіз үлкен жүйелер үшін қолданылатын тіл жасағыңыз келсе, оны бір реттік бағдарламаларды жазуға ыңғайлы етуіңіз керек, өйткені үлкен жүйелер дәл солардан бастау алады.
Perl — бұл идеяның жарқын мысалы. Ол бір реттік бағдарламаларды жазу үшін ғана жобаланып қойған жоқ, оның өзі де негізінен бір реттік бағдарлама болатын. Perl өмірін есептер жасауға арналған утилиталар жиынтығы ретінде бастады және адамдар оған жазған бір реттік бағдарламалар ұлғайған сайын ғана бағдарламалау тіліне айналды. Тек Perl 5-ке дейін ғана (егер сол кезде болса) бұл тіл байсалды бағдарламалар жазуға жарамды болды, бірақ соған қарамастан ол бұған дейін-ақ аса танымал болып үлгерген еді.
Тілді бір реттік бағдарламалар үшін не жақсы етеді? Бастау үшін, ол оңай қолжетімді болуы керек. Бір реттік бағдарлама — бұл сіз бір сағатта жазып тастаймын деп күтетін нәрсе. Сондықтан бұл тіл сіз қолданып отырған компьютерде әлдеқашан орнатылған болуы тиіс. Ол қолданар алдында орнату керек болатын нәрсе болмауы керек. Ол дайын тұруы тиіс. C тілі операциялық жүйемен бірге келгендіктен сонда болды. Perl сол жерде болды, өйткені ол бастапқыда жүйелік әкімшілерге арналған құрал еді, ал сіздің әкімшіңіз оны әлдеқашан орнатып қойған болатын.
Дегенмен қолжетімді болу тек орнатылған болудан да көп нәрсені білдіреді. Командалық жол интерфейсі бар интерактивті тіл, бөлек компиляциялап, орындау керек болатын тілге қарағанда қолжетімдірек. Танымал бағдарламалау тілі интерактивті болуы және жылдам іске қосылуы керек.
Бір реттік бағдарламада қалайтын тағы бір нәрсе — қысқалық. Қысқалық хакерлерді әрқашан қызықтырады, әсіресе олар бір сағатта бітіруді көздеген бағдарламада бұл тіптен маңызды.
6 Кітапханалар
Әрине, қысқалықтың шыңы — бағдарламаның сіз үшін алдын ала жазылып қойылуы және сіздің оны жай ғана шақыруыңыз. Және бұл бізді бағдарламалау тілдерінің барған сайын маңызды бола түсетін қасиетіне әкеледі: кітапханалық функциялар. Perl жолдармен жұмыс істеуге арналған үлкен кітапханаларының арқасында ұтады. Кітапханалық функциялардың бұл класы көбінесе деректерді түрлендіру немесе бөліп алу үшін жазылатын бір реттік бағдарламалар үшін өте маңызды. Көптеген Perl бағдарламалары бір-біріне жалғанған бірнеше кітапханалық шақыру ретінде ғана басталатын шығар.
Менің ойымша, алдағы елу жылда бағдарламалау тілдерінде болатын көптеген жетістіктер кітапханалық функциялармен байланысты болады. Меніңше, болашақ бағдарламалау тілдерінің кітапханалары негізгі тіл сияқты мұқият жобаланатын болады. Бағдарламалау тілінің дизайны тіліңізді қатаң немесе әлсіз типтелген, немесе объектіге бағытталған, немесе функционалды, не болмаса басқаша ету туралы емес, керемет кітапханаларды қалай жобалау туралы болады. Типтер жүйесін қалай жобалау керектігі туралы ойлауды ұнататын тіл жасаушылар бұған тіксінуі мүмкін. Бұл қолданбалы бағдарламалар жазумен бірдей дерлік қой! Өкінішті. Тілдер бағдарламашылар үшін арналған, ал кітапханалар — бағдарламашыларға қажет нәрсе.
Жақсы кітапханаларды жобалау қиын. Бұл жай ғана көп код жазу мәселесі емес. Кітапханалар тым үлкен болып кеткен соң, кейде қажетті функцияны табу кодты өзіңіз жазғаннан гөрі көбірек уақыт алуы мүмкін. Кітапханалар негізгі тіл сияқты ортогоналды операторлардың шағын жиынтығын қолдана отырып жобалануы керек. Бағдарламашы қандай кітапханалық шақыру оның қажетін орындайтынын болжай алатындай болуы тиіс.
Кітапханалар — Common Lisp-тің кемшін түсетін тұстарының бірі. Жолдармен жұмыс істеуге арналған қарапайым ғана кітапханалар бар, ал операциялық жүйемен байланысуға арналған кітапханалар жоқтың қасы. Тарихи себептерге байланысты Common Lisp ОЖ мүлде жоқ сияқты кейіп танытуға тырысады. ОЖ-мен байланыса алмағандықтан, тек Common Lisp-тің кірістірілген операторларын қолданып байсалды бағдарлама жаза алуыңыз екіталай. Сізге белгілі бір жүзеге асырылымға тән амалдарды да қолдануға тура келеді, ал іс жүзінде олар сіз қалағанның бәрін бере бермейді. Егер Common Lisp-те қуатты жол кітапханалары мен жақсы ОЖ қолдауы болса, хакерлер Lisp туралы әлдеқайда жоғары пікірде болар еді.
7 Синтаксис
Lisp синтаксисі бар, дәлірек айтқанда, синтаксисі жоқ тіл қашан да болсын танымал бола ала ма? Мен бұл сұрақтың жауабын білмеймін. Дегенмен менің ойымша, Lisp-тің қазір танымал еместігінің басты себебі синтаксис емес. Common Lisp-те бейтаныс синтаксистен де өткен үлкен мәселелер бар. Мен префикстік синтаксисті еркін меңгерген, бірақ әдепкі бойынша Perl-ді қолданатын бірнеше бағдарламашыны білемін, өйткені онда қуатты жол кітапханалары бар және ол ОЖ-мен байланыса алады.
Префикстік нотацияда екі ықтимал мәселе бар: оның бағдарламашыларға бейтаныс болуы және жеткілікті тығыз болмауы. Lisp әлеміндегі қалыптасқан түсінік бойынша, бірінші мәселе нақты проблема болып саналады. Мен бұған онша сенімді емеспін. Иә, префикстік нотация қарапайым бағдарламашыларды дүрліктіреді. Бірақ меніңше, қарапайым бағдарламашылардың пікірі маңызды емес. Тілдер сарапшы хакерлер олар туралы не ойлайтынына байланысты танымал немесе танымал емес болады, ал сарапшы хакерлер префикстік нотацияны игере алар еді деп ойлаймын. Perl синтаксисі өте түсініксіз болуы мүмкін, бірақ бұл Perl-дің танымалдығына кедергі болған жоқ. Керісінше, бұл белгілі бір дәрежеде Perl табынушылығын қалыптастыруға көмектескен де болар.
Неғұрлым байсалды мәселе — префикстік нотацияның шашыраңқылығы. Сарапшы хакерлер үшін бұл шынымен де мәселе. Ешкім a[x,y] деп жазуға болатын жерде (aref a x y) деп жазғысы келмейді.
Бұл нақты жағдайда мәселеден шебер шығудың бір жолы бар. Егер біз деректер құрылымдарын индекстер бойынша функциялар сияқты қарастырсақ, оның орнына (a x y) деп жаза аламыз, бұл тіпті Perl түрінен де қысқарақ болады. Осыған ұқсас тәсілдер өрнектердің басқа түрлерін де қысқартуы мүмкін.
Шегіністі мәнді ету арқылы біз жақшалардың көбінен құтыла аламыз (немесе оларды міндетті емес ете аламыз). Бағдарламашылар кодты бәрібір солай оқиды: шегініс бір нәрсені, ал шектеуіштер басқа нәрсені көрсеткенде, біз шегініске қараймыз. Шегіністі мәнді деп қарастыру қателердің осы жиі кездесетін көзін жойып қана қоймай, бағдарламаларды қысқарта түсер еді.
Кейде инфикстік синтаксисті оқу оңайырақ. Бұл әсіресе математикалық өрнектерге қатысты. Мен бүкіл бағдарламашылық өмірімде Lisp-ті қолданып келемін, және әлі күнге дейін префикстік математикалық өрнектерді табиғи деп санамаймын. Дегенмен, әсіресе код жасайтын кезде, кез келген мөлшердегі аргументтерді қабылдайтын операторлардың болуы ыңғайлы. Сондықтан бізде инфикстік синтаксис болатын болса, ол қандай да бір оқу макросы (read-macro) ретінде жүзеге асырылғаны жөн шығар.
Lisp-ке синтаксис енгізуге фанатикалық түрде қарсы болмауымыз керек деп ойлаймын, егер ол түсінікті түрде негізгі s-өрнектерге аударылатын болса болғаны. Lisp-те онсыз да синтаксис көп. Оны көбірек енгізу міндетті түрде жаман емес, егер ешкім оны қолдануға мәжбүрленбесе. Common Lisp-те кейбір шектеуіштер тіл үшін сақталып қойылған, бұл тіл жасаушылардың кем дегенде кейбіреуі болашақта көбірек синтаксис енгізуді көздегенін аңғартады.
Common Lisp-тегі lisp-тік сипатқа мүлде сай келмейтін ең сорақы синтаксис үзінділерінің бірі формат жолдарында (format strings) кездеседі; format — өз алдына жеке тіл, және бұл тіл Lisp емес. Егер Lisp-ке көбірек синтаксис енгізу жоспары болса, format спецификаторларын соның ішіне қосуға болар еді. Макростар кез келген басқа кодты жасайтыны сияқты format спецификаторларын да жасай алса, керемет болар еді.
Бір көрнекті Lisp хакері маған өзінің CLTL кітабы format бөліміне келгенде өздігінен ашылып кететінін айтты. Менікі де солай. Бұл, бәлкім, жақсартуға орын бар екенін көрсететін шығар. Бұл сондай-ақ бағдарламалардың енгізу/шығарумен (I/O) көп айналысатынын да білдіруі мүмкін.
8 Тиімділік
Жақсы тіл, бәрі білетіндей, жылдам код жасауы керек. Бірақ іс жүзінде жылдам код ең алдымен тіл дизайнында жасайтын нәрселеріңізден пайда болады деп ойламаймын. Кнут әлдеқашан атап өткендей, жылдамдық тек белгілі бір аса маңызды тар жерлерде (bottlenecks) ғана мәнге ие. Ал содан бері көптеген бағдарламашылар байқағандай, адам бұл тар жерлердің қайда екені туралы өте жиі қателеседі.
Сонымен, іс жүзінде, жылдам код алудың жолы тілді қатаң типтелген қылудан гөрі, өте жақсы профилировщикке ие болу болып табылады. Бағдарламадағы әрбір шақырудағы әрбір аргументтің типін білудің қажеті жоқ. Сізге тек тар жерлердегі (bottlenecks) аргументтердің типтерін көрсете алу мүмкіндігі қажет. Одан да маңыздысы, сол тар жерлердің қайда екенін анықтай білу керек.
Адамдардың Lisp-ке қатысты бір шағымы — ненің қымбатқа түсетінін (ресурс тұрғысынан) айтудың қиындығы. Бұл рас болуы мүмкін. Егер сіз өте абстрактілі тілге ие болғыңыз келсе, бұл сөзсіз болатын да шығар. Қалай болғанда да, жақсы профилирлеу бұл мәселені шешуге үлкен көмек берер еді: сіз ненің қымбат екенін тез үйреніп алар едіңіз.
Мұндағы мәселенің бір бөлігі әлеуметтік сипатта. Тіл жасаушылар жылдам компиляторлар жазғанды ұнатады. Олар өз шеберліктерін осылай өлшейді. Олар профилировщикті ең жақсы дегенде қосымша құрал ретінде көреді. Бірақ іс жүзінде жақсы профилировщик сол тілде жазылған нақты бағдарламалардың жылдамдығын арттыруға, жылдам код жасайтын компилятордан қарағанда көбірек үлес қоса алады. Мұнда да тіл жасаушылар өз пайдаланушыларынан біршама алшақтап кеткен. Олар сәл басқа, бұрысырақ мәселені өте жақсы шешіп жүр.
Белсенді профилировщиктің болуы жақсы идея болар еді — бағдарламашының сұрауын күтпей, өнімділік туралы деректерді оған өзі ұсынып отыратын. Мысалы, редактор бағдарламашы бастапқы кодты өңдеп жатқан кезде тар жерлерді қызыл түспен көрсете алар еді. Тағы бір тәсіл — орындалып жатқан бағдарламаларда не болып жатқанын қандай да бір түрде бейнелеу. Бұл әсіресе серверлік қосымшаларда үлкен ұтыс берер еді, өйткені онда бақылайтын көптеген іске қосулы бағдарламалар бар. Белсенді профилировщик бағдарлама орындалып жатқан кезде жадта не болып жатқанын графикалық түрде көрсете алар еді немесе тіпті не болып жатқанын білдіретін дыбыстар шығара алар еді.
Дыбыс — мәселелерді білдіретін жақсы белгі. Мен жұмыс істеген бір жерде біздің веб-серверлерімізде не болып жатқанын көрсететін үлкен циферблат тақтасы болды. Тілшелер бұрылған кезде аздап дыбыс шығаратын кішкентай сервомоторлармен қозғалатын. Мен үстелімнен тақтаны көре алмайтынмын, бірақ серверде ақау болған кезде дыбысынан бірден біле алатынымды байқадым.
Тиімсіз алгоритмдерді автоматты түрде анықтайтын профилировщик жазу да мүмкін болуы ықтимал. Жадқа қол жеткізудің белгілі бір үлгілері нашар алгоритмдердің анық белгісі болып шықса, мен таңғалмас едім. Егер компьютердің ішінде біздің бағдарламаларымызды орындайтын кішкентай бір адам жүгіріп жүрсе, ол өз жұмысы туралы федералды үкімет қызметкері сияқты ұзақ әрі мұңды әңгіме айтар еді. Менде көбіне процессорды бос әурешілікке жіберіп жатқандай сезім болады, бірақ оның не істеп жатқанын көрудің жақсы тәсілі ешқашан болған емес.
Қазіргі бірқатар Lisp нұсқалары байт-кодқа компиляцияланады, содан кейін оны интерпретатор орындайды. Бұл әдетте жүзеге асыруды басқа жүйелерге тасымалдауды жеңілдету үшін жасалады, бірақ бұл тілдің пайдалы мүмкіндігі болуы мүмкін. Байт-кодты тілдің ресми бөлігіне айналдырып, бағдарламашыларға тар жерлерде кірістірілген (inline) байт-кодты пайдалануға рұқсат беру жақсы идея болар еді. Онда мұндай оңтайландырулар да тасымалданатын болар еді.
Соңғы пайдаланушы сезінетін жылдамдықтың табиғаты өзгеруі мүмкін. Серверлік қосымшалардың көбеюімен барған сайын көбірек бағдарламалар енгізу/шығаруға (i/o-bound) тәуелді болып қалуы мүмкін. Енгізу/шығаруды жылдам етудің мәні зор болады. Тіл бұған қарапайым, жылдам, пішімделген шығару функциялары сияқты тікелей шаралармен де, сондай-ақ кэштеу және тұрақты нысандар (persistent objects) сияқты терең құрылымдық өзгерістермен де көмектесе алады.
Пайдаланушыларды жауап беру уақыты қызықтырады. Бірақ тиімділіктің тағы бір түрі барған сайын маңызды бола түседі: бір процессорға шаққанда қолдау көрсете алатын бір мезгілдегі пайдаланушылар саны. Жақын болашақта жазылатын қызықты қосымшалардың көбі серверлік болады және бір серверге келетін пайдаланушылар саны мұндай қосымшаларды орналастыратын кез келген адам үшін маңызды сұрақ болып табылады. Серверлік қосымшаны ұсынатын бизнестің күрделі шығындарында бұл — бөлгіш сан.
Көптеген жылдар бойы тиімділік соңғы пайдаланушы қосымшаларының көпшілігінде айтарлықтай маңызды болған жоқ. Әзірлеушілер әрбір пайдаланушының үстелінде барған сайын қуатты процессор тұрады деп сене алды. Ал Паркинсон заңы бойынша, бағдарламалық жасақтама қолжетімді ресурстарды пайдалану үшін ұлғайып отырды. Серверлік қосымшалармен бұл жағдай өзгереді. Ол әлемде аппараттық құрал мен бағдарламалық жасақтама бірге қамтамасыз етіледі. Серверлік қосымшаларды ұсынатын компаниялар үшін бір серверге қанша пайдаланушыға қолдау көрсете алатыны түпкілікті кіріске өте үлкен әсер етеді.
Кейбір қосымшаларда процессор шектеуші фактор болады және орындалу жылдамдығы оңтайландыру қажет ең маңызды нәрсеге айналады. Бірақ көбінесе жад шектеу болады; бір мезгілдегі пайдаланушылар саны әр пайдаланушының деректері үшін қажет жад көлемімен анықталады. Тіл бұл жерде де көмектесе алады. Ағындарды (threads) жақсы қолдау барлық пайдаланушыларға ортақ үйіндіні (heap) бөлісуге мүмкіндік береді. Сондай-ақ тұрақты нысандардың және/немесе жалқау жүктеуді (lazy loading) тіл деңгейінде қолдаудың да пайдасы тиюі мүмкін.
9 Уақыт
Танымал тілге қажет соңғы құрамдас — бұл уақыт. Көптеген бағдарламалау тілдері сияқты жоғалып кетуі мүмкін тілде ешкім бағдарлама жазғысы келмейді. Сондықтан көптеген хакерлер тілді пайдалануды қарастырмас бұрын оның бірнеше жыл өмір сүруін күтуге бейім болады.
Керемет жаңа дүниелерді ойлап табушылар мұны білгенде жиі таңғалады, бірақ кез келген хабарламаны адамдарға жеткізу үшін сізге уақыт керек. Менің бір досым біреу одан бірдеңе сұрағанда бірінші ретте сирек істейді. Ол адамдардың кейде өздеріне қажет емес нәрселерді сұрайтынын біледі. Уақытын босқа өткізбеу үшін ол бір нәрсені істеуді үшінші немесе төртінші рет сұрағанша күтеді; сол уақытқа дейін одан сұраған адам біршама ренжіп қалуы мүмкін, бірақ кем дегенде олар сұраған нәрсесін шынымен қалайтын шығар.
Көптеген адамдар өздері еститін жаңа нәрселерге осындай сүзгіден өткізуді қолдануды үйренген. Олар бірдеңе туралы он рет естімейінше, тіпті назар аудара бастамайды. Олардікі әбден орынды: жаңа шыққан «хит» дүниелердің басым бөлігі уақытты босқа кетіру болып шығады және ақырында жоқ болады. VRML-ді үйренуді кейінге қалдыру арқылы мен оны мүлдем үйренбеуге қол жеткіздім.
Сондықтан жаңа нәрсе ойлап тапқан кез келген адам өз хабарын адамдар түсіне бастағанға дейін жылдар бойы қайталауға дайын болуы керек. Біз, менің білуімше, алғашқы веб-серверге негізделген қосымшаны жаздық және оны жүктеп алудың қажеті жоқ екенін адамдарға жеткізу үшін бізге жылдар қажет болды. Олар ақымақ болғандықтан емес. Олар жай ғана бізден ажыратылып, елемей жүрді.
Жақсы жаңалық — қарапайым қайталау мәселені шешеді. Сізге тек өз әңгімеңізді айта беру керек, сонда ақырында адамдар ести бастайды. Адамдар сіздің бар екеніңізді байқаған кезде емес, сіздің әлі де бар екеніңізді байқаған кезде назар аударады.
Қарқын алу үшін әдетте біраз уақыт кетуі тіпті жақсы. Көптеген технологиялар алғаш іске қосылғаннан кейін де айтарлықтай дамиды — әсіресе бағдарламалау тілдері. Жаңа технология үшін алғашқы бірнеше жылда тек ерте қабылдаушылардың (early adopters) шағын тобы ғана қолданғанынан артық ештеңе жоқ. Ерте қабылдаушылар — талғампаз әрі талапшыл, олар технологияңызда қалған кез келген кемшіліктерді тез арада анықтайды. Пайдаланушыларыңыз аз болған кезде, олардың барлығымен тығыз байланыста бола аласыз. Сондай-ақ, ерте қабылдаушылар жүйені жетілдірген кезде, тіпті бұл кейбір ақауларға әкелсе де, түсіністікпен қарайды.
Жаңа технологияның енгізілуінің екі жолы бар: органикалық өсу әдісі және «үлкен жарылыс» (big bang) әдісі. Органикалық өсу әдісінің мысалы ретінде қаражаты жеткіліксіз, бар күшін салып жұмыс істейтін классикалық гараждық стартапты келтіруге болады. Ешкімге беймәлім екі жігіт жаңа технология жасайды. Олар оны ешқандай маркетингсіз іске қосады және бастапқыда тек бірнеше (фанаттық түрде берілген) пайдаланушылары болады. Олар технологияны жетілдіруді жалғастырады, ал бұл арада олардың пайдаланушылар базасы ауызша таралу арқылы өседі. Өздері байқамай-ақ, олар үлкенге айналады.
Екінші тәсіл, «үлкен жарылыс» әдісі, венчурлық қорлармен қаржыландырылатын, қатты жарнамаланатын стартаппен сипатталады. Олар өнімді жылдам жасап шығаруға асығады, оны үлкен жарнамамен іске қосады және бірден (олар үміттенгендей) үлкен пайдаланушылар базасына ие болады.
Әдетте, гараждағы жігіттер «үлкен жарылыс» жігіттеріне қызғанышпен қарайды. «Үлкен жарылыс» жігіттері сымбатты, өзіне сенімді және венчурлық инвесторлардың құрметіне ие. Олар барлық нәрсенің ең жақсысын ала алады, ал іске қосу айналасындағы PR-науқан оларды танымал етудің қосымша әсерін береді. Гаражында отырған органикалық өсу жігіттері өздерін кедей әрі ешкімге керексіз сезінеді. Дегенмен, олардың өздеріне жаны ашуы көбіне қате деп ойлаймын. Органикалық өсу «үлкен жарылыс» әдісіне қарағанда жақсырақ технология мен байырақ негізін қалаушыларды беретін сияқты. Егер сіз бүгінгі таңда үстемдік етіп отырған технологияларға қарасаңыз, олардың көпшілігі органикалық түрде өскенін көресіз.
Бұл заңдылық тек компанияларға ғана қатысты емес. Мұны демеушілікпен қаржыландырылатын зерттеулерден де көруге болады. Multics пен Common Lisp «үлкен жарылыс» жобалары болды, ал Unix пен MacLisp органикалық өсу жобалары еді.
10 Қайта жобалау
«Ең жақсы жазу — бұл қайта жазу», — деп жазған Э. Б. Уайт. Мұны кез келген жақсы жазушы біледі және бұл бағдарламалық жасақтамаға да қатысты. Дизайнның ең маңызды бөлігі — қайта жобалау (redesign). Әсіресе бағдарламалау тілдері жеткілікті түрде қайта жобаланбайды.
Жақсы бағдарламалық жасақтама жазу үшін басыңызда бір уақытта екі қарама-қарсы ойды ұстауыңыз керек. Сізге жас хакердің өз қабілетіне деген аңғал сенімі және сонымен бірге ардагердің күмәні қажет. Сіз миыңыздың бір жартысымен мұның несі қиын болуы мүмкін? деп ойлай білуіңіз керек, ал екінші жартысымен бұл ешқашан жұмыс істемейді деп ойлауыңыз керек.
Мұндағы басты мәселе — бұл жерде ешқандай нақты қайшылық жоқ екенін түсіну. Сіз екі түрлі нәрсеге қатысты оптимистік және күмәнді болғыңыз келеді. Сіз мәселені шешу мүмкіндігіне оптимистік көзқараспен қарауыңыз керек, бірақ осы уақытқа дейін қол жеткізген кез келген шешімнің құндылығына күмәнмен қарауыңыз керек.
Жақсы жұмыс істейтін адамдар көбінесе өздерінің жасап жатқан ісін түкке тұрғысыз деп ойлайды. Басқалар олардың жасағанын көріп, таңғалады, бірақ оны жасаушы алаңдаушылыққа толы болады. Бұл заңдылық кездейсоқ емес: жұмысты жақсы еткен дәл сол алаңдаушылық.
Егер сіз үміт пен уайымды тепе-теңдікте ұстай алсаңыз, олар екі аяғыңыз велосипедті алға қалай жылжытса, жобаны да солай алға тартады. Екі тактілі инновациялық қозғалтқыштың бірінші кезеңінде сіз оны шеше алатыныңызға деген сенімнен шабыттанып, қандай да бір мәселе бойынша жанкешті жұмыс істейсіз. Екінші кезеңде сіз жасаған ісіңізге таңғы суық ақылмен қарап, оның барлық кемшіліктерін анық көресіз. Бірақ сыни көзқарасыңыз үмітіңізден басым түспесе, сіз өзіңіздің толық емес жүйеңізге қарап: «қалған жолды жүріп өтудің несі қиын болуы мүмкін?» деп ойлап, циклді жалғастыра аласыз.
Екі күшті тепе-теңдікте ұстау қиын. Жас хакерлерде оптимизм басым болады. Олар бір нәрсе шығарады, оның тамаша екеніне сенеді және оны ешқашан жақсартпайды. Егде хакерлерде күмән басым болады және олар тіпті өршіл жобаларды қолға алуға батпайды.
Қайта жобалау циклін жалғастыру үшін қолдан келетін кез келген әрекет жақсы. Қара сөзді өзіңізге ұнағанша қайта-қайта жазуға болады. Бірақ бағдарламалық жасақтама, әдетте, жеткілікті түрде қайта жобаланбайды. Қара сөздің оқырмандары бар, бірақ бағдарламалық жасақтаманың пайдаланушылары бар. Егер жазушы эссені қайта жазса, ескі нұсқаны оқыған адамдар жаңадан енгізілген үйлесімсіздіктен олардың ойлары бұзылды деп шағымдануы екіталай.
Пайдаланушылар — екі жүзді қылыш. Олар тіліңізді жақсартуға көмектесе алады, бірақ сонымен бірге оны жақсартуға кедергі де келтіруі мүмкін. Сондықтан пайдаланушыларыңызды мұқият таңдаңыз және олардың санын баяу өсіріңіз. Пайдаланушылардың болуы оңтайландыру сияқты: оны кейінге қалдыру — ақылды қадам. Сондай-ақ, жалпы ереже бойынша, сіз кез келген уақытта ойлағаныңыздан да көп өзгеріс енгізе аласыз. Өзгеріс енгізу таңғышты жұлып алған сияқты: ауырсынуды сезінген бойда ол естелікке айналады.
Тілдің комитет тарапынан жобалануы жақсы идея емес екенін бәрі біледі. Комитеттер нашар дизайн жасайды. Бірақ менің ойымша, комитеттердің ең жаман қаупі — олардың қайта жобалауға кедергі келтіруінде. Өзгерістер енгізу соншалықты көп еңбекті талап ететіні сонша, ешкімнің мазасы келгісі келмейді. Комитет нені шешсе де, тіпті мүшелердің көпшілігіне ұнамаса да, сол күйінде қалуға бейім болады.
Тіпті екі адамнан тұратын комитет те қайта жобалауға кедергі жасайды. Бұл әсіресе екі түрлі адам жазған бағдарламалық жасақтама бөліктері арасындағы интерфейстерде орын алады. Интерфейсті өзгерту үшін екеуі де оны бір уақытта өзгертуге келісуі керек. Сондықтан интерфейстер мүлдем өзгермеуге бейім, бұл мәселе, себебі олар кез келген жүйенің ең бейберекет бөліктерінің бірі болып табылады.
Мұндағы бір шешім — интерфейстерді тік емес, көлденең болатындай етіп жүйелерді жобалау болуы мүмкін, яғни модульдер әрқашан абстракцияның тігінен жиналған қабаттары болсын. Онда интерфейс солардың біріне тиесілі болады. Екі деңгейдің төменгісі не жоғарғысы жазылған тіл болады (бұл жағдайда төменгі деңгей интерфейске иелік етеді), немесе ол бағынышты болады (бұл жағдайда интерфейсті жоғарғы деңгей белгілей алады).
11 Lisp
Мұның бәрі жаңа Lisp үшін үміт бар екенін білдіреді. Хакерлерге қалағанын беретін кез келген тіл үшін үміт бар, соның ішінде Lisp үшін де. Хакерлерді Lisp-тің оғаштығы шошытады деп ойлау арқылы біз қателескен шығармыз. Бұл жұбанышты елес бізге Lisp-тегі, немесе кем дегенде Common Lisp-тегі нақты мәселені көруге кедергі келтірген болуы мүмкін, ол мәселе — оның хакерлер істегісі келетін нәрселерді жасау үшін нашарлығы. Хакерлік тілге қуатты кітапханалар және хакерлік әрекеттер жасайтын бірдеңе керек. Common Lisp-те екеуі де жоқ. Хакерлік тіл ықшам және оңай өзгертуге келетін (hackable) болады. Common Lisp олай емес.
Жақсы жаңалық — жаман болып тұрған Lisp емес, Common Lisp. Егер біз нағыз хакерлік тіл болатын жаңа Lisp жасай алсақ, менің ойымша, хакерлер оны пайдаланатын болады. Олар жұмысты орындайтын кез келген тілді пайдаланады. Бізге тек осы жаңа Lisp-тің басқа тілдерге қарағанда қандай да бір маңызды жұмысты жақсырақ орындайтынына көз жеткізу жеткілікті.
Тарих біраз үміт береді. Уақыт өте келе, бірінен соң бірі шыққан жаңа бағдарламалау тілдері Lisp-тен көбірек мүмкіндіктерді ала бастады. Сіз жасаған тіл Lisp-ке айналғанға дейін көшіретін көп нәрсе қалған жоқ. Соңғы танымал тіл Python — инфикстік синтаксисі бар және макростары жоқ сұйылтылған Lisp. Жаңа Lisp осы ілгерілеудің табиғи қадамы болар еді.
Мен кейде оны Python-ның жақсартылған нұсқасы деп атау жақсы маркетингтік тәсіл болар еді деп ойлаймын. Бұл Lisp-тен гөрі заманауи естіледі. Көптеген адамдар үшін Lisp — бұл көп жақшалары бар, баяу ЖИ (AI) тілі. Фриц Кунце өзінің ресми өмірбаянында «L» әрпінен басталатын сөзді атаудан мұқият қашады. Бірақ менің ойымша, біз жаңа Lisp-ті Lisp деп атаудан қорықпауымыз керек. Lisp әлі күнге дейін ең жақсы хакерлер арасында — мысалы, 6.001 курсын оқып, оны түсінгендер арасында — көптеген жасырын құрметке ие. Ал олар — сіз жеңіп алуыңыз керек пайдаланушылар.
«How to Become a Hacker» еңбегінде Эрик Реймонд Lisp-ті латын немесе грек тілі сияқты нәрсе ретінде сипаттайды — оны іс жүзінде қолданбасаңыз да, интеллектуалды жаттығу ретінде үйренуіңіз керек тіл:
Lisp-ті оны ақырында түсінген кезде бастан өткеретін терең ағартушылық тәжірибе үшін үйренуге тұрарлық; бұл тәжірибе сіздің өміріңіздің соңына дейін жақсырақ бағдарламашы болуыңызға ықпал етеді, тіпті Lisp-тің өзін ешқашан көп қолданбасаңыз да.
Егер мен Lisp-ті білмесем, мұны оқу маған сұрақтар туғызар еді. Мені жақсырақ бағдарламашы ететін тіл, егер бұл сөздің қандай да бір мәні болса, бағдарламалау үшін жақсырақ болатын тілді білдіреді. Және бұл шын мәнінде Эриктің айтып отырған ойының астары.
Бұл идея әлі де бар болғандықтан, хакерлер жаңа Lisp-ті, тіпті оның аты Lisp болса да, жақсы қабылдайды деп ойлаймын. Бірақ бұл Lisp 1970 жылдардағы классикалық Lisp-тер сияқты хакерлік тіл болуы керек. Ол ықшам, қарапайым және оңай өзгертілетін болуы керек. Және оның хакерлер қазір жасағысы келетін нәрселерді істеу үшін қуатты кітапханалары болуы керек.
Кітапханалар мәселесінде Perl және Python сияқты тілдерді өз ойынында жеңуге орын бар деп ойлаймын. Алдағы жылдары жазылуы қажет жаңа қосымшалардың көпшілігі серверлік қосымшалар болады. Жаңа Lisp-те Perl сияқты жақсы жолдық кітапханалар болмауына ешқандай себеп жоқ, ал егер осы жаңа Lisp-те серверлік қосымшаларға арналған қуатты кітапханалар да болса, ол өте танымал болуы мүмкін. Нағыз хакерлер кітапхананың бірнеше шақыруымен күрделі мәселелерді шешуге мүмкіндік беретін жаңа құралдан бетін бұрмайды. Есіңізде болсын, хакерлер жалқау келеді.
Серверлік қосымшаларды тілдің ядросы деңгейінде қолдау одан да үлкен ұтыс болуы мүмкін. Мысалы, көп пайдаланушысы бар бағдарламаларды айқын қолдау немесе тип тегтері деңгейіндегі деректерге иелік ету.
Серверлік қосымшалар сонымен қатар бұл жаңа Lisp-тің не үшін қолданылатыны туралы сұраққа жауап береді. Lisp-ті Unix үшін скрипттік тіл ретінде жақсарту артық болмас еді. (Оны одан әрі нашарлату қиын болар еді.) Бірақ менің ойымша, қолданыстағы тілдерді жеңу оңайырақ болатын басқа салалар бар. Tcl үлгісіне еріп, Lisp-ті серверлік қосымшаларды қолдауға арналған толық жүйемен бірге ұсынған дұрысырақ шығар. Lisp серверлік қосымшалар үшін өте қолайлы. Лексикалық тұйықталулар (lexical closures) интерфейс жай ғана веб-беттер тізбегі болған кезде ішкі бағдарламалардың (subroutines) әсерін алу тәсілін береді. S-өрнектер html-ге жақсы сәйкес келеді, ал макростар оны құруға өте қолайлы. Серверлік қосымшаларды жазу үшін жақсырақ құралдар қажет және жаңа Lisp қажет, және бұл екеуі бірге өте жақсы жұмыс істер еді.
12 Армандағы тіл
Қорытынды ретінде, хакердің армандаған тілін сипаттап көрейік. Армандағы тіл — әдемі, таза және ықшам. Оның жылдам іске қосылатын интерактивті жоғарғы деңгейі (interactive toplevel) бар. Сіз өте аз кодпен жалпы мәселелерді шешу үшін бағдарламалар жаза аласыз. Сіз жазатын кез келген бағдарламадағы кодтың барлығы дерлік тек сіздің қосымшаңызға ғана тән код болады. Қалғанының бәрі сіз үшін жасалып қойған.
Тілдің синтаксисі шектен тыс қысқа. Сізге ешқашан артық таңба терудің немесе тіпті shift пернесін көп басудың қажеті болмайды.
Үлкен абстракцияларды пайдалана отырып, сіз бағдарламаның алғашқы нұсқасын өте жылдам жаза аласыз. Кейінірек, оңтайландырғыңыз келгенде, назарыңызды қайда аудару керектігін айтатын шынымен жақсы профилировщик бар. Ішкі циклдерді керемет жылдам етуге болады, тіпті қажет болса, кірістірілген байт-кодты да жазуға болады.
Үйренуге болатын көптеген жақсы мысалдар бар және тіл соншалықты интуитивті, оны бірнеше минут ішінде мысалдардан үйреніп алуға болады. Нұсқаулыққа жиі қараудың қажеті жоқ. Нұсқаулық жұқа және онда ескертулер мен шектеулер аз.
Тілдің шағын өзегі және негізгі тіл сияқты мұқият жобаланған қуатты, жоғары ортогоналды кітапханалары бар. Кітапханалардың барлығы бірге жақсы жұмыс істейді; тілдегі барлық нәрсе жақсы фотокамераның бөлшектері сияқты бір-біріне үйлеседі. Ештеңе ескірген (deprecated) деп танылмаған немесе үйлесімділік үшін сақталмаған. Барлық кітапханалардың бастапқы коды еркін қолжетімді. Орындау жүйесімен және басқа тілдерде жазылған қосымшалармен байланысу оңай.
Тіл қабаттар түрінде құрылған. Жоғары деңгейлі абстракциялар төменгі деңгейлі абстракциялардан өте түсінікті түрде жасалған, қаласаңыз, оларға қол жеткізе аласыз.
Өте қажет болмаса, сізден ештеңе жасырылмайды. Тіл абстракцияларды сізге не істеу керектігін бұйыру үшін емес, тек жұмысыңызды жеңілдету тәсілі ретінде ұсынады. Шындығында, тіл сізді оның дизайнына тең дәрежелі қатысушы болуға ынталандырады. Сіз ол туралы барлық нәрсені, тіпті оның синтаксисін де өзгерте аласыз және сіз жазған кез келген нәрсе, мүмкіндігінше, алдын ала анықталған нәрселермен бірдей мәртебеге ие болады.
Ескертпелер
[1] Қазіргі заманғы түсінікке өте жақын макростарды Тимоти Харт 1964 жылы, Lisp 1.5 шыққаннан кейін екі жыл өткен соң ұсынды. Бастапқыда айнымалыларды қармап қалудан (variable capture) және бірнеше рет есептеуден аулақ болу тәсілдері жетіспеді; Харттың мысалдары осы екеуіне де бейім еді.
[2] When the Air Hits Your Brain кітабында нейрохирург Фрэнк Вертосик бас резиденті Гэридің хирургтар мен терапевтер («бүргелер») арасындағы айырмашылық туралы айтқан әңгімесін еске алады:
Гэри екеуміз үлкен пиццаға тапсырыс беріп, бос кабина таптық. Бастық темекі тұтатты. «Ана қарғыс атқан бүргелерге қарашы, өмірлерінде бір-ақ рет көретін қандай да бір ауру туралы былжырап отыр. Бүргелердің бар бәлесі осында, олар тек оғаш нәрселерді ғана ұнатады. Олар күнделікті кездесетін жағдайларды жек көреді. Біз бен мына лағынет бүргелердің айырмашылығы осында. Көрдің бе, біз үлкен, шырынды бел омыртқа дискісінің жарығын жақсы көреміз, ал олар гипертонияны жек көреді....»
Бел омыртқа дискісінің жарығын (сөзбе-сөз мағынасынан басқа) «шырынды» деп елестету қиын. Дегенмен, мен олардың не айтқысы келгенін түсінетін сияқтымын. Менде де жиі іздеп табатын «шырынды» қате (bug) болатын. Бағдарламашы емес адамға қатеден ләззат алуға болады деп елестету қиын болар еді. Әрине, бәрі жай ғана жұмыс істеп тұрса жақсырақ. Бір жағынан, солай. Дегенмен, қателердің белгілі бір түрлерін аулауда сөзсіз бір ғажап қанағат бар.