Java Günlüğüm
Yazılım, Java, BT, azıcık felsefe, biraz mizah...
  • Udemy Eğitimleri
  • Temiz Kod
  • Tasarım Kalıpları
  • Hakkımda
  • Arşiv
RSS
27 Kasım 2009

No Silver Bullet ya da Sihirli Değnek Yok

Akin Yazılım Mühendisliği Frederick Brooks, No Silver Bullet, yazılım, yazılım geliştirme, Yazılım Mühendisliği, yazılımın doğası, yazılımın zorlukları

Frederick Brooks, 1987 Nisan ayında IEEE’nin Computer dergisinde “No Silver Bullet: Essence and Accidents of Software Engineering” başlıklı bir makale yayınladı. (Makalenin aslını burada, Türkçe çevirisini burada bulabilirsiniz.) Makale temel olarak yazılım mühendisliğinin doğasını inceliyor ve bu alanda o ana kadar olan gelişmeleri masaya yatırıyor. İlk yayınlandığında yazılım dünyasının klasikleri arasına giren, yazılımın neliği hakkında düşünce dünyamızı aydınlatan bu makale, lehinde ya da alehinde pek çok düşüncenin ortaya çıkmasını sağlamıştır. Makale, daha sonra yazarın, yine klasiklerden olmuş “The Mythical Man Month” isimli  kitabında da yer aldı. Chapel Hill’deki University of North Carolina’da Bilgisayar Bilimleri bölümünü kurup, 1964 ve 84 yılları arasında da bölümün başkanlığını yapan Prof. Brooks aynı zamanda IBM System/360’ın da babası olarak bilinmektedir.

Brooks makalesinde, Aristo’nun ayrımından yola çıkarak yazılımın asli ve arızi zorlukları olduğunu ifade ediyor. Brooks’a göre yazılımın asli zorlukları, yazılımın kavramsal olan doğasının bir sonucudurlar. Yazılımın kavramsal doğasının en belirleyici özellikleri ise karmaşıklık, uyumluluk, değişebilirlik ve görünmezlik olarak sıralanıyor. Yani yazılımlar öncelikle kavramsal yapılardır ve her zaman karmaşıktır, devamlı ortama uyum sağlaması beklenir, daima değişir ve hiç bir zaman görünür değildir. Brooks’a göre yazılım var oldukça yazılımcılar, yazılım geliştirmenin kavramsal taraflarını içeren ve geliştirilecek yazılımı tanımlama, tasarlama ve test etme gibi çalışmalarda bu dört özellikten kaynaklanan zorluklarla bir şekilde uğraşacaklardır. Makalede yazılım süreçlerinde olan ve yazılımı kodlamak ya da olması gerekene uygunluğunu test etmek gibi diğer çalışmaların ise arızi yani ikincil olduğu, dolayısıyla bu çalışmalardaki zorlukların, yazılım için olmazsa olmaz zorluklar olmadığı vurgulanıyor. Makalenin temel olarak savunduğu tez şu üç cümlede özetlenebilir: Bu dört özellik, yazılımın tabiatını oluşturdukları için yazılım geliştiriciler her zaman ve muhakkak bu dört özellikten kaynaklanan zorluklarla baş etmek zorundadırlar. Teknolojide ya da yönetimde bulunacak hiçbir yenilik, yazılım mühendisliğini daha üretken, güvenilir ve basit yapma adına önümüzdeki 10 senede 10 katlık bir kazanç sağlamaycaktır. Ayrıca yazılım dünyasında kurtarıcı olarak sunulan yeniliklerin hiçbirisi bu asli özellikleri ortadan kaldırmaz; olsa olsa arızi özelliklerini iyileştirir. İnsanoğlunun yazılım tecrübesi arttıkça, yazılım üretim hızında, yazılımın kalitesinde vs. tabi ki kazanımlar olacaktır. Fakat bu kazanımların, bilgisayar donanım endüstrisinde olduğu hızda olması hayal bile edilmemelidir. Bu yüzden Amerikan folklorunda var olan kurt adamları yere seren gümüşten kurşunu yazılım dünyasında aramak beyhudedir. Kurt adamları öldüren tek şey olan “gümüş kurşun”un bizim kültürümüzde tam bir karşılığı olmasa bile, “sihirli değnek” kavramı kastedilen manayı ifade etmektedir. Yani yazılım dünyasında ortaya çıkan yeni diller, yeni programlama yaklaşımları, yeni araçlar vs. hiç bir zaman sihirli bir değnek olmayacaklardır. Bu yenilikler yazılımı çok daha kolay hale getiremeyecekler, yazılımın devamlı değişken olan tabiatını daha durağan yapamayacaklar, yazılımın uyum sorununu ortadan kaldıramayacaklar ya da yazılımı görünür hale getiremeyeceklerdir.

Makalenin önemi, yazılım geliştirme kavramıyla alakalı ciddi soyutlamalar yapması ve bu soyutlamaları analitik olarak değerlendirmesindedir. Makale, kendisini okuyan her yazılımcının dünyasında yeni ufuklar açmıştır ve açmaya da devam etmektedir. Bu yüzden makalenin savunduğu iddialar, makalenin yayımlanmasından sonra “işte benim gümüş kurşunum bu” gibisinden yazılardan, yazılım konferanslarında konu ile ilgili panellere kadar pek çok şekilde tartışılmıştır. Yazılımcı olmak isteyen ya da olan herkesin bu makaleyi okuması ve üzerine kafa patlatması son derece elzemdir.

Yazarın makalesinde ileri sürdüğü iddiaları ispatlamak için vermiş olduğu örneklerin, o yılların tecrübe ve anlayışına uygun olduğu açıkça görülebilir. Fakat bu makalede ileri sürülen iddiaların artık geçersiz olduğu anlamına gelmez. Aksine makalenin yazılmış olduğu zamandan bugüne geçen 20 yılı aşkın sürede yazılım dünyasında yaşananlar, makalede ileri sürülen iddaları kuvvetlendirici pek çok yeni delil sağlamıştır. Şimdi bu dört asli özelliğe bir kere daha göz atalım.

Karmaşıklık: Yazılım doğası gereği karmaşıktır çünkü bir yazılımda ifade edilen durumlar diğer mühendislik uygulamalarına hatta bilgisayarlara göre bile sayıca çok daha fazladır. Yazılımlar diğer pek çok diğer mühendislik uygulamalarında olduğu gibi aynı parçaların farklı şekillerde bir araya getirilmesiyle oluşmazlar, dolayısıyla yazılımın büyümesi yeni parçalar demektir, aynı parçaların daha büyük ebatta olanlarının kullanılması değildir. Bir yazılım sistemini meydana getiren parçalar birbirleriyle doğrusal bir şekilde haberleşmezler, aralarındaki iletişim daha çok doğrusal olmayan bir şekilde gerçekleşir. Bu tür karmaşıklıklar yazılımı anlamayı, anlatmayı, geliştirmeyi ve test etmeyi zorlaştırır. Yazılımın doğasının bir parçası olan karmaşıklık yazılımı sadece teknik olarak zor kılmaz, yazılım projelerini yönetmeyi de zorlaştırır.

Yazılımlar, aradan geçen 20 küsür senede daha da karmaşık hale geldi. Bu durum, sadece yazılımların daha fazla module, satıra vs. sahip olması yani ebat açısından daha büyük hale gelmesiyle açıklanamaz. Aradan geçen sürede yazılımlar hayatın içine çok daha fazla girdi. Yazılımlar artık algoritmik olmaktan çok süreç odaklı. Yazılımlar günümüzde ezici bir çoğunlukla bir grup iş yapış şeklini ya da süreci hayata geçiriyor. İş süreçlerindeki akışların karmaşıklığı, iş kurallarının sayısı ve detayı, iş süreçlerine dahil olan kullanıcıların sayısı, sürece katılım şekli ve süreçle alakalı yetkileri, iş süreçlerini yerine getiren yazılımların karmaşıklığını ciddi bir şekilde arttırıyor. Yazılımların iş ve gündelik hayatın bu kadar içine girmesi, geçmişe göre daha sıradan kişilerin bu yazılımların kullanıcıları olması anlamına geliyor. Bu da yazlımın veriyi kullanıcıdan almasında daha dikkatli olmasını gerekli kılıyor; yazılımların kullanılabilirliği ciddi bir problem olabiliyor.

Topolojik açıdan zamanımızda üretilen yazılımlar, bundan 20 küsur öncesine göre çok daha dağınık (distributed). Yazılımların büyük çoğunluğu web üzerinden hizmet veriyor, ciddi bir kısmı web servislerini kullanıyor. Global bir köye dönüşen dünyamızda kıtalar arası işbirlikleri, dağınık entegrasyon projelerinin sayısını bir hayli arttırmış görünüyor. Dolayısıyla artık yazılımlar ağlarda çalışacak şekilde tasarlanıyor. Bu durum da haliyle karmaşıklığı arttırıyor.

