← A–Z Röportajları

Sh

Sh: Steve Bourne

1970’lerin başında Bourne, İngiltere’nin Cambridge kentindeki Computer Laboratory’de, dinamik astronomi alanındaki doktora çalışmasının bir parçası olarak Algol 68 için bir derleyici üzerinde çalışıyordu. Bu çalışma, 1973’te kısmen derleyiciler üzerine araştırma yapmak amacıyla New York’taki IBM T. J. Watson Research Center’a gitmesinin yolunu açtı. Bu çalışmalar ve bir dizi bağlantı ve koşul sayesinde Bourne, Bell Labs’teki kişilerle tanıştı ve onlar da 1975’te ona Unix grubunda bir iş teklif etti. Bourne’un sh’yi geliştirdiği dönem bu zamandı.

Bourne kabuğunun ortaya çıkmasına ne sebep oldu?

Orijinal kabuk aslında bir dil değildi; daha çok bir kayıt mekanizmasıydı – bir dosyadaki komutların doğrusal bir dizisini çalıştırmanın bir yoluydu ve tek kontrol akışı ilkel yapısı bir etikete goto ile atlamaktı. Ken Thompson’ın yazdığı orijinal kabuğun bu sınırlamaları önemliydi. Örneğin, bir komut betiğini bir filtre olarak kullanmak kolay değildi; çünkü komut dosyasının kendisi standart girdiydi. Oysa bir filtrede standart girdi, komut dosyası değil, üst süreçten devralınandır.

Orijinal kabuk basitti, ancak insanlar Unix’i uygulama geliştirme ve betik yazımı için kullanmaya başladıkça fazla sınırlı kaldı. Değişkenleri yoktu, kontrol akışı yoktu ve tırnaklama yetenekleri son derece yetersizdi.

Bell Labs’e gitmeden önceki kişisel ilgim, programlama dili tasarımı ve derleyiciler üzerindeydi. Cambridge’de Mike Guy ile birlikte Algol 68 dili üzerinde çalışmıştım. Küçük bir grubumuz Algol 68 için Algol68C adını verdiğimiz bir derleyici yazdı. Ayrıca dili daha kullanılabilir hale getirmek için bazı eklemeler de yaptık. Bir yan not olarak, derleyiciyi özyüklemeli hale getirdik; yani kendisi de Algol68C ile yazılmıştı.

Bell Labs’e geldiğimde, birçok kişi orijinal kabuğa değişkenler ve kontrol akışı ilkel yapıları gibi programlama yetenekleri eklemenin yollarını araştırıyordu. Bir gün (1975’in ortaları) Dennis Ritchie ile birlikte, Ken’in yazdığı orijinal kabukta alınmış bazı tasarım kararlarının üzerine yama yaparak bir başka varyasyon öneren birinin bulunduğu bir toplantıdan çıktık. Ben Dennis’e baktım, o bana baktı ve ben şunu söyledim: “biliyorsun, bunu baştan ele almamız ve bazı orijinal tasarım kararlarını yeniden düşünmemiz gerekiyor; çünkü bazı temel şeyleri değiştirmeden buradan oraya gidemezsiniz.” İşte yeni kabuk üzerinde çalışmaya bu şekilde başladım.

Dilin çözmeyi amaçladığı belirli bir sorun var mıydı?

Temel sorun, kabuğu hem betik yazımı için tam anlamıyla programlanabilir bir dil olacak hem de terminalde etkileşimli olarak komut yazan kullanıcılar için bir arayüz görevi görecek şekilde tasarlamaktı. Her şeyden önce, insanların aşina olduğu mevcut kullanımla uyumlu olması gerekiyordu.

İki kullanım modu vardı. Biri betik yazımıydı ve çok sınırlı olmasına rağmen insanların yazdığı pek çok betik zaten mevcuttu. Diğeri ise, kabuğun ya da komut yorumlayıcısının, terminalde yazdığınız komutları okuyup çalıştırmasıydı. Dolayısıyla hem bir komut satırı yorumlayıcısı hem de bir betik dili olmak zorundaydı.

Örneğin Unix komut satırı yorumlayıcısı olarak, C’de yaptığınız gibi tüm dizgileri tırnak içine alarak komut yazmak istemezsiniz; çünkü yazdığınız şeylerin çoğu yalnızca yorumlanmayan metinlerdir. ls directory yazıp dizin adını tırnak içine almak istemezsiniz, çünkü bu son derece zahmetli olurdu. Ayrıca boşluklar, komutlara verilen argümanları ayırmak için kullanılır.

