Tag Archives: agile

Çevik Süreçler Neden Dikiş Tutturamadı

Çevik süreçlerin tam olarak ne olduğunu kavramamış, çevik süreçler ile bir proje uygulamamış, scrum yaparak çevik olduğunu ve çevik süreçlerin bir işe yaramadığını zanneden şahısların “agile is dead” naralarını unutmadık. Ben de çevik süreçler öldü diyorum, lakin ekliyorum: “yaşasın çevik süreçler”. Çevik süreçlerin yıldızlarının bundan sonra nasıl parlayacaklarını ve tam anlamıyla yazılım geliştirme süreçlerine hakim olacaklarını kendi yazılımcı perspektifimden sizinle paylaşmaya çalışacağım.

Bir yazılım sistemi belli bir büyüklüğe ulaştıktan sonra, kendi dinamiklerini oluşturarak, yeni özellikler eklenmek suretiyle geliştirilmesini engeller hale gelir. Bunun başlıca sebebi, mevcut mimarinin yeni özellikleri taşıyacak yapıda olmamasıdır. Bunu bilen yazılımcılar iki nokta arasındaki en kısa mesafeyi seçmek yerine, en az dirençle karşılacakları patikayı yeğlerler. Bunun neye sebebiyet verdiğini çok iyi biliyoruz: teknik borç! Burada yazılımcının büyük oranda suçu olmadığını düşünüyorum. Daha ziyade yazılımdan bihaber yöneticiler zaman baskısı oluşturarak, işi aceleye getirmektedirler ve aslında başarısızlığın temelini ilk saniyeden itibaren atmaktadırlar. Bu duruma yazılımcılar tepki vermeyerek ve kimsenin etlisine, sütlüsüne karışmayarak ortak olmaktadırlar. Lakin şöyle yöneticilerin karşılarında ağız birliği yaparak, dik durabilseler ve “madem bu işi biz yapıyoruz, o zaman ne zaman biteceğine de biz karar veririz” diyebilseler, çok daha güzel işler ortaya koyabilecekler.

Yazılımda bu sorun ile başa çıkmanın tek bir yolu mevcut, o da refactoring olarak adlandırılan kodun yeniden yapılandırılmasıdır. Teoride her yazılımcının yeniden yapılandırmanın ne anlama geldiğini bildiğini düşünebiliriz. Lakin pratik açıdan baktığımızda, yeniden yapılandırma işleminin nasıl yapıldığı konusuna çok az sayıda yazılımcı hakimdir. Bunun da başlıca sebebi, yazılım testleri üzerinde olan hakimiyetsizliktir.

Refactoring tek başına yapılması mümkün olmayan bir işlemdir. Yapılan her değişiklik bir yan etki doğurabileceğinden, bu etkinin tespit edilebilmesi zaruridir. Bu kontrolü bir yazılımcının elden yapması mümkün değildir. Bu sebepten dolayı burada bir otomasyon ihtiyacı doğmaktadır. İhtiyaç duyulan kapsama alanına sahip olduğumuzu farz ettiğimizde, otomatik çalışan testler refactoring esnasında oluşan tüm yan etkileri tespit etmeyi mümkün kılacaklardır. Özetleyecek olursak, aslında yazılım sisteminin sürekli gelişimi için ihtiyaç duyduklarımız yeniden yapılandırma, test yazılımı ve test otomasyonudur. İşte çevik süreçlerin temelini de bunlar oluşturmaktadır. Eğer sürekli müşteri gereksinimlerini koda dökebiliyor ve mevcut sistemi genişletebiliyorsanız, çeviksiniz! aksi tektirde yazılımcılık oynuyorsunuz!

Çevik süreçler bünyesinde yer alan çevik metotların ana amacı yazılımda sürdürülebilirliği hedefliyor olmalarıdır. Burada sürdürülebilirlik terimini teknik açıdan ele almamız gerekmektedir. Sürdürülebilirlik bir yönetici için başka, bir yazılımcı için daha başka, bir patron için çok daha başka bir anlam ifade etmektedir. Ama doğru olan yaklaşım hangisidir? Şüphesiz herkes kendince doğru yaklaşım içindedir, çünkü beklentiler değişiktir. Lakin tekrar altını çizerek sormak istiyorum, teknik olarak sürdürülebilirlik ne anlama gelmektedir? Bunun cevabını verebilmek için öncelikle işin müşteri kısmını incelememiz gerekiyor.

Bir yazılım sistemi müşteri gereksinimleri doğrultusunda şekillenir. Yazılımcı olarak nihai amacımız, müşteri gereksinimlerini tatmin edecek bir sistem oraya koymaktır. Bu yüzden doğal olarak müşteriye kulak vermemiz ve ne istediğini iyi anlamamız gerekmektedir. Lakin müşteri ne istediğini tam olarak bilmekte midir? Ne yazık ki bu sorunun cevabı hayıdır. Burada yazılımcı olarak bizim için iki sıkıntı oluşmaktadır. Birincisi nasıl bir sistem oluşturmamız gerektiği sorusudur, ikincisi bu sistemin mimarisinin nasıl olması gerektiğidir. Bu iki sorunun da cevabını düşünerek, bulmamız mümkün değildir. O yüzden bir an önce kolları sıvıyarak, müşteriye yarım yamalak dile getirdiği gereksinimleri için kısa bir zaman dilimi sonunda bir şeyler göstermemiz gerekmektedir ki müşteri ne istediğine dair fikir üretmeye başlayabilsin. Bu yüzden çevik süreçlerde bir ya da iki haftalık iterasyonlar sonunda müşteriye mutlaka tespit edilen miktardaki özelliğin çalışır durumda olduğu sistemler sunulur. Bu prototipler müşteriden alınan geribildirimler doğrultusunda onun kullanacağı ürün olana kadar geliştirilir. Lakin burada tekrar sürdürülebilirlik konusuna değinmemiz gerekmektedir. Teknik olarak bu nasıl sağlanabilir? Bunun iki yöntemi mevcuttur: Teknik borç ve teslimiyet ya da kararlılık ile uygulanan “yap/boz” mentalitesi.