Nesne merkezli dillerin gelişmesi ve yaygınlık kazanamasının, yazılımın karmaşıklığını yönetmede bize güç sağladığı açıktır. Nesne merkezli diller, gerçekliği soyutlayıp yazılım yapılarına aktarmada, nesne merkezli olmayanlara göre çok daha güçlüdürler. Nesne merkezli dillerin 1960’lı 70’li yıllarda Simula 67 ve Smalltalk ile gündeme gelmesine rağmen bu kadar yaygın kullanım alanı bulması 90’lı yılların ortasından ititbaren Java ile mümkün olmuştur. Bunun kanımca iki sebebi vardır: İlki, “Java Nedir?” başlıklı yazıda da kısaca açıklandığı gibi, zamanın yaygın olan nesne merkezli dili C++’ın çok aşağı seviyeli ve güvenirliği düşük bir dil olması yanında nesne yapılarını uygulamada yeterince açık olmayıp, ciddi bir nesne kültürü oluşturmaktan uzak kalmasıdır. İkincisi de ilkiyle ilgili olmakla birlikte, daha çok geliştirilen yazılımların hayatımıza ve iş dünyamıza ciddi bir şekilde girmiş olmasıyla alakalıdır.  Yazılımların gündelik hayatın içine girmesi, gerçekliği ifade etmede nesne yapılarını rahat bir şekilde uygulayabilmemizi gerekli kıldı. Bu durum da Java’nın, C++’ın yerini alma sürecini çok kısalttı.   Bu noktada, Java gibi hem nesne merkezli hem de platformdan bağımsız bir dilin özellikle sunucu ve mobil tarafta çok yaygın bir kullanım alanı kazanması ve platformlardaki farklılıkları soyutlaması, karmaşıklığı kesinlikle azaltmıştır. Öte taraftan yine Java ile açık kaynak kod felsefesini destekleyen irili ufaklı, Ruby ve benzeri pek çok dilde geliştirilen bileşen (component) ve çerçeve (framework) yapıları, yazılımcıların üretim hızlarını ve üretilen yazılmın kalitesini arttırmıştır.

Tasarım şablonlarının (design patterns) nesne merkezli dillerle birlikte yaygın bir şekilde kullanılır olması, mimari tabanlı yazılım tasarlama yaklaşımının yaygınlık kazanması, tasarım şablonlarını ve farklı mimari modelleri kullananan bileşen ve çerçevelerin pek çok yazılım projesinde değişik yoğunluklarda kullanılması, anlamayı kolaylaştırarak karmaşıklığı azaltmıştır. Bu yapıların yaygın bir şekilde kullanılması yazılımcılar arasında bir dil oluşturmuş ve iletişimi, tarif etmeyi ve aktarmayı daha kolay hale getirmiştir.

Yazılım elemanlarını modelleme notasyonu olarak standart hale gelmiş olan UML’in, yazılımı, projenin değişik safhalarında modellemek amaçlı kullanılır olması, karmaşıklığı yönetmede kolaylıklar sağlamıştır. Çünkü UML, yazılımın farklı safhalarında ortaya çıkan farklı kavramları, çok güçlü grafiksel soyutlamaları yardımıyla algılamamıza katkıda bulunmuş, bu yapıların iletişimini kolaylaştırmış, hatta çok teknik olmayan kişilerle bile bir iletişim köprüsü kurulmasına yardım etmiştir.

Yazılım projesininin başından sonuna kadar yönetilmesinde bir çerçeve çizen XP ya da UP gibi metodolojiler, projede neyin en zaman ve kim tarafından yapılacağını ve nelerin üretecileğini öğreterek karmaşıklığı azaltmaya yardım etmişlerdir. Yazlım geliştirmenin belli safhalarına hitap eden, örneğin kullanım şekli tabanlı ihtiyaç analizi (use case-based requirement analysis), cephe merkezli programlama (aspect-oriented programmming) ya da test güdümlü programlama (test-driven programming) gibi tekniklerin, ilgili safhalarda kolaylık sağladığı açıktır.

Öte taraftan bütün bu kavram ve tekniklerin, karmaşıklığın bir kısımını soyutlayıp, üzerlerini örtüp bizden uzak tutarken, hiçbir maliyetlerinin olmadığı düşünmek çok safça olur. Bu yapılar da yeterince karmaşıktır ve seçim, öğrenilme ve uygulanma konusunda fazladan yük gewtirdikleri de kesindir. Öncelikle hangi bileşene, hangi çerçeveye ya da hangi mimari ve metodolojik yaklaşıma ihtiyacınız olduğunu belirlemek başlı başına bir karmaşıklıktır. Bu konuda yazılımcıların yaklaşımı, genel olarak “daha önce başarıyla uyguladığından vazgeçme”dir. Bu konuda yapılacak yanlış bir seçimin projeyi doğrudan başarısızlığa götürebileceği de aşikardır. Benzer zorluk öğrenme konusunda da vardır. İşe yeni aldığınız yazılım mühendisiniz, kullandığınız tasarım şablonlarını, bileşen ve çerçeve yapılarını, uyguladığınız mimari ve metodolojik yaklaşımları biliyorsa, çok hızlı bir şekilde projenize girebilir demektir. Aksi taktirde ya bu yapıları öğrenmek için ona zaman tanıyacaksınız ya da hızlıca projeye dahil olup, bütün bunları yolda öğrenecek. Bu gibi yapıları iyi bir şekilde öğrenmenin, en az bir ciddi projede baştan sona kullanmakla mümkün olabileceği düşünülürse, karmaşıklığı bu yapılarla alt etmenin ciddi bir maliyeti olduğu ve bu maliyetin önemli bir kısmının da karmaşıklıktan oluştuğu açıktır.

Uyumluluk: Aradan geçen sürenin, yazılımların uyumlulukları konusunda yazılımcılara daha fazla sorumluluk yüklediği açıktır. Öncelikle yazılımların hayatımıza daha fazla girmesi, tipik bir projede var olan kullanıcı tipi ve entegrasyon ucu sayısını arttırdı, eskiden elle yapılan veri alışverişlerinin gerçek zamanlı (real-time) olmasını gerekli kıldı. Yazılımlar artık daha fazla çevre birimi ya da iç ve dış sistemle haberleşiyorlar. Ağ yapılarının gelişmesi, gerek Internet gerek ise intranette çalışan uygulamaların, birbirlerinden daha çok haberdar olmalarını gerektiriyor. Eskiden elle ya da email veya FTP gibi protokollarla yapılan veri aktarımları artık gerçek zamanlı yapılıyor. Bütün bunlar yazılımların kendisine uyum sağlayacağı daha çok ortamla ilişkide olması anlamına geliyor ki bu da yazılımların uyumluluk sorumluluklarını arttırıyor.

XML ve web servisleri gibi standartların geliştirilmiş olması, yazılımların kendileriyle haberleştikleri çevre birimlerinin eskiye göre nispeten daha standart arayüzlere sahip olmaları, uyumluluk konusunda yazılımcılara elbette yardım etmektedir. Fakat tüm bunlar günümüz yazılımlarının daha uyumlu olması gerektiği gerçeğini ortadan kaldırmamaktadırlar.

Değişebilirlik: Hayatın ve iş yaşamının hızlanması, değişimi, başarının ya da başarısızlığın en önemli faktörü haline getirdi. Değişimi yönetebilenler ayakta kalırlarken yönetemeyenlerin akibetleri, ne kadar köklü olurlarsa olsunlar, hep aynı son olmakta. Bu durum, hayatımıza ve iş dünyamıza olabildiğince giren yazılım sistemlerinin de zamanın bu hızlı akışına ve değişime ayak uydurmalarını gerektirmektedir. Bilişim teknolojileri, artık iş yapmanın bir olmazsa olmazı olduğuna göre, yazılımların üzerindeki değişim baskısı, eskisine göre çok daha fazla artmış durumdadır.

Nesne merkezli diller, kodlamadan çok bir düşünme ya da modelleme aracı olarak kullanıldıklarında, yazılımda değişimi öngörülen kısımları, değişmesi pek de muhtemel olmayan diğer kısımlardan yalıtacak yapılar sunmaktadır. Hangi durumlarda nasıl yalıtım sağlanacağı temel olarak tasarım şablonlarının konusudur ve “dörtlü çete”nin (Gang of Four, Erich Gamma, Richard Helm, Ralph Johnson ve John Vlissides) Design Patterns isimli kitabında ayrıntılı bir şekilde açılanmıştır. Java gibi nesne merkezli diller ile tasarım şablonlarının ve mimari tabanlı yazılım tasarım yaklaşımının yaygınlaşması, bileşen ve çerçeve kullanımının artması, yazılımcıların değişimi yönetebilmelerine yardımcı olmaktadır.