Temel tasarım buradan yola çıkar ve bu da dilde dizgileri nasıl temsil ettiğinizi belirler; yani yorumlanmayan metin olarak. Dizgi olmayan her şeyin, dizgi olmadığını anlamanızı sağlayacak bir ön işareti olması gerekir. Örneğin değişkenlerin önünde bir $ işareti vardır. Bu, değişkenlerin adlar olduğu ve dizgilerin bir tür tırnak işareti içinde bulunduğu tipik bir programlama dilinin tersidir. for döngüleri gibi yerleşik komutlar için ayrılmış sözcükler de vardır, ancak bu birçok programlama dilinde yaygındır.

Bu, Bourne Shell’in çözmek üzere tasarlandığı sorunun ne olduğunu ifade etmenin bir yoludur. Ayrıca şunu da söyleyebilirim ki kabuk, Unix sistem ortamına açılan arayüzdür ve dolayısıyla birincil işlevi budur: Unix komut kümesinin ve Unix sistem çağrılarının size sunduğu her şeyi yapabilmenizi sağlayacak, Unix sistem ortamına tam işlevli bir arayüz sağlamak. Kabuğun temel amacı budur.

Çözmeye çalıştığımız sorunlar hakkında konuşurken yaptığımız diğer şeylerden biri de Unix sistemine ortam değişkenlerini eklemekti. Bir komut betiğini çalıştırdığınızda, o betiğin çalışacağı bir bağlama sahip olmak istersiniz. Eski günlerde, komutlar için konumsal parametreler bilgi aktarmanın temel yoluydu. Açıkça belirtilmeyen bir bağlam istiyorsanız, komut bir dosya okumaya başvurabilirdi. Bu çok zahmetliydi ve pratikte nadiren kullanılıyordu.

Unix’e ortam değişkenlerini ekledik. Bunlar, üst süreçten alt sürece açıkça aktarmanız gerekmeyen adlandırılmış değişkenlerdi. Alt süreç tarafından miras alınırlar. Örneğin, komutları çalıştırırken kullanılacak dizinlerin listesini belirleyen bir arama yolu tanımlayabilirdiniz. Bu arama yolu, tanımlandığı üst süreç tarafından başlatılan tüm süreçler için kullanılabilir olurdu.

Bu, kabuk programlamasının yapılma biçiminde büyük bir fark oluşturdu; çünkü artık ortamda bulunan bilgileri görebiliyor ve kullanabiliyordunuz ve aradaki kişinin bunu size aktarması gerekmiyordu. Bu, betik yazımını desteklemek için işletim sistemine eklediğimiz en önemli katkılardan biriydi.

Thompson kabuğuna göre nasıl bir iyileştirme sağladı?

Kabuğu, komut betiklerinin filtre olarak kullanılabilmesini sağlayacak şekilde değiştirdim. Orijinal kabukta bu pek mümkün değildi; çünkü çalışan betik için standart girdi, betiğin kendisiydi. Bu değişiklik, insanların alışkın olduğu çalışma biçiminde ciddi bir sarsıntıya yol açtı.

Değişkenler, kontrol akışı ve komut ikamesi ekledim. case deyimi, dizgilerin kolayca eşleştirilmesine olanak tanıdı; böylece komutlar argümanlarını çözümleyip buna göre kararlar verebildi. for döngüsü, açıkça belirtilmiş ya da varsayılan olarak komuta verilen argümanlar olan bir dizgi kümesi üzerinde yineleme yapılmasını sağladı.

Ayrıca tırnaklar içinde değişken ikamesi yapabilmenizi sağlayan ek bir tırnaklama mekanizması da ekledim. Thompson kabuğunun özgün havasının bir kısmı hâlâ korunurken, bu önemli bir yeniden tasarımdı. Ayrıca goto’yu kaldırıp if ve for gibi akış kontrolü ilkel yapılarını tercih ettim. Bu da mevcut uygulamadan oldukça radikal bir sapma olarak görülüyordu.

Komut ikamesi eklediğim bir başka şeydi; çünkü bu, dizgi işleme için çok genel bir mekanizma sunar. Komutlardan dizgiler geri almanıza ve bunları, sanki doğrudan yazmışsınız gibi betiğin metni olarak kullanmanıza olanak tanır. Bunun, belki Lisp dışında, betik dillerinde gördüğüm yeni bir fikir olduğunu düşünüyorum.

Bu süreç ne kadar sürdü?