Eğer bir bina yapımı söz konusu ise, atılması gereken temelin ve uygulanmak istenen mimarinin bilinmesi gerekmektedir. Bu değişmez iki parametre yapılan binanın kaderidir. Eğer inşaat mühendisleri ve mimarlar yazılım yapmaya başlasalardı, hiç zorluk çekmeden bu işe adapte olabilirlerdi, çünkü günümüzde de yazılım bir bina inşaatı gibi ele alınmaktadır. Durum böyle olduğu için yazılım projelerinin çok büyük bir kısmı belli bir zaman sonra çıkmaza girerek, hem yazılım sistemini oluşturanları hem de müşterisini zorda bırakmaktadırlar.

Tekrar teknik sürdürülebilirlik sorusuna geri dönelim. Teknik sürdürüleiblirliğin bedeli ne yazık ki ağırdır. Öncelikle yazılımla uğraşan herkesin bu bedeli maddi ve manevi olarak ödemeye hazır olması gerekmektedir. Maddi açıdan baktığımızda yöneticilerin sürdürülebilirliği sağlamak adına daha fazla zamana ihtiyaç duyulduğunu ve bunun maliyeti artıracağını anlamaları, manevi açıdan baktığımızda yazılım mühendislerinin işin çıkmaza girdiğinde radikal kararlar vererek, refactoring teknikleri yöntemleri ile mevcudiyeti yeniden şekillendirme iradesine sahip olmaları gerektiğini görmekteyiz.

Günümüzde yapılan yazılımı yirmi sene önceki şekli ile kıyasladığımızda, aslında kafalarda fazla bir şeylerin değişmediğini görebilmekteyiz. Çoğu yazılım projesi yirmi sene önceki kafa yapısı (mindset) ile uygulanmaktadır. Yirmi sene önce aktif olarak hayatımıza giren çevik metotlar ihtiyaç duyulan dönüşümü sağlayamadılar. Bunun nedeni ne olabilir? Çevik süreçler performans gösterebilmek için çok radikal değişimlere ihtiyaç duymaktadırlar. Bu programcıların çalışma tarzlarından başlayarak, firmanın sahip olduğu yazılım geliştirme kültürüne kadar uzanana bir alanı kapsamaktadır.

Çevik süreçler programcı perspektifinden bakıldığında test güdümlü yazılım gibi radikal bir metodun uygulanmasını talep etmektedir. Yazılım birimlerini test etme konusunda pek kafa yormamış ve bu konuda tecrübesi olmayan bir yazılımcıdan test yazarak, yazılıma devam etmesini istemek, bir cobol yazılımcısına bugünden yarına nesne tabanlı program yazdırmaya çalışmak gibi birşeydir. Nitekim ikibinli yılların başlarında görev başında olan yazılımcıların bu fikri benimsemeleri mümkün olmadı. Onlar hep testlerin yazılımın en sonunda uygulanan bir aktivite olarak gördüler. Her zaman angarya olarak görülmüş test yazma olayının birden bire gündemin en başına oturarak, tüm gidişata yön verme fikrine o jenerasyon ne yazık ki adapte olamadı. Tekrar hatırlamakta fayda görüyorum. çevik olabilmeniz için yani müşteri gereksinimlerine her daim yazılım ile karşılık verebilmeniz için yeniden yapılandırma yapmak zorundasınız. Test olmadan yeniden yapılandırma yapılamaz. Bu yüzden çevik süreçlerin en temelinde bu iki prensip yatmaktadır: yeniden yapılandırma ve testler. Olay sadece test güdümlü yazılım ile bitmiyordu. Eşli programlama, sürekli entegatasyon, iterasyon bazlı yazılım gibi birçok çevik süreç metodu mevcut yazılım süreçlerini yer yer tersine çevirdiğinden dolayı, bu durum yazılımcılara sudan çıkmış balık hissi yaşatmakta ve adaptasyonu zorlaştırmaktaydı.

O dönemin yazılım sektöründe çalışanlarını şelale (waterfall) yazılım süreçlerinden geldiklerini unutmamamız gerekmektedir. O zamanın yazılım ekipleri müşteri gereksinimlerini en ince detayına kadar anladıktan ve kağıda döktükten sonra yazılım yapmaya başlarlardı. Burada bir senelik bir ön çalışma ve akabında yine birkaç sene sürebilen yazılım geliştirme sürecinden bahetmekteyiz. O gün olsun, bugün olsun yazılım projelerinin başarısız olmalarının ana sebeplerinden birisi ne yazık ki budur. Müşteri gereksinimleri doğrultusunda bir yazılım sistemine ihiyaç duyar. Müşterinin bu gereksinimleri piyasa şartları ile günlük bazda bile değişime uğrayabilirken, şelale yöntemleri ile birkaç sene kapalı kapılar arkasında yapılan yazılımın, bu zaman dilimi sonunda müşteri gereksinimlerine ne kadar az hitap edebilme potansiyeline sahip olduğunu görebilmekteyiz. Nitekim yazılım projelerindeki başarısızlık, müşteri gereksinimlerinin ne oranda karşılık göremediği ile çok yakından bağlantılı.