Groovy ve Ruby gibi dinamik tipli dillerin, Java gibi statik tipli dillerin kısıtlarını ortadan kaldırmak üzere geliştirilmesi ve yaygın kullanım alanı bulması, yazılımcıların değişimi daha kolay yönetebilmelerine imkan tanımıştır. Bu gibi dinamik tipli diller ile çalışma zamanında koda yapılan değişikliklerin derlenmesine gerek yoktur, yapılan değişiklikler yazılımın davranışında anında görülür. İş dünyasından gelen değişim baskıları bu gibi dinamik dillerin ortaya çıkmasını ve yaygın kullanım alanı bulmasını tetiklemiştir.

Java ya da .NET gibi platform dillerinin ortaya çıkmış olması, özellikle Java platformunda geliştirilen bileşen ve çerçeve yapılarının tekrar kullanım konusunda yazılım dünyasına umut dağıtıyor olması bir artı olmakla birlikte, çığ gibi büyüyen değişim karşısında tek başına değişime ayak uydurmanın yolu olması da pek gözükmemektedir. Yukarıda bahsedilen dinamik diller ile tasarım şablonları, bileşen ve çerçeve yapılarını projelerde rahat bir şekilde uygulayabilmek de ancak uzun süreli eğitim ve tecrübeden sonra mümkündür. Baskının zaten zaman konusunda olduğu günümüz yazılım projelerinde bu yapıları uygulamak için yazılımcıların fazla fırsat bulamadıkları da açıktır.

UML gibi modelleme notasyonlarının yaygın kullanımı ve yazılımların artık bu notasyonlar ile belgelenmesi, yazılımların sadece karmaşıklıklarını yönetmemize yardımcı olmamış aynı zamanda yazılım içine gömülen bilgiyi yazılımın dışına çıkartarak, yazılım değişmesini yönetmeyi kolaylaştırmıştır. Fakat, yukarıdaki paragrafta ifade edilen negatif etkenler bu konuda da geçerlidir.

Görünmezlik: Yazılımlar görünmez olmaya devam ediyorlar. Yazılımı görünür kılmak çok da mümkün olmasa da yazılım elemanlarını ya da yazılımın değişik yönlerini gözde canlandırılabilir yapmak mümkündür. UML gibi notasyon dilleri, sahip oldukları güçlü soyutlamalar sayesinde, yazılımın farklı yönlerini daha rahat algılanır ve anlatılır hale getirmişlerdir.

Yukarıdaki paragraflarda bahsedilen tasarım şablonları, mimari tabanlı yaklaşım, bileşen ve çerçeveler de aslında yazılımlarla alakalı çok güçlü soyutlamalar barındırmakta ve yazılımı tahayyül etme gücümüzü arttırmaktadırlar. Fakat bu yapıların kendilerinin aynı zamanda, öğrenme ve başarılı bir şekilde uygulanma sürecinde ciddi bir görünmezlik yaratmakta olduğu da gözden kaçırılmamalıdır. Yukarıda da anlatıldığı gibi bu yapıları uygulayabilmenin gerektirdiği bilgi, tecrübe ve zaman da genelde yazılım projelerinin en eksik taraflarını oluşturmaktadır.

 

Toplam görüntülenme sayısı: 2783

26 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
27 Kasım 2009

Gümüş Kurşun Yok: Yazılım Mühendisliği’nin Asli ve Arızi Özellikleri – I

Akin Yazılım Mühendisliği Frederick Brooks, No Silver Bullet, yazılım geliştirme, Yazılım Mühendisliği, yazılımın doğası, yazılımın zorlukları

Gümüş Kurşun Yok: Yazılım Mühendisliği’nin Asli ve Arızi Özellikleri – I

Frederick P. Brooks, Jr.

(Bu yazı, Frederick Brooks’un IEEE Computer dergisinin Nisan 1987 sayısında yayınlanmış olan “No Silver Bullet: Essence and Accidents of Software Engineering“ başlıklı makalesinin ilk kısmının Türkçe çevirisidir. (Bu makaleye buradan ve buradan ulaşabilirsiniz.) Geri kalan kısmı da çevrildikçe burada yayınlanacaktır. Çevirinin PDF dosyasına buradan ya da buradan ulaşabilirsiniz. Çevirideki her türlü hata benimdir. Öneri ve eleştirileriniz için akin@javaturk.org adresinden bana ulaşabilirsiniz.)

Halk kültürümüzün kabuslarında ortaya çıkan canavarların en çok korkutanı kurt adamlardır, çünkü onlar, tanıdık bir sima iken, aniden dehşet verici bir hale dönüşürler. Bu yaratıklar için insanlar da onları yere serecek gümüşten yapılmış kurşun ararlar.

Benzer şekilde yazılım projeleri de, en azından teknik olmayan yöneticiler için aynı karakteri taşırlar;  ilk başta genelde masum görünüşlüdürler ve herşey yolunda gibidir ama tutturulamamış planlara, aşılmış bütçelere ve hatalı ürünlere sahip bir canavara dönüşeme yeteneğine sahiptirler. Bu yüzden yazılım projeleri için de, aynı donanım maliyetlerindeki düşüş hızında bir maliyet düşüşü sağlayacak, gümüş bir kurşun arayan, umutsuz çığlıkları duyar dururuz.

Fakat önümüzdeki 10 yıllık ufka baktığımızda herhangi bir gümüş kurşun görünmemektedir. İster teknolojide isterse yönetim tekniklerinde, üretkenlik, güvenirlik ve basitlikte, 10 katlık bile bir ilerleme sağlayacak bir gelişmenin olması mümkün değildir. Bu makalede, yazılım problemlerinin tabiatını ve teklif edilen kurşunların özelliklerini inceleyerek bunun neden böyle olduğunu göstemeye çalışacağım.

Öte taraftan, şüphecilik karamsarlık değildir. Her ne kadar heyecan verici buluşlar olmasa ve böyle bir şeyin zaten yazılımın doğasıyla çeliştiğini düşünsem de pek çok cesaret verici yenilikler olmaktadır. Bu yenilikleri geliştirmek, yaymak ve kullanmak konusunda dispilinli ve kararlı olmak, 10 katlık bir gelişmeyi sağlamalıdır. Bu konuda müthiş bir yol olmasa da en azından yol vardır.

Hastalığı ortadan kaldırmaya ilk adım, şeytanlarlarla ilgili teorileri bir kenara bırakıp mikrop teorisine dönmektir. Yani ilk adım, umudun başı olarak, sihirli çözümlerden medet ummayı bırakmaktır. Bu konuda söylenebilecek şey, ilerlemenin büyük gayretlerle, ancak adım adım olacağı ve temizliğe, kararlı ve aralıksız bir özenin verilmesinin gerektiğidir. Yazılım mühendisliği dünyasında bugün olan biten de budur.

Zor Olmak Zorunda mı? Asli Zorluklar

Gümüş bir kurşunun olmaması sadece şu an görünürde olan birşey değildir, yazılımın doğası, onun gelecekte de olmasını pek de ihtimal dahilinde kılmamaktadır. Elektroniğin, tranzistörlerin ve büyük çaplı entegre devrelerin bilgisayar donanımı için yaptığını hiçbir buluş yazılımın üretkenliği, güvenirliği ve basitliği için yapmayacaktır. Hiç bir zaman, her iki yılda bir, iki katına çıkan kazanımlar göremeyeceğiz.

Birincisi, şu teslim edilmelidir ki, anormallik yazılımdaki gelişmenin yavaşlığı değil, bilgisayar donanımındaki ilerlemenin çok hızlı oluşundadır. Medeniyetin başlangıcından bu yana hiç bir teknoloji 30 yılda 1 milyon katında bir performans kazanımı elde edemedi. Hiç bir başka teknolojide ileri performans ile düşük maliyet arasında bir seçimde bulunulamaz. Bütün bu kazanımlar, bilgisayar üretiminin montaj endüstrisi olmaktan çıkıp bir süreç endüstrisine dönüşmesinin sonucudur.

İkinci olarak, yazılım teknolojisinde ne hızda bir ilerleme umabileceğimizi görmek için bu teknolojilerin zorluklarını inceleyelim. Aristo’ya uyarak bu zorlukları asli yani yazılımın doğasında var olanlar ile arızi yani bugün yazılımın üretiminde olan ama aslında doğasında olmayanlar olmak üzere ikiye ayırıyorum.

Bir yazılım varlığının aslı, içiçe geçmiş kavramlardan oluşmuş bir yapı olmasıdır: Veri kümeleri, veriler arasındaki ilişkiler, algoritmalar ve fonksiyonların çağrıları. Bu asıl, böyle kavramsal bir yapının, pek çok farklı görünümün altındaki aynı yapı olmasından dolayı, soyuttur. Yine de böyle bir yapı yüksek bir kesinlikte ve zengin bir detaydadır.

İnancım şudur ki yazılım inşa etmenin zor tarafı böyle kavramsal bir yapıyı, tarif etmek, tasarlamak ve test etmektir, onu sunma/oluşturma eforu ya da sunumun/oluşturulanın olması gerekene sadakatini test etmek değildir. Hala pek çok sözdizim hatası yapıyoruz ama emin olun ki onlar pek çok sistemdeki kavramsal hatalarla kıyaslanamayacak kadar basit şeylerdir.