Çok uzun sürmedi; şaşırtıcı derecede kısa sürdü. Sorunun doğrudan cevabı, temel tasarım seçimlerini yapmak ve çalışır hale getirmek için en fazla yaklaşık 3–6 ay civarında olduğudur. Bundan sonra, kullanıcı geri bildirimleri ve taleplerine dayanarak tasarımı yineledim ve hataları düzelttim.

Açıkçası tam olarak hatırlamıyorum ama o dönemde eklediğim bir dizi tasarım unsuru vardı. Önemli olduğunu düşündüğüm şeylerden biri, dizgi boyutları ya da başka herhangi bir şeyin boyutları konusunda kabuk tarafından hiçbir sınır dayatılmamasıydı. Bu nedenle yazdığım uygulamadaki bellek ayırma oldukça gelişmişti. Dizgilerin herhangi bir uzunlukta olmasına izin verirken, aynı zamanda çok verimli bir dizgi işleme yeteneğini de koruyordu; çünkü o günlerde dizgileri sürekli kopyalayarak çok fazla komut harcamak mümkün değildi.

En çok zaman alan kısım bellek yönetiminin uygulanmasıydı. Bir programın bu bölümündeki hatalar genellikle bulunması en zor olanlardır. Bu kod bölümü, ilk tasarımı ayağa kaldırdıktan sonra üzerinde çalışılan bir alandı.

Bellek yönetimi hikâyenin ilginç bir parçasıdır. Dizgi oluşturma sırasında belleğin tükenip tükenmediğini çalışma zamanında kontrol etmek zorunda kalmamak için sbrk sistem çağrısının çok iyi bilinmeyen bir özelliğini kullandım. Bir bellek hatası aldığınızda Unix’te daha fazla bellek ayırabilir ve ardından programı kaldığı yerden devam ettirebilirsiniz. Bu nadiren gerçekleşen bir durumdu ama kabuğun performansında önemli bir fark oluşturdu. O dönemde Dennis tarafından bunun sbrk arayüz tanımının bir parçası olduğu konusunda bilgilendirilmiştim. Ancak Unix’i başka bir bilgisayara uyarlayan herkes, kabuğun kendisini taşımaya çalışırken bunu fark etti.

Ayrıca o dönemde Bell Labs’te, laboratuvarın farklı bölümlerinde ortaya çıkmış başka betik dilleri de vardı. Bunlar, daha önce tanımladığım aynı sorunlar kümesini çözmeye yönelik çabalardı. En yaygın kullanılan “yeni” kabuk, programcı çalışma tezgâhında yer alan ve John Mashey’in yazdığı kabuktu. Dolayısıyla laboratuvarın diğer bölümlerinde, yeni kabuğa dönüştürülmesi önemli bir maliyet gerektirecek ciddi bir betik yatırımı bulunuyordu.

En zor kısım, bu betiklere sahip olan insanları dönüştürmeye ikna etmekti. Yazdığım kabuk, betik yazımını kolaylaştıran önemli özelliklere sahipti; ancak diğer grupları ikna etme yöntemim bir performans karşılaştırması yapmak oldu. Performansı iyileştirmek için zaman harcadım; bu da muhtemelen, laboratuvardaki diğer grupları benimsemeye ikna etmek için fazladan, bilemiyorum, 6 ay ya da bir yıl aldı. Ayrıca bu betiklerin dönüştürülmesini daha az sancılı hale getirmek için dilde bazı değişiklikler de yapıldı.

Bunun size düşmesinin nedeni neydi?

Bell Labs’teki Unix grubunda işleyiş şu şekildeydi: Eğer bir şeyle ilgileniyorsanız ve kodun sahibi başka kimse değilse, onun üzerinde çalışabiliyordunuz. O sırada Ken Thompson özgün kabuğun sahibiydi, ancak o yıl Berkeley’i ziyaret ediyordu ve yeni bir kabuk üzerinde çalışmayı düşünmüyordu; ben de bu işi üstlendim. Daha önce de söylediğim gibi dil tasarımıyla ilgileniyordum ve programlanabilir bir komut dili yapma konusunda bazı fikirlerim vardı.

Dili sürdürürken zor kararlarla karşılaştınız mı?

Bunun basit cevabı şu: 1983’te dile yeni şeyler eklemeyi bıraktım. Dile eklediğim son şey fonksiyonlardı. Ve neden baştan fonksiyonları koymadığımı bilmiyorum. Soyut bir düzeyde bir komut betiği bir fonksiyondur, ancak aynı zamanda izlenmesi gereken bir dosya olma özelliği de vardır.