Hala ikibinli yılların başlarındayız ve çevik süreçlerin var olma savaşını yakından inceliyoruz. Şimdi o zamanlar yazılımın nasıl yapıldığını ve uygulanan mimarileri yakından inceleyerek, çevik süreçlerin neden tutunamadığını görmeye devam edelim.

İkibinli yılların başlarında Java programlama dili sahip olduğu ekosistemi ile tüm yazılım camiasına hakim olmaya başladı. O zamanlar EJB (Enterprise Java Beans) ile uygulama sunucularında yazılım yapanlar çok iyi hatırlayacaklardır. Tarih hep tekerrürden ibarettir, lakin umarım o günleri hiçbir yazılımcı tekrar yaşamak zorunda kalmaz. O devrin yazılım yöntemleri, araç ve gereçleri çevik süreçler için hazır değildi. Siz ne kadar iyi niyetli de olsanız ve test güdümlü yazılım ile birim testleri yazsanız bile, entegrasyon, onay/kabul testleri ve benzeri testlerin otomatik çalıştırılmaları onlarca ya da yüzlerce dakikanızı almaktaydı. Çok küçük bir değişilik yaptığınızı düşünün. Uygulamanın tekrar paketlenerek, uygulama sunucusunda çalışır hale gelmesi en az on dakikanıza mal olmaktaydı. Bunu çok defa yaşamış bir programcıyım. Çeviklik geribildirimle doğrudan orantılıdır. Yaptığınız şey size ne kadar hızlı geribildirim sağlarsa, o hızda değişilik yapabilirsiniz. Çevik olabilmek için yeniden yapılandırmamız gerekiyor. Bunun için testlerin sağladığı geribildirime ihtiyacımız var. Aynı şekilde sürekli entagrasyon yaparak, sistemin hangi derecede entegre olduğu geribildirimine ihtiyaç duymaktayız. Tüm çevik metotlar geribildirim prensibine dayanmaktadır. Geribildirim sağlanmadan, yaptığımız işin neresinde olduğunu anlamamız mümkün değildir. Geribildirim alma süresinin uzaması, bu o oranda çeviklikten uzaklaşma anlamına gelmektedir. Nitekim uygulama sunucularından kaynaklanan sebeplerden dolayı çok zaman alan test otomasyonu ilerleyebilmek adına devre dışı bırakılmak zorunda kalındı. O devrin EJB projelerine göz attığımız taktirde ya hiç ya da çok çok az oranda test koduna sahip olduğunu görebiliriz. Aynı durum bugün yapılan projeler için bile geçerlidir. Birçok güncel projede bir tane bile test metodu bulunmaması hiç şaşırtıcı değildir. Projelerin neden sürdürülebilir olmadıklarını ortadadır.

İkibin onlara kadar uygulanan yazılım prensip ve mimarileri de ne yazık ki çevik süreçler için gerekli ortamı oluşturamadı. Bahsetmiş olduğum zaman diliminde monolitler revaçtaydı. Durumun bugün bile değişik olduğu söylenemez. Trendin ama microservice mimarileri ile değiştiğine şahit olmaktayız. Peki bir monolit çevik süreçler ile geliştirilemez anlamına mı gelmektedir bu? Bu monolitin büyüklüğü ve bünyesinde barındırdığı kod kalitesi ile doğrudan ilişkili bir durum.

Çevik süreçler ile bir monoliti geliştirmek mümkün. Ama bu ne yazık ki belli bir büyüklüğe kadar sağlanabilir. O kritik büyüklüğe erişildikten sonra, sistemin küçük ve birbirinden bağımsız parçalardan oluşuyor ve geliştirilebiliyor olması gerekmektedir. Yani burada modüler bir yapıya ihtiyaç duyulmaktadır. Lakin bir monolit ne kadar modüler bir yapıda da olsa, tek bir parça olarak entegre edilmesi gerekmektedir. Burada yine test otomasyonu sorunları baş göstermektedir. Bunun yanı sıra entegrasyon süreleri uzamakta ve hızlıca yapılması gereken değişiklikler zaman almakta ve çeviklikten ne yazık ki ödün verilmesi zazuri bir hale gelmektedir. Tekrar hatırlayalım: hızlı bir şekilde geribildirim alınamayan ortamlarda çevik olunması imkansızdır.

Çevik bir yazılım ürünü yani her yeni müşteri gereksnimi ile yeniden yapılandırılabilen ve sürekli değişiklik ile başedebilen bir yazılım sistemi için belli başlı yazılım prensiplerinin, tasarım şablonlarının ve yazılım mimarilerinin uygulanması zaruridir. En basit hali ile clean code, solid prensipleri ve modüler bir mimariye ihtiyaç duyulmaktadır. Bunların uygulandığı bir proje test kültürü ile birleştiğinde her yeni müşteri gereksnimi ile hamur gibi yoğrulabilen yazılım ürünleri ortaya çıkamaktadır. Ama günümüzde bile birçok projede test kodunu bir yana bırakın clean code ya da solid prensiplerinden eser bile bulmak mümkün değildir. Testler olmadığından dolayı programcılar artık binlerce satırdan oluşan sınıfları değiştirmeye korkar olmuşlardır. Bu korkunun mevcut olduğu bir yerde nasıl yeni müşteri gereksinimleri hayat bulabilir?

Teknik açıdan baktığımızda, birçok sebepten dolayı çevik süreçlerin uygulanabilir olmadıklarını ve bu yüzden bir zaman sonra terk edildiklerini görebilmekteyiz. Lakin bunu tümüyle teknik sorunlarla ilişkilendirmek doğru değildir. Bunun yanı sıra firmalarda oluşan yazılım geliştirme kültürlerini ve organizasyonel yapıları da yakından incelememiz gerekmektedir.