Eğer bu doğruysa, yazılım inşa etmek her zaman zor olacaktır. Tabiati itibariyle de gümüş bir kurşun hiçbir zaman olmayacaktır.

Şimdi de modern yazılım sistemlerinin bu indirgenemez aslının doğal özelliklerine bir bakalım: Karmaşıklık, uyumluluk, değişebilirlik ve görünmezlik.

Karmaşıklık: Yazılım varlıkları, belki de büyüklük itibarıyla diğer insan yapılarından daha karmaşıktırlar çünkü hiçbir parçası birbirinin benzeri değildir (en azından dilin ifadelerinin üzerindeki yapılarda). Zaten benzer olsalar, bu iki benzer parçayı – açık ya da kapalı – tek bir yordam olarak birleştirirdik. Bu açıdan bakıldığında yazılım sistemleri, tekrarlı parçaların bir arada olduğu bilgisayarlar, binalar ya da otomobillerden, temelden ayrılır.

Dijital bilgisayarlar zaten insanların bina ettiği pek çok şeyden daha karmaşıktır: Örneğin çok fazla sayıda durumları vardır. Bu onları anlamayı, anlatmayı ve test etmeyi zaten zor kılar. Yazılım sistemleri ise bilgisayarlardan onlarca kat daha fazla duruma sahiptirler.

Benzer şekilde bir yazılım varlığını büyütmek sadece aynı elemanların daha büyük ebattakilerini tekrarlamak değildir, farklı elemanlarla sayıca büyümek demektir. Pek çok durumda elemanlar birbirleriyle doğrusal olmayan bir şekilde iletişimde bulunurlar ve bütünün karmaşıklığı, doğrusal iletişimde oldukları duruma göre çok daha fazla artar.

Yazılımın karmaşıklığı asli bir özelliktir, arizi değildir. Bu yüzden bir yazılım varlığının karmaşıklığını ortadan kaldıran bir tanım, çoğu zaman onun aslını da ortadan kaldırır. Üç yüz senedir matematik ve fizik bilimleri, modellerden özellikler elde edip, bu özellikleri deneyle test ederek, karmaşık olayların basitleştirilmiş modellerini yapıp ciddi ilerlemeler elde ettiler. Bu paradigma başarılı oldu çünkü modellerde  önem verilmeyen karmaşıklıklar, ilgili olayın asli özelliklerinden değildi. Karmaşıklıklar asli olduğunda başarılı olamazdı.

Yazılım ürünleri geliştirmedeki klasik sorunların pek çoğu, bu asli karmaşıklıktan ve ebata göre doğrusal olmayan büyümeden kaynaklanmaktadır. Karmaşıklıktan takım üyeleri arasındaki iletişimin zorluğu ortaya çıkmaktadır ki bu da ürün hatalarına, aşılmış bütçelere ve gecikmiş planlara yol açmaktadır. Karmaşıklıktan, programın, olması muhtemel bütün durumlarını ortaya koymanın zorluğu, dolayısıyla da bunları daha az seviyede bir anlama ortaya çıkmaktadır ki bu da güvenirliği ortadan kaldırmaktadır. Fonksiyondaki karmaşıklık, fonksiyonu çağırmada zorluğa yol açar ki bu da programları kullanmayı zorlaştırır. Yapıların karmaşıklığından, yan etki oluşturmaksızın programları yeni fonksiyonlara sahip olacak şekilde genişletmenin zorluğu çıkar. Yapıların karmaşıklığından, gözde canlandırılamayan durumlar oluşur ki bunlar da güvenlik açıklarına sebep olur.

Karmaşıklıktan sadece teknik sorunlar çıkmaz, yönetim sorunları da baş gösterir. Karmaşıklık genel bakışı zor hale getirir ki bu durum da kavramsal tutarlılığa engel olur. Karmaşıklık bütün sıkıntılı noktaların bulunup kontrol altına alınmasını zorlaştırır. Karmaşıklık, öğrenme ve anlama konusunda o kadar büyük bir yük oluşturur ki çalışanların işten ayrılmaları bir yıkım haline gelir.

Uyumluluk: Karmaşıklıkla karşılaşma noktasında yazılımcılar yalnız değillerdir. Fizikçiler “temel” parçaçık seviyesindeki son derece karmaşık nesnelerle uğraşırlar. Fakat bir fizikçi, kuarklarda olsun, birleşik alan teorilerinde olsun hepsi için genel geçer prensiplerin bulunacagına dair sağlam bir inançla çalışır. Einstein, doğanın basitleştirilmiş açıklamalarının olması gerektiğini çünkü Tanrı’nın kaprisli ya da rastgele davranmayacağını ileri sürmüştü.

Böyle bir inanç, bir yazılım mühendisini kesinlikle rahatlatmaz. Çünkü üstesinden gelmek zorunda olduğu karmaşıklığın büyük çoğunluğu rastgele karmaşıklıktır ki pek çok insani kurum ya da sistem tarafından mantıksızca oluşturulmuştur ve yazılım mühendisinin arayüzleri bu yapılarla uyum içinde çalışmalıdır. Yazılım mühendisinin geliştirdiği bu arayüzler, arayüzden arayüze, zamandan zamana değişir ama bu durumun sebebi ihtiyaçlar değildir, sadece Tanrı yerine farklı kişiler tarafından tasarlanmış olmalarıdır.

Pek çok durumda yazılım uyumlu olmalıdır çünkü sahneye en son gelen odur. Diğer pek çok durumda da, yazılımın uyum  yeteneğinin yüksek olduğu düşünüldüğü için uyumlu olmak zorundadır. Fakat bütün bu durumlarda karmaşıklığın büyük çoğunluğu, diğer arayüzlere uyumdan kaynaklanmaktadır ki böyle bir karmaşıklık sadece yazılımın tekrardan tasarlanmasıyla basitleştirilemez.

Değişebilirlik: Yazılım varlıkları sürekli olarak değişim baskısıyla karşı karşıyadırlar. Tabi ki binalar, arabalar ve bilgisayarlar da öyledir. Fakat imal edilen şeyler imalattan sonra çok seyrek değişirler; ya daha sonraki modellerle yer değiştirirler, ya da asli özellikleri, aynı temel tasarımla üretilen sonraki kopyalarının içine gömülür. Otomobillerin geri çağrılması son derece nadirdir; piyasaya yayılımış bilgisayarların değişmesi de pek sık olmaz. Bu ikisi durum da, piyasaya yayılımış yazılımların değişmesinden çok daha nadiren olur.

Bu durum bir yönüyle, bir sistemin yazılımının, o sistemin fonksiyonlarını meydana getirmesi ve fonksiyonların da değişimin baskısını en fazla hisseden taraf olmasındadır. Bu durum diğer bir yönüyle de yazılımın daha kolay değiştirilebilmesindendir, çünkü yazılım tamamen zihinseldir ve sınırsızca değiştirilebilir. Gerçekte binalar da değişir, ama değişimin yüksek maliyeti ki herkes tarafından bilinir, değiştireceklerin isteklerini kursaklarında bırakır.

Bütün başarılı yazılımlar değişir. Burada iki süreç vardır. İlki, yazılım ürünü faydalı bulunur, insanlar da onu esas alanının dışındaki ya da kenarındaki durumlar için denerler. Fonksiyonlarını genişletme baskısı daha çok, temel fonksiyonlarını seven ve kullanan kullanıcılardan gelir.

İkincisi, başarılı yazılım, kendisi için yazıldığı makinanın normal hayatından çok daha uzun yaşar. Yeni bilgisayarlar olmasa bile yeni diskler, yeni ekranlar, yeni yazıcılar gelmeye devam eder  ve yazılım, bütün bu yeni olanaklar getiren yeni araçlara uyum sağlamak zorundadır.

Kısaca yazılım ürünü, uygulamalar, kullanıcılar, kurallar ve makina araçlarının kültürel matrisinde gömülü olarak bulunmaktadır. Bunlar sürekli değiştiğinden, onlardaki değişimler ister istemez yazılım ürününü de değişmeye zorlayacaktır.

Görünmezlik: Yazılım görünmez ve gözde canlandırılamaz. Geometrik soyutlamalar güçlü araçlardır. Bir binanın kat planı, hem mimarın hem de müşterinin, mekanı, trafik akışlarını, görünümü değerlendirmelerine yardımcı olur. Çelişkiler ve unutulanlar açığa çıkar. Mekanik parçaların küçültülmüş çizimleri ve moleküllerin şekilleri, her ne kadar soyutlama olsalar da, aynı amaca hizmet eder. Geometrik gerçeklik, geometrik bir soyutlamayla yakalanır.