Ancak komut dosyalarıyla ilgili sorun performanstır; bunun dışında fonksiyonlar ile komut betikleri arasında anlamsal olarak büyük bir fark yoktur. Performans sorunu, bir komut betiğini çalıştırmanın Unix fork ve exec sistem çağrıları aracılığıyla yeni bir süreç oluşturmayı gerektirmesinden kaynaklanır; bu da Unix ortamında pahalıdır. Dolayısıyla betik yazımındaki performans sorunlarının çoğu bu maliyetten gelir. Fonksiyonlar ise uygulamayı gerçekleştirmek için fork ve exec gerektirmeden soyutlama sağlar. Bu yüzden dile eklediğim son şey fonksiyonlar oldu.

Tek bir dil programlama dünyasındaki tüm sorunları çözemez; bu yüzden bir noktada ya onu basit ve makul ölçüde zarif tutarsınız ya da sürekli yeni şeyler eklersiniz. Bazı modern masaüstü uygulamalarına bakarsanız özellik şişmesi yaşadıklarını görürsünüz. Aklınıza gelebilecek her türlü zil, düğme ve süs eklenmiştir ve içinde yolunuzu bulmak imkânsızdır.

Bu nedenle, kabuğun başlangıçta sahip olduğu tasarım kısıtları içinde sınırlarına ulaştığına karar verdim. “Biliyorsunuz, tutarlılığı ve sadeliği koruyarak yapabileceğim çok fazla şey kalmadı,” dedim. Ondan sonra insanların yaptığı şeyler onu POSIX uyumlu hâle getirmekti ve kuşkusuz zamanla başka eklemeler de yapılmıştır. Ancak bir betik dili olarak sınırına ulaştığını düşünüyordum.

Geriye dönüp baktığınızda, dilin geliştirilmesinde değiştirmek isteyeceğiniz bir şey var mı?

Dil tasarımında kesinlikle fonksiyonları daha erken eklerdim. Bunu özgün tasarımın bir parçası olarak yapmamış olmama oldukça şaşırıyorum. Yapmak isteyeceğim diğer şey ise onun için bir derleyici yazmak olurdu. Bir kabuk betiği derleyicisi yazmanın yarısına kadar gelmiştim ama o dönemde kimse performanstan şikâyet etmediği için rafa kaldırdım.

Geriye baktığımda özellikle farklı yapacağımız şeyler aklıma gelmiyor. İlk programlanabilir betik dillerinden biri olarak üretkenlik üzerinde önemli bir etki yapıyordu.

Dil bir betik dili olma amacıyla yazıldıysa, nasıl oldu da etkileşimli bir komut yorumlayıcısı olarak daha popüler hâle geldi?

Başlangıçtan itibaren her ikisini de yapacak şekilde tasarlanmıştı. Tasarım alanı şuydu: Terminalin başındasınız — bugünlerde ekranın başında — ve işleri yapmak için komutlar yazıyorsunuz. Bunun kabuğun birincil işlevlerinden biri olması her zaman amaçlanmıştı.

Bir kabuk betiğinde olduğunuzda da eriştiğiniz komut kümesi aynıdır, çünkü hâlâ Unix ortamına erişiyorsunuz, sadece bunu bir betik içinden yapıyorsunuz. Bir programlama dilinden farkı, esasen Unix komutlarına ve bu yeteneklere terminalden ya da doğrudan betikten erişiyor olmanızdır. Yani baştan itibaren her ikisini de yapması amaçlanmıştı.

Şu anda hangisinin daha popüler olduğu konusunda hiçbir fikrim yok; sanırım ortalıkta çok sayıda kabuk betiği var.

Bourne Again shell (Bash), Korn Shell (ksh), C Shell (csh) ve tcsh gibi varyasyonlar dâhil olmak üzere pek çok başka kabuk yazıldı. Bunlar hakkındaki görüşünüz nedir?

Bash’in Bourne kabuğunun açık kaynaklı bir kopyası olduğuna inanıyorum. İçinde bazı ek özellikler olabilir; emin değilim. Herkesin bildiği gibi bu, açık kaynak dünyasından gelen bir itkiyle gelişti, çünkü Unix lisansı Unix’in fikrî mülkiyetini (kaynak kodunu) bağlıyordu ve onu kullanmak için lisans almanız gerekiyordu.