Zaman içinde, çevik süreçlerin popülerliğinden de istifade edilerek benim fake agile olarak tabir ettiğim ve yazılımda çevikliği ima eden ama bunu sağlamaktan çok uzak sözde çevik süreçler oluştu. Bunların başında scrum geliyor. Scrum yakından incelendiğinde, aslında yakından, uzaktan çeviklik ile hiçbir alakası olmayan bir şey olduğu görülmektedir. Scrum ne çeviklik namına bir çevik metot ihtiva etmektedir ne de scrum ile çevik bir yazılım ürünü geliştirmek mümkündür. Çevik olmak için çevik metotlara ihtiyaç duyulmaktadır. Bunlar teknik anlamda yazılımcılar tarafından uygulanan metotlardır. Test güdümlü yazılım ya da eşli programlama gibi çevik metotları sadece yazılımcılar uygulayabilirler. Tüm çevik metotlar yazılımcılar için ve onların çevik hareket edebilmeleri için oluşturulmuşlardır. O yüzden çevik süreçler yardımı ile yazılım yapıyoruz denildiğinde, incelenmesi gereken nokta, çevik metotların ne oranda yazılımcılar tarafından yaşanıyor olduklarıdır.

Scrum ve benzeri yapılar ne yazık ki extreme programming gibi gerçek çevik metotların önüne geçtiler ve organizasyonlara çevik oldukları hissini verdiler. Kendini iyi hissetmekten öteye götüremeyen bu yaklaşımlar yazılım yapanların “çevik çalışıyor olmamıza rağmen, gerekli performansı alamıyoruz” söylenimlerine yol açtılar. Scrum ve benzeri yapılar ne yazık ki gerçek çevik süreçlerin adlarını karaladılar ve diskredite olmalarına sebep oldular. Bugün baktığınızda çevik olmayan bir yazılım ekibi bulamazsınız. Herkes scrum yapıyor ve herkes çevik. Ama ortaya çıkan yazılım ürünlerine göz attığımızda, hepsinin aynı dertlere sahip olduklarını ve aslında müşteri gereksnimlerine cevap veremeyecek yapıda, teknik ve mimarı açıdan tükenmiş olduklarını görmekteyiz.

Çevik süreçlerin önünü kapatan diğer bir durumda, yazılım ekiplerinin organizasyon yapısı olmuştur. Klasik bir yazılım ekibinde yazılımcı, testçi, analizci, sürümcü, proje yöneticisi gibi rolleri görmek mümkündür. Bir fabrika bandında üretim için uygun olan bu rol bazlı kadrolaşma, yazılım için ne yazık ki büyük sorular doğurmaktadır. Çevik süreçler yazılım, test, analiz, sürüm ve canlı işletme sorumluluğunu (production) yazılım ekibini oluşturan yazılımcılarda görmektedir. Yazılımcılar yazılım ile ilgili her şeyi yapamazlar mantığı doğru değildir. Mühendislik altyapısına sahip bu kişilerin günümüzde sadece kod yazmak için uygun olduklarını düşünmek en kibar ifadeyle onlara yapılan haksızlıktır. Nitekim Google tarafından uygulanan SRE (Site Reliability Engineering) ve DevOps gibi akımlara baktığımızda, yazılım ekibinin yazılım için gerekli tüm işlevleri yerine getirdiklerini görmekteyiz. Yazılımın, testin, analizin ve sürümün ayrı ekipler tarafından yapıldığı ortamlarda, çevik süreç faydalı olamamaktadır. Bu tür ayrıştırıcı organizasyonel yapılar olduğu sürece, çevik yazılım yapmak ne yazık ki mümkün değildir.

Yazılımda teknik sürdürülebilirlik için gerekli etkenleri ele almaya çalıştım. İsmi illa çevik süreç olmak zorunda değil. Lakin sürdürülebilirlik için atılması gereken somut adımlar var. Yazılımcının ana görevi sadece kod yazmak değildir. Mevcut organizasyonel yapılar bunun doğru olduğu fikrini savunsalar da teknik sürdürülebilirlik için yazılımcılara daha fazla sorumluluk verilmesi gerekmektedir. Yeni gereksinimlerin ivedilikle yazılım ürününe entegre edilebilmeleri için kodun her daim hamur gibi yoğrulabilmesi gerektirmektedir. Bunu sadece ve sadece yazılımcılar yapabilirler. Bunun için yüksek seviyede teknik beceriye ihiyaç duyulmaktadır. Bu da mühendisliğin hakkını verebilen yazılımcılarla mümkün olabilecek bir iştir.

Buraya kadar bahsetmiş olduğum nedenlerden dolayı çevik süreçler ne yazık ki hak ettikleri yere gelemediler ve haksız yere işe yaramaz damgasını gördüler. Ama ben bu durumun değişme sürecine girdiği düşüncesindeyim. Çevik süreçlerin işlemesini engelleyen unsurların yavaş yavaş kaybolmaya başladıklarına şahit olduğumuz bir dönemden geçiyoruz. Bu unsurlardan bazılarını yakından inceleyelim.

Artık günümüzde monolitlerin terk edilmeye yüz tutmuş bir mamarı türü olduğunu görmekteyiz. Modern yazılım sistemleri küçük ve birbirlerinden bağımsız çalışan modüllerden oluşmakta. Bunu sağlamak için microservice, webservice, rest ve soa gibi mimariler ve kubernetes, docker ve cloud gibi altyapı ve teknolojiler tercih edilmekte. Belli bir büyüklüğü geçmeyen ve otonom çalışan kod birimlerinin bakımı, geliştirilmesi, test edilmesi, sürümlenmesi ve işletilmesi geçmişe nazaran çok daha kolay.