Yazılımın gerçekliği tabiati itibariyle mekanda gömülü değildir. Dolayısıyla da yazılım, arazilerin haritaları, silikon yongaların diyagramları, bilgisayarların bağlantı şemaları gibi hazır bir geometrik sunuma sahip değildir. Yazılım yapılarının diyagramlarını çizmeye girişir girişmez,  bir değil ama birkaç tane birbiri üzerine getirilmiş genel yönlü grafikler elde ederiz. Birkaç graifk kontrol akışını, data akışını, bağımlılık şablonlarını, zamandaki adımları, isim-uzay ilişkilerini  temsil eder. Bu grafikler düzlemsel bile değildir, çok daha az hiyerarşiktir. Gerçekte böyle bir yapının üzerinde kavramsal bir kontrol oluşturmanın yollarından birisi bir ya da daha fazla grafiğin hiyerarşik olması için bağlantıları kesmeye çalışmaktır. [1]

Yazılım yapılarını kısıtlamak ve basitleştirmek yolundaki ilerlemelere rağmen yazılım yapıları, doğaları itibariyle canlandırılamaz olamaya devam edecektir ve bu durum da zihnin, en güçlü kavramsal araçlarının bir kısımını kullanmasına imkan vermeyecektir.

Böyle bir eksiklik sadece bir zihindeki tasarım sürecini engellemekle kalmaz aynı zamanda birden fazla zihin arasındaki iletişimi de sekteye uğratır.

(Çevirinin devamı gelecektir.)

Toplam görüntülenme sayısı: 3363

18 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
06 Kasım 2009

Java Nedir?

Akin Java Java, nesne, programlama

Bu konu ile ilgili sunuma buradan ukaşabilirsiniz. Ayrıca sunumu PDF dosyası olarak buradan indirebilirsiniz.

Java’nın ne olduğunu anlamanın en iyi yöntemi bence, Sun’ın, 1995’te, Java’nın ilk günlerinde  yayınlamış olduğu  ve halen http://java.sun.com/docs/overviews/java/java-overview-1.html adresinden ulaşılabilen, kısa ve tanıtıcı olan yazıyı okumaktır. Bu yazının hemen başında, 2. paragrafında şöyle bir cümle vardır:

Java: A simple, object-oriented, network-savvy, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, dynamic language.

Yani

Java: basit, nesne merkezli, ağlarda yetkin, yorumlanan, sağlam (gürbüz), güvenli, mimari olarak tarafsız, taşınabilen, yüksek başarımlı/performanslı, çok kanallı, dinamik bir dil.

Ufff bu ne? Bizim sektörümüzde bu kadar önemli ve etkileyici kelimeyi bir araya getirebilen başka ne vardır bilmiyorum. Java’nın, bu tanımdaki sıfatların hangisini ne kadar haiz olduğu tartışılır ama sonuçta bu tanım üzerinden gitmek, kanımca Java’yı anlaşılır kılmaktadır. Bu yüzden ben ilk öğrenenlere hep bu cümle üzerinden giderek Java’yı anlatmışımdır. Şimdi de öyle yapacağım ve bu özellikleri tek tek ele alacağım:

Basit: Doğrusu, Java o kadar da basit değildir. Aslında, Java’nın en temelde, ataları olarak görebileceğimiz C ve C++’ın sıkıntılı ve zorluk çıkaran taraflarının budanarak  tasarlandığını göz önüne aldığımızda, bu özelliğin “basit” (simple) yerine “daha basit” (simpler) şeklinde ifade edilmesinin daha uygun olacağını farkederiz. Evet Java, çıktığı yıllarda C ve C++’ın doldurmakta olduğu genel amaçlı uygulama geliştirme dili olma rolünü devralmak için, onlara göre daha basit, bu dillerin geliştiricilerine çıkardığı zorlukları çıkarmayan, çalışma zamanında (run-time) yol açtığı sıkıntıları önlemeyi amaçlayan bir dil olarak tasarlandı. Neydi bu Java’nın problemli olarak görüp ya hiç kapsamadığı ya da farklı bir şekilde ele aldığı noktalar?

  • Otomatik bellek yönetimi: Java zaten nesne merkezli olduğu için, çokça oluşturulan nesnelerin sistemin belleğini hızlıca doldurmaları sıkça görülen bir durumdur. Bu nesnelerin kullanımdan çıktıkları zaman sistem belleğine geri kazandırılmaları, Java’nın çöp toplayıcısı (garbage collector) sayesinde, otomatik olarak yapılır. Kullanılmayan nesneleri sistemin belleğine geri kazandırmayı otomatik olarak yapmayıp bunu geliştiricinin insiyatifine bırakan C++’da bellek kaçakları (memory leak) çok sıklıkla görülen bir problemdir. Zaten C++’a göre nesne kullanımını çok daha ön plana çıkaran Java’nın bellek yönetiminde böyle bir yöntem izlemesinin faydalarını en başından bu yana görmekteyiz.
  • Pointer kullanımı: Bellekteki nesnelerin adreslerini tutan pointerların, pointer aritmetiği gibi konulardan arındırılarak, sadece nesnelerin referansı haline getirilmeleri, bu konu ile alakalı gündeme gelen pek çok zorluğu ortadan kaldırmış ve Java’yı donanımdan daha uzakta bir noktaya yerleştirip, daha yüksek seviyeli (high-level) bir dil yapmıştır.
  • Operatör overloading: + ya da % gibi operatörlerin nerelerde nasıl kullanılabileceğinin daha tasarım zamanında, Java’yı tasarlayanlar tarafından belirlenip, bu operatörlerin geliştiriciler tarafından farklı şekillerde kullanılabilmesinin önüne geçilmesi, Java’yı kesinlikle çok daha basit kılmıştır.
  • Çoklu kalıtım (multiple inheritance) ve otomatik tip çevrimleri (automatic type conversion ya da type coercion) gibi irili ufaklı pek çok konu ya dil dışında tutulmuş ya da kullanıcısına sıkıntı çıkarmayacak şekilde dilin altyapısında çözülmüştür.

Görüldüğü gibi, Java, C ve C++’ın kullanıcılarına sağladığı ama aynı zamanda sıkıntılara da yol açan pek çok özelliği ya içinde barındırmamayı ya da derleyici (compiler) veya yorumlayıcı (interpreter) gibi yapıların içinde, konuyu çok da fazla geliştiricinin önüne getirmeden halletmeyi seçmiştir.

Bu seçimler daha sonra da ifade edileceği gibi Java’nın daha basit olmasından öte, dilin gerek derleme zamanında (compile time) gerek ise çalışma zamanında (run-time) daha sağlıklı çalışabilmesiyle alakalıdır. Bu yüzden mesela C/C++’ın otomatik olarak yaptığı tip çevrimlerinin daraltan tiplerinde (yani long gibi daha geniş bir tipten int gibi daha dar bir tipe gitme) Java’nın çevrimi otomatik yapmayıp, geliştiricinin insiyatifini istemesi ve çevirme (cast) operatörünü kullanmasını gerekli kılması, tamamen daha ihtiyatlı davranma tercihinden dolayıdır. Aynı konu Java’nın tipler konusunda çok daha hassas olmasında da ortaya çıkar. Bu anlamda Java, C/C++’a göre tip hiyerarşisine  ve aralarındaki ilişkilere önem veren (strongly-typed) bir dildir.

Özet olarak Java’da, dili daha sade ve rahat kullanılır yapmak için özellikle aşağı seviyeli (low-level) pek çok özelliği budanırken, gerekli mekanizmalar derleyici ve yorumlayıcı seviyesine indirilerek, belki çok daha karşmaşık bir altyapı oluşturulmuş ama öğrenim ve kullanım kolaylığı sağlanmıştır.

Tabi, C/C++ kültürünün çok yaygın olmadığı ülkemizde yukarıda anlatılanların ne kadar anlam ifade ettiği de tartışılır. Ama bütün bunların en azından Java’yı doğru bir şekilde değerlendirmede gerek tarihi bilgi gerek ise entellektüel tartışma açısından önemlidir.

Nesne merkezli: Kanımca Java’nın en önemli özelliği nesne-merkezli (object-oriented) olmasıdır. Nesne-merkezli olmak demek program mantığı açısından en temel soyutlama (abstraction) biriminin nesne olması demektir. Birazdan açıklanacağı gibi bu o kadar temel bir farktır ki, programlamaya yaklaşımınızı her yönüyle değiştirir. Dolayısıyla nesne-merkezli programlama bir paradigmadır. Benzer şekilde nesne-merkezli yanında, programlamaya, prosedürel (procedural),  fonksiyonel (functional) ya da mantıksal (logical) yaklaşımlar da vardır ve bütün bu yaklaşımlar da birer paradigma oluşturacak şekilde bir düşünce sistemine sahiptirler. Bu yaklaşımlar arasında en yaygın olan iki tanesi, nesne-merkezli ve prosedürel yaklaşımdır. Hatta nesne-merkezli dillerin hayatımıza bu kadar çok girmesinden önce en yaygın paradigma prosedürel olandı ve bu dünyanın en tipik temsilcisi olan dil de “C” idi. C gibi Pascal, Fortran, Cobol  gibi diller de prosedürel dünya içerisinde yer almakta olup halen yoğun bir şekilde kullanılmaktadırlar.