C kabuğu, Bourne kabuğunu yazmamdan biraz sonra yapıldı — o zamanlar Bill Joy ile bunun hakkında konuşmuştum. sh’yi yazdığım sırada o da aynı anda bunu düşünüyor olabilir, ama her hâlükârda benzer bir zaman diliminde ortaya çıktı. Bill, o dönemde benim daha az ilgi duyduğum bazı konularla ilgileniyordu. Örneğin geçmiş (history) özelliğini ve iş denetimini eklemek istiyordu; bu yüzden C kabuğunu yazmaya devam etti.

Belki geriye dönüp bakınca, Unix kabuğuna geçmiş ve iş denetimi gibi bazı şeyleri eklemeliydim. Ama o zamanlar bunların gerçekten oraya ait olduğunu düşünmüyordum… bir pencere sisteminiz olduğunda bu işlevlerin bazılarına zaten sahip oluyorsunuz.

Korn kabuğunun tam olarak ne zaman yazıldığını hatırlamıyorum. Sanırım 80’lerin başıydı. O sırada sh’ye “özellik” eklemeyi bırakmıştım ve insanlar daha iyi dizge işleme gibi şeyler eklemeye devam etmek istiyordu. Ayrıca POSIX tanımlanıyordu ve sh’nin kullanım biçimine ilişkin standartta bir dizi değişiklik düşünülüyordu. Sanırım ksh de iş denetimi gibi bazı csh olanaklarına sahip.

Kendi görüşüm, söylediğim gibi, kabuğun onu oldukça barok hâle getirmeden ve kesinlikle anlamayı daha karmaşık kılmadan eklenebilecek özelliklerin sınırına ulaşmış olduğuydu.

C kabuğu (ve ondan türeyenler) neden yeryüzünden silinip gitmedi? Aslında böyle bir şey oluyor mu?

Bilmiyorum, oluyor mu? İnsanların C kabuğunda yazdığı çok sayıda betik var. Ayrıca C’ye daha benzeyen bir sözdizimine sahip. Dolayısıyla insanlar bir betik koleksiyonu oluşturduktan sonra ondan kurtulmak zor oluyor.

Geçmiş ve iş denetimi dışında, dil özelliklerinin o kadar da farklı olduğunu düşünmüyorum; her ne kadar farklı şekilde ifade edilmiş olsalar da. Örneğin her iki dilde de döngüler, koşullar, değişkenler vb. var. Bazı insanların kabuğun Algol 68’e benzeyen sözdizimine karşılık C tarzı sözdizimini tercih ettiğini tahmin ediyorum.

Oraya Algol benzeri sözdizimini koymamın bir nedeni vardı. Her zaman şunu fark etmişimdir — bu bir dil tasarımı meselesidir — bir C programını okurken bir kapatma parantezine geldiğimde, o paranteze karşılık gelen açma parantezinin nerede olduğunu merak ederdim. Yapının başlangıcını bulmak için etrafta arama yapardım, ancak neye bakmanız gerektiğine dair sınırlı görsel ipuçları vardı.

Örneğin C dilinde bir kapatma parantezi bir if’in, bir switch’in ya da başka pek çok şeyin sonu olabilir. O günlerde kapatma parantezine işaret edip “buna karşılık gelen açma parantezi nerede?” diyebileceğiniz iyi araçlarımız yoktu. Elbette bir girintileme kuralı benimseyebilirdiniz, ancak yanlış girintilerseniz, eşleşmeyen ya da yanlış yerde duran parantezler yüzünden programlarda kolayca hatalar oluşabilirdi.

Bu yüzden if ve fi gibi eşleşen açma ve kapama belirteçlerini kullandım — böylece tüm bileşik ifadeler kapatılmış oluyor ve kendilerine özgü kapatma belirteçlerine sahip oluyordu.

Bir başka nedenle de önemliydi: Dilde şu özelliğin olmasını istiyordum: Bir komutun bulunduğu her yerde, onu if-fi ya da while-do-done gibi kapalı biçimde herhangi bir komutla değiştirebilmeli ve bunu yaparken yerine koyduğunuz şeyin sözdizimini yeniden yazmak zorunda kalmamalıydınız. Eşleşen parantezler gibi, kolayca tanımlanabilir bir başlangıç ve bitişe sahipler.

Mevcut Unix kabuklarını (metni işleyen programlar) ve yeni MS Windows PowerShell’i (nesneleri işleyen sınıflar) karşılaştırın. Unix, PowerShell yaklaşımından fayda sağlar mıydı?