Günümüzde yazılım ekiplerinin yapıları da değişmeye başladı. Örneğin Google bünyeside SRE olarak bilinen takımlar, test etmeden işletime kadar uygulamanın her yönüyle ilgileniyorlar. Birçok yeni ekip iki pizza prensibine göre oluşturuluyor. İki pizza ile doymayan bir ekip, büyüklüğü itibari ile monolite dönebilecek yapılar oluşturma eğilimi gösterebilmektedir. Küçük ekip ve tek sorumluluk prensibi kolay değiştirilebilir ve geliştirilebilir yazılım birimleri için sihirli bir formül haline geldi.

Bunun yanı sıra yazılımcılar eskiye nazaran tasarım prenbipleri, tasarım şablonları ve yazılım mimarileri konularında daha donanımlı hale geldiler. Clean code, software craftşman ve devops akımları, yazılımcıların teknik olarak daha da iyi olmaları için gerekli fikir ve pratikleri ihtiva ediyorlar. Ayrıca günümüzde eskiye kıyasla yazılımda teknik sürdürülebilirliği destekleyici, sonar, jenkins, git gibi birçok açık kaynaklı ürün bulmak mümkün.

Müşteri cephesinde de bazı değişiklilerin meydana geldiğini görmekteyiz. Müşteri eskisi gibi artık yıllar sonra kullanmaya başlayacağı bir yazılım ürünü siparişi vermek istemiyor. Müşteri bugün siparişini verdiği yazılım ürününün ilk sürümünü birkaç hafta sonra kullanmaya başlamak isteyebiliyor. Buna sadece çevik süreç ve iterasyon bazlı çalışma ile cevap vermek mümkün. Ayrıca müşteri için bir yazılım ürününün kullanılabilirlik seviyesi de değişmiş durumda. Piyasa rekabetinden doğan yeni gereksinimlerinden dolayı müşteri yıllarca beklemek yerine, sürekli geliştirilen, gereksinimler doğrultusunda adapte edilen ve her daim kullanılabliir yazılım ürünlerine yönelebiliyor.

Yirmi sene öncesi çevik süreçler ve tdd, bdd, pair programming, ci, refaçtoring, solid gibi çevik metotlar uygulanmaya başlandığında devir monolitlerin hakim olduğu mimarı devirdi . Çevik süreç ile bir monolit geliştirmek sadece iyi bir niyetten öteye gidemedi ve bu yüzden çevik süreçlerin bir işe yaramadığı düşünüldü. Oysaki container ve microservice dünyası için çevik süreç biçilmiş bir kaftan. Yıldızı söndüğü zannedilen çevik süreçler bulut bilişim ile ne olduklarını ispatlayacaklar.


Not: Eğer extreme programming gibi safkan bir çevik sürecin nasıl işlediğini merak ediyorsanız, size pratik agile isimli ücresiz kitabımı tavsiye etmek isterim. Çevik süreçler hakkındaki yazılarıma buradan, buradan ve buradan ulaşabilirsiniz.


EOF (End Of Fun)
Özcan Acar

Yazılım Dünyasının Hızlı Çözüm Üretmek İle Olan İmtihanı

Yazılım neden vardır sorusu sorulduğunda, benim aklıma gelen ve benim için en anlamlı cevap yazılımın müşterinin gereksinimlerini tatmin etmek için var olduğudur. Müşteri piyasa ihtiyaçlarından doğan gereksinimlerini tatmin etmek ya da piyasa rekabetinde avantaj sağlamak için yazılıma yönelir. Yazılım müşterinin piyasa şartlarında ayakta kalkmak için kullanacağı en kıymetli araç haline gelebilir. Sektörüne göre yazılım olmadan bir firmanın piyasa işlevini yerine getiremediğini, rakiplerine yenik düştüğünü ve yök olduğunu ya da yetersiz yazılım yüzünden yok olma riski ile karşılaştığına tanık olmak mümkündür.

Yazılımın artık çok kıymetli bir konumda olduğu konusunda hemfikir olduğumuzu düşünüyorum. Böyle bir ihtiyacın olması yazılım sektörünün temelini oluşturuyor. Firmalar ihtiyaçları doğrultusunda ya kendi yazılım takımlarını oluşturuyorlar ya da mevcut yazılım ürünlerini satın olarak bu konudaki ihiyaçlarını tatmin etmeye çalışıyorlar.

Burada yapı olarak çok değişik iki dünyanın karşı karşıya geldiğini görmekteyiz. Bir tarafta çok hızlı değişen piyasa koşulları neticesinde oluşan yeni müşteri gereksinimleri, diğer tarafta o kadar çok da hızlı müşteri gereksinimlerine adapte olmayan yazılım ürün/ürünleri. Müşteri bulunduğu piyasada önde gidebilmek için kullandığı yazılım ürününde hızlıca değişiklik yapılmasını talep edecektir. Lakin yazılımdaki en büyük problemlerden birinin bu noktada oluştuğuna tanık olmaktayız. Ne yazık ki kurumsal çerçevede geliştirilen yazılım ürünlerde istenilen değişikliklerin rekabetin önünü açacak hızda yapılamadığını görmekteyiz. Bunun başlıca sebebi yazılımda silolaşmaya gidilmesidir.

Günümüzde yazılım değişik vasıflara sahip grupların birlikte çalışarak yerine getirilen bir aktivitedir. Yazılımcılar kod yazmaktan, testçiler bu kodu test etmekten, oplar yazılan ve test edilen kodu canlıya almaktan sorumludur. Sadece bir önceki cümle içinde bile üç değişik meslek gurubunun adı geçti. Bunlara analizcileri, proje yöneticilerini ve ürün sahiplerini de eklersek, aslında çok değişik nitelikteki insanların bir araya gelerek, yazılım oluşturduklarını görmekteyiz. Ama bu gerçekten böyle olmak zorunda mıdır? Asıl sıkıntılar buradan kaynaklanıyor olabilir mi? Neden yazılım silolardan oluşan değişik ekiplerin elinden geçerek, oluşmak zorunda?