Nesne-merkezli yaklaşım ile prosedürel yaklaşım arasındaki en temel fark, procedürel bir dilin en temel soyutlama biriminin bir fonksiyon olmasına karşın, nesne-merkezli bir dilde bu birimin fonksiyondan nesne seviyesine çıkarılmış olmasıdır. Böyle bir farkın detaylı bir şekilde nelere mal olduğu bu yazının en azından şimdilik bir konusu olmamakla birlikte, bu iki yaklaşımın en tipik özelliklerini ifade etmek gereklidir.

Prosedürel dillerde probleme yaklaşım, dil yardımıyla bilgisayara verilecek olan ardışıl komutlarla olur. Bu ardışıl komutlar ki genel olarak statement olarak ifade edilir, bir yemeğin tarifindeki gibi sırayla ifade edilirler ve bilgisayar bunları yerine getirdiğinde problem çözülmüş olur. İşte bu yüzden bu sınıftaki dillere emreden anlamında imperative diller de denir. İlgili komutlar bir araya gelerek daha büyük bir komut birimi olan prosedürler oluşur.   Prosedür, farklı dillerde fonksiyon (function), metot (method), rutin (routine) sabrutin (subroutine) vb. kelimelerde adlandırılan bir kavram olup, Türkçe’de de bazen “yordam” olarak da ifade edilmektedir. (Biz bu yazılarda bu kavramları birbiri yerine geçecek şekilde kullanıyor olmakla birlikte nesne merkezli diller sözkonusu olduğunda metot demeyi tercih edeceğiz.) Prosedürler, değişken denen veri yapıları üzerinde çalışırlar ve çalışmalarının sonuçlarını yine bu veri yapılarında saklarlar.

Nesne merkezli diller de fonksiyonları ve değişkenleri bir araya getirirler fakat prosedürel dillerden en temel farkları, bir araya getirdikleri fonksiyon ve değişkenlerin, insan zihninin kendisine odaklandığı herhangi bir “şey”i betimlemesidir.  Dolayısıyla nesne merkezli diller bir problemi adım adım çözmeye odaklanmaz onun yerine o problemde var olan “şey”leri yani nesneleri bulup onları özellikleri ve davranışlarıyla betimlemeye çalışır. Nesne merkezli teori, fiziksel olsun ya da sadece zihinsel olsun, evrende var olan varlıkları bu yolla, oldukları gibi tanımlamak, aralarındaki ilişkileri doğru bir şekilde resmetmek ve dolayısıyla da bir problemi gerçekte olduğu gibi yazılım dünyasına aktarmak iddiasındadır.

Nesne merkezli bir dil olarak da Java, iş modellerimizi yazılıma aktarmakta, atası olan C ve C++’a göre çok daha başarılıdır.

Ağlarda yetkin: Ağlar, bilgi teknolojileri dünyasının en başından bu yana parçası olmakla beraber, hayatımıza bu girişi 90’lı yılların ilk yarısında başlayan Internet devrimiyle akıl almaz bir şekilde hızlanmıştır. Bu yılların Java’nın doğuş yılları olduğu gerçeği göz önüne alınırsa, Java’nın kendini neden ağlarda bu kadar yetkin kıldığının cevabı da ortaya çıkmış olur. Zaten Java’nın yaratıcısı olan Sun şirketinin de sloganı “The Network is the Computer” yani “Ağ Bilgisayardır”dır. Ağ yapılarıyla alakalı böyle bir vizyona sahip olan ve bunu geliştirmekte olduğu Unix sistemlerinde başarıyla uygulayan Sun’ın, Java’yı, 90’lı yıllarda hızla gelişmekte olan Internet ve web teknolojilerine uygun bir yapıda, ağlar üzerinde rahatça çalışabilecek ilk dil olarak kurgulaması da son derece tabidir.

Bu noktada Java’nın sadece en basit ve temel şekliyle soket programlamaya imkan vermekle kalmayıp, Web’in üzerinde çalıştığı HTTP ve HTTPS protokolları başta olmak üzere FTP ve Telnet gibi diğer protokolları, web servislerini, uzak nesnelere (remote objects)  ulaşmayı destekleyen protokolları rahatça kullanır kılmasından bahsetmek gereklidir. Java’nın nesne-merkezli yapısıyla, ağ programlamayı nesne seviyesine çıkarması ve örneğin uzak nesnelere rahatça ulaşıp onları yerel nesneler gibi görmesi, eskiden çok zaman alıcı olarak görülen bu işlerleri harcıalem hale getirmiştir.

Yorumlanan: Java yorumlanan bir dildir. Aslında bu, bu konudaki gerçeğin sadece bir yüzüdür. Çünkü Java hem derlenir (compiled) hem de yorumlanır (interpreted). Derlemek (compilation) aslında bir çevrim işidir, kodu bir formdan başka bir forma çevirmektir. Genelde de kaynak kodu, derleyici (compiler) tarafından üzerinde bulunulan platformun makina koduna çevirmeye denir öyle ki bu çevrim sonunda ortaya çıkan kod çalışabilen (executable) bir koddur. Yorumlanan dillerde böyle bir çevrim ancak çalışma zamanında ve yorumlayıcı (interpreter) tarafından yapılır.

Bu iki yaklaşımın farkları ve avantaj ve dezavantajları bu yazının konusu değildir. Fakat Java’nın neden hem derlenen hem de yorumlanan bir dil olduğunu ifade etmek gereklidir. “java” uzantılı bir dosyada bulunan Java kaynak kodu Java derleyicisi tarafından adına bytekod (bytecode) denen ve sanal bir makinanın (Java Virtual Machine ya da kısaca JVM) koduna çevrilir. Üretilen bytekodlar “class” uzantılı dosyalarda bulunurlar. JVM, her platform için ayrıdır ve genel olarak o platformu üreticileri tarafından geliştirilp piyasaya sunulur. Java’da derleme zamanında (compile-time) elde edilen bytekodlar her platform için standart ve aynıdır. Yani Java programcısı JVM için kod yazar. JVM ise bytekodları, çalışma zamanında (run-time) üzerinde bulunduğu platformun makina diline çevirir ve çalıştırır.

Böyle bir iki fazlı yaklaşım ne sağlar? Java programcısına, programlama yaparken, kodunun çalışacağı son ortamı bilmek zorunda olmama imkanı verir. Platformların temelde merkezi işlem birimi (CPU) ve diğer çevre birimlerinden oluşan donanım ile bu donanım üzerinde çalışan işletim sisteminden (OS) oluştuğu ve farklı platformların donanım ve yazılım yapılarının birbirlerinden çok farklı oldukları düşünüldüğünde, hem derlenen hem de yorumlanan bir yapıda olma ve bunu JVM isimli sanal bir yapı üzerinden gerçekleştirme, Java programcılarına, platformdan bağımsız kod yazma lüksünü vermektedir ki bu durum Java’nın bir diğer özelliğini, yani taşınabilir olmasını sağlar.

Taşınabilir: Java kodları herhangi bir platformdan bağımsız olarak yazılır ve çalıştırılır. Bu, Java kodlarının bir platformdan  diğerine herhangi bir değişiklik olmaksızın, hatta tekrar derlenmeksizin çalıştırılabilmesi imkanını verir. Bu durum, Java’nın platformlardandan bağımsız ve standartlar üzerine kurgulanmış yapısı sayesindedir.

Java’da kaynak kodları JVM için yazılır, çalışma-zamanı ortamı için değil. JSM, platform ile Java programcısı arasına girerek, programcının çalışma-zamanıyla platformu bilme zorunluluğunu ortadan kaldırır. JVM’ler aynı kodu farklı platformlar üzerinde çalışma-zamanında yorumlayarak çalıştırırlar. Bu noktada JVM, programcıya bakan tarafı Java standartları ve uygulama programlama arayüzleri (Application Programming Interface, API) ile oluşturulmuş ama diğer tarafı platform ile konuşan bir ara katman ya da adaptör olarak düşünülebilir.  Dolayısıyla, JVM’in Java kaynak kodlarıyla çalışma-zamanı platformu arasında bir katman oluşturması, Java kodlarını çalışma-zamanındaki platformdan bağımsız kılar.

Ayrıca, Java’nın yapısı, veri yapıları da dahil olmak üzere  tarifnameler (specification) ile belirlenir.. Dolayısıyla en temelde aynı Java kodu farklı platformlarda aynı davranışı gösterir. Java’yı oluşturan altyapıların tarifnamaleri, platformlara özel yapılar içermez ve hangi konuda nasıl davranması gerektiği detaylı bir şekilde açıklanır. Bu yüzden örneğin Java’nın en temel veri tiplerinden olan int verisinin bütün platformlarda 32 bittir ve aynı şekilde davranır. Aksi taktirde, Java da, C ve C++ dillerindeki gibi taşınabilirliği önleyen platforma özel yapılara sahip olurdu. Ayrıca C ve C++ gibi pek çok dil, tariflerindeki açık bırakılan noktalarda farklı ürünlerin farklı davranmaları sonucu platformlar arasında taşınamaz bir kod yapısına sahiptir.