Unix ortamının kendisi, kabuğun arayüz sağladığı şey olan Unix’e baktığınızda, gerçekten nesnelere sahip değil. Eğer kabuk düzeyinde yazan kişiler için nesneler görünür olsaydı, kabuğun bunları desteklemesi gerekirdi. Ama Unix’te bunun nerede söz konusu olacağını bilmiyorum; böyle bir şey görmedim.

Microsoft örneğinde nesnelerin kullanıcıya görünür birinci sınıf varlıklar olduğunu ve bu yüzden Windows ile arayüz kuran betik dilinde desteklenmelerinin istendiğini tahmin ediyorum. Ancak bu, sorunuza oldukça genel bir yanıt; PowerShell hakkında özel olarak bilgi sahibi değilim.

Bash, Bourne kabuğunun layık bir ardılı mı? Bash’te bazı şeyler farklı mı yapılmalıydı?

Bourne kabuğunda ya da bash’te çalışacak kabuk betikleri yazabileceğinize inanıyorum. Bourne kabuğunda olmayan bazı ek özellikleri olabilir. Bash’in, Bourne kabuğunun sıkı biçimde uyumlu açık kaynaklı bir sürümü olarak amaçlandığını düşünüyorum. Açıkçası ayrıntılı olarak incelemedim, dolayısıyla yanılıyor olabilirim. Evde bir GNU/Linux sistemi kullandığım için ben de bash kullandım ve beklediğim gibi çalışıyor gibi görünüyor.

Unix uzmanı Steve Parker, yazdığı Steve’in Bourne / Bash betik yazımı öğreticisinde şunları söylüyor:

“Kabuk betiği programlamanın bazı Unix sistem yöneticileri arasında biraz kötü bir şöhreti vardır. Bunun genellikle iki nedenden biri vardır: a) Yorumlanan bir programın, bir C programına ya da hatta yorumlanan bir Perl programına kıyasla çalışma hızı; b) Basit bir toplu iş türü kabuk betiği yazmanın kolay olması nedeniyle ortalıkta çok sayıda düşük kaliteli kabuk betiği bulunması.”

Katılıyor musunuz?

Katılmamak zor olurdu, çünkü muhtemelen bu konuda benden daha fazla şey biliyor. Gerçek şu ki, hemen her dilde kötü kod yazabilirsiniz; kabuk da bunun istisnası değildir. Nasıl karmaşıklaştırılmış C yazılabiliyorsa, karmaşıklaştırılmış kabuk da yazılabilir. Belki de karmaşıklaştırılmış kabuk yazmak, karmaşıklaştırılmış C yazmaktan daha kolaydır. Bilmiyorum. Ama bu ilk nokta.

İkinci nokta ise kabuğun bir dizge işleme dili olması ve dizge işlemenin oldukça basit olmasıdır. Dolayısıyla bu tür işler için oldukça verimli çalışmaması için temel bir neden yoktur. Bash’in performansı ve bunun nasıl uygulandığı konusunda bilgi sahibi değilim. Belki de bahsettiği bazı kişiler kabuk yerine bash çalıştırıyordur, ama yine de bunlar için herhangi bir performans karşılaştırmam yok. Ancak bakacağım yer burası olurdu.

Özgün kabuk uygulamasını yazdığımda, verimli olduğundan emin olmak için çok zaman harcadığımı biliyorum. Özellikle dizge işleme konusunda, ama aynı zamanda komut dosyasının okunması konusunda da. Yazdığım özgün uygulamada, komut dosyası önceden yükleniyor ve önceden ayrıştırılıyordu; böylece onu çalıştırdığınızda dizge ikameleri ve değerleri değiştirecek diğer anlamsal işlemler dışında herhangi bir işlem yapmanız gerekmiyordu. Bu da kod üretmeden, yorumlanan bir dilde elde edilebilecek en yüksek verimlilikti.

Şunu da söyleyeyim — komik çünkü Maurice Wilkes, ona ne yaptığımı anlattığımda bana bu soruyu sormuştu — ve “bunu yapmayı nasıl karşılayabiliyorsun?” demişti. Yani, örneğin bir C programında bir fonksiyon çalıştırmaya kıyasla, komut çalıştırmanın maliyeti bu kadar yüksekken, ilkel yapıtaşları çalıştırılan komutlar olan programlar yazmayı nasıl karşılayabiliyorsun demek istemişti.