Yazılımla uğraşan herkes bilir. Yazılımcı ekibi yazdıkları kodun canlıya alınmasından, canlıyı (production) koruyup, kollayan op ya da admin ekibi de yazılımdan bihaberdir. Op ya da adminler her zaman canlının canlı kalması için ellerinden gelen her türlü işlemi yaparlar ve yeni yazılım ürünleri ya da mevcut yazılım ürünlerinin yeni sürümlerini canlıya almak için kırk dereden su getirirler. Onların uzun checklisteleri vardır. Bu listeler canlıyı korumak amacılıdır lakin hem yazılımcıları canlarından bezdirirler hem de değişikliklerin hızlıca canlıya alınmasını engellerler. Bu sadece op ya da adminlerle sınırlı bir durum değildir. Yazılıma yeni bir özelliğin eklenip, canlıya alınması aylar sürebilmektedir. İş ne yazık ki değişik silolarda çalışan değişik nitelikteki çalışanların tüm resmi göremeyerek, sadece kendi siloları bünyesindeki çalışmalara odaklanmalarından dolayı uzayaip gider.

Durumu kısaca özetleyecek olursak… Bir tarafta hzli değişeçen piyasa koşullarına adapta olmak isteyen müşteri ve yazılımdan olan beklentileri, diğer tarafta değişik silolarda organize olmaya çalışan ve yeterli hızda müşteri isteklerine cevap veremeyen yazılım ekipleri. Burada kaybeden kimdir? Her iki taraf da!

Yazılım sektörü ve camiası uzun bir süredir problemin farkında ve yer yer çözüm üretmeye çalışıyor. Bu çözümlerden birisi DevOps olarak bilinen akım. DevOps benim tanımıma göre yazılımı yapan, canlıda işleten ve her türlü yetki ve sorumluluğa sahip yazılımcıdır. Lakin yine bu konuda da işin sulandırılması sağlanmış ve yazılımcı ekibine gerekli tüm yetki ve sorumluluk verileceği yerde, op ve adminlerin biraz yazılımdan anlayacak ve gidişata destek olacak şekilde yeniden konuşlandırılması sağlanmış ve silo düşüncesine sağdık kalınması yeğlenmiştir. Hala hazırda birçok kurumsal altyapıda devopsları, testçileri ve yazılımcıları beraber çalışır durumda görmek mümkündür. Bir şekilde, yazılım sistemini oluşturan yazılımcıların aynı zamanda canlı için sorumluluk taşıyabilecekleri ve bu görevi yerine getirebilecekleri inancı hala oluşmamıştır. Bunun sebebi nedir?

Bunun başlıca sebebi yöneticilerin yazılımın nasıl işlediğinden bihaber olmaları ve yazılım için gerekli organizasyonel yapıyı oluştururken klasik kurumsal kadrolaşma ve iş yapma şablonlarından faydalanmalarıdır. Klasik organizasyonel yapılarda birileri bir ürünü oluşturur, birileri gerekli tasarımı yapar, birileri kalite konotrulünden sorumludur ve birileri de bu ürünleri pazarlar. Roller ve iş tanımları birbirlerinden keskin bir şekilde ayrıdır ve herkesin görevi detaylı olarak tanımlıdır. Lakin bir yazılım ürünü söz konusu olduğunda, ürünün pazarlanması haricinde gerekli tüm işlerin yazılımcılar tarafından yapılabileceğini söyleyebiliriz. Bunun en güzel örneğini Extreme Programming gibi gerçek çevik yazılım metotlarının uygulandığı projelerde görmek mümkündür. Böyle birçok projede yazılımcı olarak çalışmış birisi olarak söyleyebilirim ki gerçek bir çevik süreç içinde yazılımcılar her türlü sorumluluğu üstlenebilirler ve doğru olan zaten budur.

Klasik iş ayrımı verimliliği artırmak ve vasıf bazlı ücretlendirmeyi mümkün kılmak için kapitalizmin oluşturduğu bir prensiptir. Örneğin klasik bir fabrika üretiminde bant üzerinde oluşan ürün kademeli olarak değişik ellerden geçer. Ürünün oluşumuna katkı sağlayan her el belli bir vasfa sahiptir ve çok hızlı bir şekilde kendi üzerine düşen görevi yerine getirir. Eğer ürüne dokunan el gerekli vasfa sahip değilse, ürünün oluşturulma süreci uzar ve bu maliyeti artırır. Bu yüzden vasıflar silolar bünyesinde gruplaştırılır ve ürün üzerinde iş gücü olarak uygulanır. Seri şekilde üretim yapıldığı sürece bu tarz bir iş gücü organizasyonunun faydalı olduğunu söyleyebiliriz. Lakin nasıl bir ürünün ortaya çıkacağı belli olmayan durumlarda, bu silolaşma ne yazık ki iş koordinasyonu, bilgi ve vasıf yetersizliği ve tüm resmi görememe gibi durumlardan ötürü istenilen sonucun sağlanması konusunda yetersiz kalmaktadırlar. Bunun ispatını günümüzde uygulanan bilimum yazılım projelerinde görmek mümkündür.

Yazılım endüstrisinin yaptığı işten verim almak için ihtiyaç duyduduğu tüm araç, gereç ve metodolojiler gözünün önünde durmaktadır, lakin bunları kullanmak yerine nedendir bilinmez, iş gücünü silolaşmaya götürmekte inat etmektedir. Extreme Programming gibi çevik süreçler yazılımın nasıl yapılması gerektiği konusunda gerekli tüm metotları ihtiva etmektedirler lakin sahip oldukları inovasyon gücü göz ardı edilmektedir.