Taşınabilirlik özelliği sayesinde, Java programcıları bilerek ya da bilmeyerek, dosya yollarındaki ayıraçları (“/”, “\” ya da “:” gibi) kodun içine gömmek gibi hatalar yapmadıkları sürece, bir kurumsal yazılımın, örneğin bir Unix platformundan Windows platformuna taşınması hiç bir tekrar derleme gerektirmeyecek ve sadece bir kaç saat içinde gerçekleştirilebilecektir. Java’nın ilk günlerinde bu durumu ifade eden slogan “Write Once, Run Anywhere” ya da WORA idi. Yani “Bir Kere Yaz, Heryerde Çalıştır”. Tabi umulmadık durumlarla karşılaşmamak için Java’cılar bu sloganı, daha ihtiyatlı olan “slogan “Write Once, Test Anywhere”e yani “Bir Kere Yaz, Heryerde Test Et”e çevirmişlerdir.

Sağlam: Sağlamlıktan kastedilen, kodun, çalışma zamanında oluşabilecek sıradışı durumlarda bile kırılmadan, göçmeden çalışmasına devam edebilme yeteneğidir. Java’nın standartlar üzerine kurulu ve bir sanal makina üzerinde çalışıyor olması, gerek derleme zamanında gerek ise çalışma zamanında pek çok kontrolu rahatça yapabilmesini sağlamaktadır. Örneğin C ve C++’ta çalışma zamanında en sık problem üreten konu olan, programcının belleği göstergeler (pointer) üzerinden açık adreslemeyle yönetmesi ve gösterge aritmetiği, Java’da tamamen JVM’in sorumluluğundadır. Java programcısının belleği yönetirken kullandığı göstergeler ki Java terminolojisinde referans (reference) olarak adlandırılır, sadece soyut göstergelerdir, Java programcısına sadece nesneye ve özellik ve davranışlarına ulaşma imkanı sağlar, daha ötesini değil. Java’nın tip yapılarına ayrı bir dikkat göstermesi, sıradışı durumları yönetmede programcıya ciddi sorumluluk yüklemesi gibi noktalar da çalışma-zamanı güvenirliğini arttırmak için dile konmuş mekanizmalardandır.

Güvenli: Java’nın ağ ortamlarında çalışmak üzere tasarlanmış olması, onun güvenlik konsunda daha dikaktli olmasını gerekli kılar. Bu sebeple Java en başından bu yana, JVM’de çalışan bytekodlar ile JVM’nın üzerinde çalıştığı sistemin dosya, soket vb. kaynakları arasındaki iletişimi iki yönde de kontrol etmek için gerekli mekanizmaları sağlamıştır. Java, gerek web üzerinden hizmet veren uygulamalara ve web servislerine gerek ise uzak nesnelere rol temelli erişim kontrolü (role-based access control, RBAC) yaklaşımıyla gerek tanım tabanlı (declarative) gerek ise API tabanlı erişim imkanı sağlamaktadır.

Java’nın ilk yıllarında zaman zaman duyulan Java Sanal Makina’sındaki güvenlik açıkları haberleri uzun süredir duyulmamakta olması Java’nın bu konuda da istenen seviyeye geldiğini göstermektedir.

Ayrıca Java’nın güvenlik konusunda sunduğu bileşenler son derce zengin olup her türlü şifrelemeye ya da HTTPS gibi güvenli protokolleri kullanmaya imkan tanımaktadır.

Mimari olarak tarafsız: Java, farklı mimarilere sahip pek çok platformun bulunduğu ortamlarda çalışmak için tasarlandığından, hiçbir mimari yapıya öncelik vermez ve hiç bir platforma özel yapılar içermez. Java’nın platformlar ile ilgili kabulleri, bütün platformalar tarafından genel kabul görmüş yapılarla ilgilidir. Dolayısıyla Java ile her türlü mimari yaklaşım kullanıalrak her çeşit platform üzerinde uygulama geliştirmek için vardır.

Yüksek performanslı: Pek tabi ki bu özellik ciddi bir açıklamaya muhtaçtır. Aksi taktirde Java’nın yüksek performanslı olması iddiası Fortran ya da C gibi dillerle yapılacak basit ve üstünkörü kıyaslarla çok kolayca çürütülebilecektir.

Öncelikle şunu ifade etmek gerekir ki nesne-merkezli diller kalıtım ve çok formlu yapıları destekledikleri için zaten prosedürel dillerin derleme zamanında yaptıkları pek çok işi çalışma zamanında yapmak durumundadırlar. Ayrıca Java, daha güvenli ve sağlam bir dil olmak adına sadece derleme zamanında değil çalışma zamanında da pek çok kontrol yapmaktadır. Tip kontrolleri bunun en güzel örneğidir. Ayrıca Java’nın platformdan bağımsız ve taşınabilir olması, onun bir sanal makina üzerinde çalışması ve çalışma zamanında yorumlanmasını gerekli kıldığından, çalışma zamanında ciddi bir handikapa sahip olacağı da açıktır. Bu ve benzeri sebeplerden dolayı Java, zaten tasarlanırken yapılan tercihlerin sonucu olarak zaten Fortran ya da C gibi hızlı olması beklenmemelidir. Fakat Java’nın yukarıda bahsedilen cinsten özellikleri, çalışma zamanında tatmin edici bir performansta erişmesinin önünde engel teşkil etmezler. Lakin pek tabi olarak, Java programcıları, performans konusunda diğer pek çok dilde program yazanlara göre daha bilgili ve uyanık olmalıdırlar. Nesne merkezli teorinin sınırları içinde kalarak olabildiğince az nesne oluşturmak (mesela bu amaçla sıkça değişen string nesneleri için String yerine StringBuffer kullanmak) , oluşturulan nesneye yapılan referansları işi bittiğinde nesneden koparmak vb. teknikleri uygulayarak, Java programcıları daha başından yazdıkların kodun performans yönünden sıkıntıda olmaması için çaba gösterirler. Bütün bu çabalara rağmen bir Java kod parçası halen istenilen performansta çalışmıyorsa tabi olarak ince ayara (tuning) tabi tutulur.

Öte taraftan şu da bilinmelidir ki bir sistemin performans ve ölçeklenirliği (scalability) o sistemde kullanılan dilden ziyade sistemin mimarisinin bir özelliği ve sonucudur. Yüksek performanslı olması istenen sistemler, mimari seviyede bu amacı sağlayacak yaklaşım ve tekniklerle tasarlanmalıdırlar. Tabi olarak böyle bir tasarım dil seviyesinde de pek çok yaklaşımı bünyesinde barındırabilecektir.

Çok kanallı: Kanal (thread) işlem/süreç (process) içerisinde bir akıştır, diğer bir ifade ile işlem içerisinde küçük bir işlemdir, işlemciktir. İşletim sistemi bir işlemi başlatdığında, belleğin bir kısmını ona tahsis eder ve kodunu belleğe yükler. İşletim sistemi CPU gibi sistem kaynaklarını pek çok işlem arasında devamlı surette paylaştırır. Bu paylaştırma çok hızlı yapıldığı için kullanıcı, aynı anda pek çok program çalışıyormuş izlenimini elde eder. Benzer paylaştırma, bir işlem içindeki pek çok işlemcik arasında da yapıldığında o işlem çok daha hızlı çalışacaktır, en azından kullanıcı nezninde öyle algılanacaktır. Hesaplamanın ana unsuru olan CPU’ların çok hızlandığı, hatta birden fazla çekirdeğe sahip CPU’ların yaygın hale geldikleri bir ortamda programlar çok kanallı yapıları daha sık ve etkin kullanmalıdırlar.  Çünkü kanallar, işlemlere göre çok daha hızlı oluşturulurlar. Ayrıca kanalların aralarında veri alışverişi çok kolaydır çünkü işlemlerin veri alanları kanallar tarafından paylaşılır. Bu paylaşım avataj olduğu gibi zaman zaman sıkıntılı durumlara da yol açabilmektedir.

Java’nın kanallar konusundaki yaklaşımı çok basittir; Java’ya başlayan herkes çok kısa sürede kanalları kullanır hale gelebilir. Hatta bir programcı eğer sunucu tarafında (server-side) çalışıyorsa, kendisi kanal oluşturmasa bile JVM’in oluşturduğu pek çok kanalın bulunduğunu bilmek ve buna göre davranmak zorundadır. Bu noktada Java’nın yaklaşımı, yüksek performanslı ve ölçeklenirlikli sistemler için çok kanallı yapılar şarttır ve iyi Java programcıları da kanalları çok etkin bir şekilde kullanır.