Daha önce de söylediğim gibi, temel performans sınırlaması her komut çalıştırıldığında bir Unix fork ve exec yapılması gerekliliğidir. Bunlar bir C fonksiyon çağrısından çok daha pahalıdır. Ve komutlar soyutlama mekanizması olduğu için, çok sayıda ve çok az iş yapan komut çalıştırıyorsanız bu durum verimsizliğe yol açar.

Bourne kabuğunun geleceğini nerede görüyorsunuz?

Bilmiyorum; zor bir soru. Unix var olduğu sürece onun da var olacağını tahmin ediyorum. Unix kabukları arasında en yaygın olanı gibi görünüyor. İnsanların bana söylediğine göre, dünyadaki tüm Unix sistemlerinde çalışacak bir şey istiyorlarsa, bunu Bourne kabuğunda (ya da bash’te) yazıyorlar. Yani bu bir neden. Bunun doğru olup olmadığını bilmiyorum ama bana söylenen bu.

Ve Unix’in yakın zamanda ortadan kaybolacağını da sanmıyorum. Açık kaynak hareketiyle, özellikle GNU Projesi ve Linux çekirdeğiyle birlikte bir canlanma yaşadığı görülüyor.

Genel olarak kabukların nereye gittiğini görüyorsunuz?

Söylediğim gibi, kabuk Unix ortamına bir arayüzdür. Unix komutlarını çağırmak ve bu ortamı etkileşimli olarak ya da betikler aracılığıyla yönetmek için size bir yol sağlar. Bu önemlidir, çünkü diğer kabuklara ya da daha genel olarak betik dillerine baktığınızda, genellikle bir ortama erişim sağladıklarını ya da bir ortamı denetleyip işlediklerini görürsünüz. Ve programcıya sunulan özelliklerde, arayüz kurdukları ortamın karakteristiklerini yansıtırlar.

Unix kabuklarının böyle olduğu kesinlikle doğrudur. Bazı farklı dil tercihleri ve bazı farklı ödünleşimler olabilir, ancak hepsi Unix ortamına erişim sağlar. Dolayısıyla dillerin ve kabukların ortaya çıkmaya devam ettiğini göreceksiniz.

Web’de olup biten bazı gelişmelere bakın — PHP gibi HTML ve Web sayfalarını programlamanıza olanak tanıyan bir dizi dil geliştirilmiştir. Bunlar o ortama özgüdür. Bence yeni yeteneklere sahip yeni ortamlar geliştikçe, onları kullanmayı kolaylaştırmak için etraflarında betik yeteneklerinin de geliştirildiğini göreceksiniz.

Adınıza bir programlama dili verilmiş olması nasıl bir his?

İnsanlar bazen bana “aa, siz Steve Bourne’sunuz” derler, çünkü kabuğu tanıyorlardır. Pek çok kişi tarafından kullanıldı. Hayatta pek çok şey yapıyorsunuz ve bazen adınızın bir şeye verilmesi gibi bir şans yakalıyorsunuz. Ona ilk kimin Bourne kabuğu dediğini bilmiyorum.

Onu Bourne olarak adlandıran siz değil miydiniz?

Hayır. Biz ona sadece “the shell” ya da “sh” diyorduk. Laboratuvardaki Unix grubunda başka birkaç program daha yazdım, örneğin adb hata ayıklayıcısı, ama ona “Bourne adb” demedik. Ve elbette “Aho awk” demedik. “Feldman make” de demedik. Yani ona Bourne kabuğu adını ben vermedim; başka biri verdi. Belki de o dönemdeki diğer kabuklardan ayırt etmek içindi.

Bilgisayar programlama dillerinin gelecekte, özellikle önümüzdeki 5 ila 20 yıl içinde nereye gittiğini görüyorsunuz?

Biliyorsunuz, bu tür şeyleri tahmin etmeye çalıştım ve bunda pek başarılı olamadım. Ve bu alanda 20 yıl sonsuzluk gibidir. Alana giren yeni isimlerin sayısına şaşırıyorum. 70’lerin sonları ve 80’lerin başlarında programlama dili tasarımlarının tamamlandığını düşünmüştüm. Belki bir süreliğine öyleydi. C vardı, C++ vardı; sonra Java ve Python çıkageldi.

Görünen o ki en popüler diller, sistemin farklı bölümleriyle arayüz kurmak için iyi bir kütüphane ya da yöntemler kümesine sahip olanlardır. Ayrıca bu modern dillerin, önceki dillerden dersler çıkardığı ve bunun sonucunda genel olarak daha iyi tasarlandığı da doğrudur.