Çevik süreçlerde bilimum sorumluluk yazılım ekibindedir. Yazılım ekibi müşteriye kulak verir, gerekli yazılımı yapar ve çok kısa aralıklarla oluşan yazılım ürününü müşteriye gösterek, geri bildirim sağlar. Bu geri bildirim ile istikametini belirler. Kendisi yazar, kendisi test eder, kendisi canlıya alır ve kendisi hataları giderir. Google Site Reliability Engineering ismi altında bu prensibi uygulamaktadır. Google yazılım ürünlerinde bütün işi çekip, çeviren yazılımcılardan oluşan takımlardır.

Yazılım endüstrisi kör değil. O da gidişatın doğru olmadığının farkında ve DevOps gibi yerinde ama uygulanışı absürd olan yöntemler geliştirilmekte. Yazılımdan anlamayan sistem adminlerini birkaç günlük bulut eğitimlerine göndererek, onların DevOps olması sağlanamaz. DevOps ile kasıt, canlı ile arasında hiçbir engel kalmamış ve canlının sorumluluğnu da üstlenmiş, yani bu işi a dan z ye yapabilen yazılımcılardır. Bunu anlaması neden bu kadar zordur? Karşımızda bu işin üniversitede eğitimini almış ve her türlü mühendislik çözümü üretebilen yüksek vasıflı yazılım ve bilgisayar mühendisleri durmaktadır. Onları bir kenara koyup, “siz sadece kod yazın” demek, yaşadığımız sorumların başlıca nedenidir.


Özcan Acar
EOF (End Of Fun)

Yazılımda Çeviklik İflas mı Etti?

Çevikliğin Böylesi başlıklı yazımı okudunuz mu? O yazımda çevik kelimesinin yerli yersiz her şey için kullanıldığını ve bu yüzden anlam erozyonuna ugradığından bahsetmiştim. Bu yazımda çevikliğin tanımını yapmaya çalışacağım.

Martin Fowler bu link üzerinden ulaşabileceğiniz yazısında şöyle diyor:

… lack of rigorousness is part of the defining nature of agile methods, part of its core philosophy. … Any attempt to define a rigorous process that can be tested for conformance runs contrary to [the agile] philosophy.

Martin Fowler yazılımda çevikliğin belli bir çerceveye sokulmuş bir süreç (process) olarak tanımlanmasının mümkün olmadığını, bunun çeviklik filozofi ve düşüncesine ters düştüğünü söylüyor.

Bazı kesimler Martin Fowler’in sözlerini çevikliğin iflası olarak yorumlayabilirler. Onların mutlaka katıksız bir tanımlamaya ihtiyacı var, çünkü ipe sapa gelmeyen bir şeyin pazarlamasını yapmak mümkün değil. Bu yüzden çeviklik filozofisinin sadece bir kısmını ihtiva eden yarım yamalak çevik süreçler tanımlamaya ve satmaya çalışıyorlar. Onlar için önemli olan elle tutulur, gözle görülür ve ölçülebilir bir süreç tanımlaması yapmak. Eğer A, B, C adımlarını uygularsan, X, Y neticesini elde edersin diyebilmek istiyorlar. Keşke müşteri gereksinimleri odaklı yazılım bu kadar basite indirgenebilseydi!

Bu sebeptendir ki birçok sözde çevik süreç ile istenilen neticeler elde edilemiyor, çünkü sürecin ihtiva ettiği adımları birebir uygulamak her projede mümkün olmuyor. Doğal olarak bu durumda sürecin yeniden tanımlanıp, ihtiyaçlar doğrultusunda yeniden yapılandırılması gerekiyor. Sözde çevik süreçler bu değişime izin vermedikleri için yazılımda çeviklik yarı yolda kalıyor.

Benim Çeviklik Tanımım

Ben yazılımda çevikliği bir soğanın kabukları gibi iç içe geçmiş, değişik katmanlardan oluşmuş bir yapı olarak görüyorum. En üst katmanda değişikliklere karşı koymadan, onlarla beraber yaşayabilmek için gerekli olan cesaret yer alıyor. Yazılımda çeviklik cesaret ile başlar ve en içteki katmana kadar varlığını sürdürür. Değişiklikle yaşamak ve yeni yollar, yöntemler keşfetmek için birey ve ekip bazında casaret gereklidir. Bunun olmadığı yerde sadece sözde çeviklik olabilir.

Sözde çevik süreçlerde cesaretin yerini sabit süreç tanımlamarı alır. Bunlar tek tek ve sırayla atılması gereken adımlardır, bir nevi yemek tarifidir. Değişikliğe bu şekilde bilinçaltı karşı konulmaya ve her şey daha kontrol edilir hale getirilmeye çalışılır. Yazılım projelerinde değişmeyen tek parametrenin değişikliğin kendisi olduğunu düşünecek olursak, sabit süreç tanımlamaları ile buna karşı koymanın imkansız olduğu ortadadır. Sabitlik isminden de anlaşıldığı gibi dinamizmin karşıtıdır ve ani değişikliklere cevap verebilecek nitelikte ya da değişikliklere adapte olacak yapıda değildir. Değişikliğe karşı koymanın tek yolu, ona karşı koymamak ve onunla beraber yaşamayı ögrenmekten, bunun yolu da cesaret ve cesaretli olmaktan geçer.