Dinamik: Bir Java programı çalışmaya başlarken, çalışması sırasında ihtiyaç duyacağı tiplerin hazır olmasına ihtiyacı yoktur. Program, ihtiaycı olan tipleri, içinde bulundukları .class dosyalarından çalışma zamanında, yeri geldikçe yükleyebilir. Buna dinamik yükleme (dynamic loading) denir. C gibi dillerde bütün yüklenecek kütüphane vb. öğeler bağlantı zamanında (linking time) hazır olmalıdırlar. Buna da statiktir bağlama (static linking) denir ve çalışma zamanından öncedir. Java’nın böyle bir özelliğe sahip olması, onun ağ ortamlarında çalışmasına uygun bir davranıştır. Çünkü ağlı yapılarda, ağ üzerinde erişilecek uzak nesnelerin daha derleme zamanında hazır olmalarını beklemek çok da mantıklı değildir.

Evet işte Java böyle bir dildir. Burada sayılan özelliklerin hangisini ne kadar sahip olduğu ya da ne derece yerine getirdiği tabi ki tartışılır. Ama yazılım dünyasında başka hiçbir dil Java kadar hızlı ve heyecanlı bir karşılama görmemiştir. Telefonlardan çok büyük çaptaki kurumsal projelere kadar pek çok farklı platformda kullanılıyor olması Java’nın bilgi teknolojileri dünyasının en temel dillerinden birisi haline geldiğinin kanıtıdır.

Bundan sonraki yazıda Java’nın kısa tarihinden bahsedeceğiz.

Toplam görüntülenme sayısı: 4362

21 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
02 Kasım 2009

Ben kimim?

Akin Diğer Akın, Kaldıroğlu

İsmim Akın Kaldıroğlu. Balıkesir, Ayvalık’lıyım, Ege ve deniz çocuğuyum yani. Dünyanın en güzel manzaralı liselerinden biri olan Ayvalık Lisesi mezunuyum. 1990 yılında da İstanbul Teknik Üniversitesi Elektronik ve Haberleşme Mühendisliğinden mezun oldum. 1993-2001 yılları arasında ABD’de bulundum. Aslında önceleri sadece eğitim amaçlı olarak başlayan bu bulunma daha sonra, ABD’deki “.com” patlamasının da etkisiyle biraz daha dünyevi bir hal aldı. Yani ABD’de bilgisayar ve yazılım mühendisliği master eğitimleri aldım ve profesyonel olarak da yaklaşık 5 sene çalıştım. 2001 yılında kürkçü dükkanına geri döndüm, Türkiye’deyim, İstanbul’da yaşamaktayım, ama her fırsatta kendimi Ayvalık’a atarım.

90’lı yılların başından bu yana yazılımla profesyonel olarak ilgileniyorum. İlk zamanlar C ve C++ ile çalıştım ve nesne-merkezli dünyaya C++ ile girdim. O zamanlarda Unix üzerinde çalışırdım. Daha sonra Java çıktı ve o gün bugündür Java ile uğraşıyorum. Entellektüel amaçlar dışında Java’dan sonra onun üzerine hiç gül koklamadım, dolayısıyla Java’yı seviyorum. “Analist programcı” etiketiyle başlayan çalışma hayatım (ABD’de üniversitedeki “Graduate Research Assistant” ya da yine üniversitede para kazanmak  için “private tutor” adı altındaki çalışmamı profesyonel olarak değerlendirmiyorum.) tecrübeli programcı, yazılım mimarı, proje yöneticisi, yazılım müdürü, genel müdür yardımcısı, danışman, eğitmen vb. etiketlerle devam etti.

Java ve nesne-merkezli dünyada bulunmayı, yazılım geliştirmeyi, ya da ne bileyim küçük ama zekice geliştirilmiş bir algoritmayı Java ile yazmak ve bunu insanlarla paylaşmak bana mutluluk veriyor. Bu yüzden eğitmeyi seviyorum ve zaman zaman eğitmenlik de yapıyorum.

Sanırım hayatta yapmayı en çok sevdiğim şey çocuklarımla birlikte vakit geçirmektir. Sonra da bildiklerimi paylaşmak gelir. Çocuklarımla iyi vakit geçirmek ve herkesle bildiklerimi paylaşmak için okumam ve düşünmem gerekir, bunları severim. Müzik dinlemeyi çok severim, Batı Klasik Müziğ’inden kendi klasik müziğimize, rock müzikten Türk Halk Müziği’ne kadar hemen her türlü müziği dinlerim. Futbol’u severim, bir Fenerbahçe taraftarıyım. Amatör felsefe meraklısıyım, sistemli düşünmeyi severim. Mesleğimde de bunu yapmaya çalışırım. Dolayısıyla aşırı hedef odaklı olmaya karşı, sistemsiz kazanımların uzun soluklu olmadığını düşünürüm. Bu konuyu savunabilmem için ülkemiz bana, siyasetten spora çok zengin örnekler de veriyor zaten.

Bana ulaşmak için bu sayfaya yorum bırakabilirsiniz, akin@javaturk.org adresime ileti gönderebilirsiniz ya da Facebook ve LinkedIn gibi yerlerde beni bulabilirsiniz.




Toplam görüntülenme sayısı: 858

10 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
«< 71 72 73 74 75 >

Günlüğüme Hoşgeldiniz

Bu günlükte, Yazılım Mühendisliği, Bilgi Teknolojileri, Java, kişisel gelişim ve zaman zaman da diğer konulardaki düşüncelerimi sizlerle paylaşacağım. Umarım beğenir ve hoşça vakit geçirirsiniz.

Her türlü düşüncenizi, yorum olsun, beğeni ya da eleştiri olsun, bana iletmenizi rica ediyorum sizden. Ayrıca bana akin@javaturk.org adresinden ya da Twitter'dan ulaşabilirsiniz. Videolarıma da buradan ulaşabilirsiniz.

Teşekkür ederim.

Akın Kaldıroğlu

Rahat Okumak İçin

A Decrease font size. A Reset font size. A Increase font size.

Sosyal Medya

  • Twitter
  • Facebook
  • LinkedIn
  • Youtube

Son Twitlerim

→ Takip Etmek İçin

Abone Olun

Emalinizi girerek yazılardan haberdar olun.
Loading

Son Yazılarım

  • Udemy Eğitimlerim Üzerine
  • (başlıksız)
  • Clean Code / Temiz Kod Eğitimi Udemy’de
  • Java ile Nesne-Merkezli Programlamaya Giriş Eğitimi Udemy’de
  • Selsoft Video Eğitimleri
  • Spring ile Kurumsal Yazılım Geliştirme
  • Corona Günlerinde Design Patterns
  • Corona Günlerinde Java
  • JDK 10 ve “var” Özelliği
  • Onur Özcan
  • Analist ve İş Bilgisi
  • Farklı Dillerin Bakış Açısıyla Nesne-Merkezli Programlama
  • Java Nedir?
  • Bilgi Teknolojilerinde Yetenek Yönetimi – II: Tanımlar ve Eleştiriler – I
  • Alelade Hikayeler – II: Bir Başka Performans Problemi

Popüler Yazılar ve Sayfalar

  • Java’ya Nasıl Başlarım? Java’yı Nasıl Öğrenirim? – I
  • Nasıl Yazılımcı Olalım? – II: Hangi Bölümü Okuyalım?
  • Oracle’ın Java SE Sertifikaları: OCA, OCP ve OCM
  • Java Kurulumu ve İlk Programımız
  • İş Analisti İş Tanımı
  • Java Tutorial ya da Kendi Kendine Java Öğren
  • Nasıl Yazılımcı Olalım? – I: Üniversiteli mi Alaylı mı?
  • Tasarım Kalıpları
  • Java’ya Nasıl Başlarım? Java’yı Nasıl Öğrenirim?
  • UML Nedir?

Yazı Kategorileri

Yazı Takvimi

Haziran 2025
P S Ç P C C P
 1
2345678
9101112131415
16171819202122
23242526272829
30  
« May    

Yazı Arşivi

Blogroll

  • Binnur Kurt'un Günlüğü
  • Ender'in Java Blogu
  • Erdem Seherler
  • Kızımın Günlüğü
  • Kurumsal Java
  • Levent Karagöl
  • Levent'in Java Blogu
  • Mert Can Akkan’s java tips,options, news…
  • Yaşar Safkan
  • Yasin Saygılı
  • Yazı Dünyası

Yazı Etiketleri

analiz Bilmek C Desen design pattern EJB Eğitim Fortran Hibernate Java Java'ya nasil baslarim Java dersleri Java EE Java Persistence API Java SE Java Sertifika Java Öğren Java öğreniyorum Java öğrenmek JPA Kalıp Kurumsal Java nesne nesne-merkezli No Silver Bullet object object-oriented Oracle Java Certifications pattern performans programlama programlama dilleri programlama nedir sertifika singleton tasarım tasarım deseni tasarım desenleri tasarım şablonu yazılım yazılım geliştirme Yazılım Mühendisliği yazılımın doğası yazılımın zorlukları Şablon

↑

© Java Günlüğüm 2025
Powered by WordPress • Themify WordPress Themes
 

Yorumlar Yükleniyor...