1980’de yanıldığımı görüyorum; o zamanlar “peki, dillerle işimiz bitti, hadi işletim sistemlerine, nesne yönelimli programlamaya ve sonra da ağlara geçelim” diye düşünüyorduk ve o dönemdeki diğer büyük sorunlar her neyse. Sonra birden İnternet ve Web ortamına girdik ve farklı, geliştirilmiş, daha yetenekli olan ve benzeri pek çok şey ortaya çıktı. Bu yüzden bu kadar hızlı bir tempoda evrilmeye devam eden bir alanda olmak keyifli.

Artık İnternet’e girebilirsiniz ve örneğin posta dosyalarınızı sıralamak için bir program yazmak isterseniz, gezegendeki tüm farklı posta biçimlerini çözecek bir Python ya da Perl kütüphanesi bulursunuz. Bu yöntemler kümesini ya da işlevler kütüphanesini, tüm temel çözümlemeyi kendiniz yazmak zorunda kalmadan kullanabilirsiniz. Dolayısıyla günümüzde mevcut yazılımlar çok daha yetenekli ve kapsamlı.

Bence uzmanlaşmış dilleri görmeye devam edeceğiz; örneğin Web sayfaları ve HTML ile iyi çalışan PHP gibi. Bir de Ruby on Rails’e bakın. Lisp’in yeniden canlanacağını kim düşünebilirdi. Bir gözlemci olmak ve bu yeni şeyleri öğrenmek keyifli.

Sizce çok fazla programlama dili mi var?

Belki. Ama iyi olanlar ayakta kalacak, iyi olmayanlar ise birer heves olarak görülüp ortadan kaybolacak. Ve o anda hangilerinin hangisi olduğunu kim bilebilir. Bir bakıma araçlar gibiler; farklı şekillerde uygulanırlar. Herhangi bir mühendislik alanına bakın ve kaç tane araç olduğunu görün. Bazıları çok özel amaçlar için, bazıları ise oldukça genel.

Asıl mesele şu: “Yapmak istediğiniz her şeyi yapmak için hangi kütüphaneler ve yöntemler kümesi mevcut?” Posta dosyalarıyla ilgili verdiğim örnek gibi. Belirli türde verileri işlemek istediğiniz düzinelerce durum var. Dolayısıyla işleri yapmak için kütüphaneler istiyorsunuz.

Örneğin, bir çizim paketi istediğinizi varsayalım. Soru şu: çizim paketini ne için kullanmak istiyorsunuz? Bunu yapmak için programlar yazacaksanız, onları Perl’de mi Python’da mı yoksa başka bir dilde mi yazacaksınız? Dolayısıyla bu, dilin kendisi kadar, bu dillerin kütüphaneler ve yöntem kümeleri açısından sahip olduğu destek tarafından belirlenecek.

Yetişmekte olan programcıları eğitiyor olsaydınız, ne söylerdiniz?

Öncelikle biraz gözüm korkardı, çünkü günümüzde hepsi benden daha çok şey biliyor! Ve bugünkü ortamlar, benim kod yazdığım zamanlara kıyasla çok daha karmaşık. Bunu söylemişken, yazılım mühendisliği yıllar içinde çok fazla değişmedi.

Unix grubunda uyguladığımız şey şuydu: Bir kod yazdıysanız, o kodun çalışmasından şahsen sorumluydunuz ve bu kodu kamunun kullanımına sunduğunuzda çalışmıyorsa, tehlikeye giren sizin itibarınızdı. Unix laboratuvarında sistemi her gün kullanan yaklaşık 20 kişi vardı ve yazılımlarımızı herkesin kullandığı PDP-11 üzerine kuruyorduk. Ve çalışmıyorsa, oldukça hızlı bir şekilde azar işitirdiniz. Bu yüzden programlarımızı gruba sunmadan önce elimizden geldiğince test ederdik.

Bence bu günümüzde de önemli — bu büyük yazılım projelerinde kod yazıp çalışacağınız ortamı yeterince iyi anlamamak çok kolay; böyle olunca da kodu gerçek dünyada yayınladığınızda çalışmıyor. Yani vereceğim tavsiyelerden biri, kodunuzu kimin kullandığını ve ne için kullanacağını mutlaka anlamanızdır. Mümkünse gidip müşterilerinizi ziyaret edin ve kodunuzla ne yaptıklarını öğrenin. Ayrıca programınızın dağıtılacağı ortamı da mutlaka anlayın. Son olarak, kodunuzla gurur duyun ki hem meslektaşlarınız hem de müşterileriniz becerinizi takdir etsin.