Casaret aynı zamanda müşteriye devamlı ne istediğini sorabilmektir. Bu amaçla yazılımda çeviklik çok kısa döngülerin doğurduğu geribildirimlerden beslenir. Bu döngülerin başında proje gidişatını yönlendirmek için kullanılan iterasyon bazlı planlama yer alır. Değişikliğin her an damdan düşer gibi projeyi alt üst edebilecegini varsaydığımızda, buna karşı koymanın en kolay yolu, projeyi kısa ve tanımlanmış zaman dilimlerinde müşterinin gereksinimlerini tatmin edecek seviyeye getirmektir. Bu örneğin bir ya da iki haftalık bir zaman dilimini ihtiva eder. Bu zaman diliminde müşteri kendisi için önemli olduğunu düşündüğü gereksinimlerini tespit edip, gerçekleştirilmek üzere yazılım ekibiyle paylaşır. Yazılım ekibi müşterinin seçmiş olduğu gerekli gereksinimleri hayata geçirir. Ekip seçilen gereksinimlerin öngörülen zaman diliminde tamamlanır tarzda olmasına dikkat eder. Öngörülen zaman dilimi tamamlandığında müşteriye çalışır bir prototip sunulur ve kendisinden geribildirim sağlanır. Bu noktatan itibaren müşteri gidişati kontrol edebilir bir araca sahiptir: çalışan bir prototip. Çoğu zaman müşteri bu prototipe bakarak sahip olduğu gereksinimleri doğru olarak tanımlamadığının farkına varır. Bu kendisi ve yazılım ekibi için bir geribildirimdir ve değişikliğin habercisidir. Bir sonraki çalışma safhasında (iterasyon) ekip bu geribildirimden beslenerek, müşterinin gereksinimlerini tam anlamıyla tatmin edecek değişikliklere gider.

Geribildirim alma çevikliğin ana temellerinden birisini teşkil etmektedir. Müşteriye ne istediğini sorarak, iterasyon bazlı çalışıp prototipler oluşturarak, sürekli entegre edip, entegrasyon seviyesinin ne durumda olduğunu sorgulayarak, birim testleri yazıp, uygulamanın test edilbilirliğini ölçerek birçok katmanda geribildirim ediniyoruz. Bu bizim yazılımcılar olarak müşteri gereksinimlerinin ifade edilmesi ile yazılımcılar tarafından tatmin edilmesi arasında nerede durduğumuzu anlayayıp, tartabilmemiz için çok önemli bir veri olma özelliği taşımaktadır.

Teknik olarak yazılımda çevikliği incelediğimizde çevik olmanın çekirdeğinde çok önemli bir metodun yer aldığını görmekteyiz: uygulamayı yeniden yapılandırma. İngilizce refactoring olarak isimlendirilen bu yöntem, biz yazılımcılara yeni müşteri gereksinimleri ile uygulamayı hamur gibi yogurma yetisi kazandırmaktadır.

Birçok sözde çevik süreci ya da çevik süreçlerin uygulandığı projeleri yakından incelediğimizde, başarısızlıklarının sebebinin uygulamayı hamur gibi yoğurma kabiliyetlerinin olmadığından kaynaklandığını söylemek mümkündür. Bazı sözde süreçler uygulamanın yeniden yapılandırılabilme özelliğine oluşturdukları gidişat planında yer bile vermemektedirler. Bir uygulamanın müşteri gereksinimlerine cevap verebilmesi için yeniden yapılandırılabilmesi gerekmektedir. Bunun ne olduğunu bile bilmeyen ya da tanımlayamayan bir çevik süreç nasıl çeviklik ibaresi olma savına sahip olabilir? Bunu anlamak güç!

Belki çevikliği tanımlamak kolay değil. Belki bu sebepten dolayı herkes her şeye çevik ismini takabiliyor. Ama bildiğim bir şey var, o da birim testi yazmadan ve sürekli refactoring yapmadan çevik olunamayacağıdır. Bu ikisinin nasıl yapılması gerektiğine dair birçok kaynak bulmak mümkündür. Martin Fowler’in Refactoring isimli kitabı yazılımcılara bu konuda ilham kaynağı olacaktır. Refactoring’i mümkün kılmak için birim testleri yazılması gerekmektedir. Bunu isteyen test güdümlü (Test Driven Development), isteyen klasik tarzda uygulamayı kodladıktan sonra yapabilir. Test güdümlü yazılımı şiddetle tavsiye etmekle beraber, klasik birim test yazılımını da hor görmüyorum. Uygulamayı hamur gibi yoğurabilmek için otomatik çalışan her türlü birim testi mübahtır. Bu birim testleri yeniden yapılandırma sürecinde oluşan hataları yazılımcıya gösterirler. Bunun yanısıra yazılımcının özgüvenini artırarak, daha cesaretli bir şekilde yeniden yapılandırma sürecine dahil olmasını sağlarlar. Birim testleri olmadan mantıklı çercevede uygulamanın yeniden yapılandırılması mümkün değildir.

Müşteri gereksinimlerini tatmin etmek için oluşturulan bir uygulama, üç katlı bir apartman gibi sabit bir yapı değildir. Uygulama devamlı değişiklige maruz kalır, çünkü müşteri kendi çalışma sahasında değişikliğe maruz kalmaktadır. Bunun doğal olarak uygulamaya yansıması gerekmektedir. Aksi taktirde uygulama müşterinin güncel gereksinimlerini tatmin edemez. Müşterinin gereksinimlerini tatmin edemeyen bir uygulama, işe yaramayan bir uygulamadır.

Demek oluyor ki “Birim testi yoksa refactoring yok. Refactoring yoksa çeviklik yok. Çeviklik yoksa, müşteri yok (olur)”. Benim çeviklik konusundaki formülüm bu.

EOF (End Of Fun)
Özcan Acar