Arda Çetinkaya Yazılım ve arada kendim ile ilgili karaladıklarım…

“User Story”, Scrum’da çok önemli kavramlardan bir tanesi. Aslında tüm yazılım geliştirme projelerinde bu kavram var. Ama farklı şekilde ele alındığından ya da gerekliliği ve önemi çok farkında olarak ele alınmadığından dolayı zaman zaman havada kalan bir kavram olabiliyor.

Genellikle çeşitli analizlerden sonra ortaya çıkan iş gereksinimlerinden(Business requirments),  fonksiyonel gereksinimler(Functional requirments) ortaya çıkartılıyor ve yapılacak iş(task-item) şeklinde ele alınıyor. Ama ne yazık ki çok da doğru bir şekilde “task” olarak ele alınmadığından dolayı(-ki bu noktada, kişisel olarak “task” olarak bir kavramın bu aşamada ele alınmasının doğru olduğuna inanmıyorum) gün sonunda sahipsiz, fazla bir şey ifade etmeyen, ya da ifade ettiği kavramın ürün açısından bir geçerliliği olmayan kavramlar ortaya çıkıyor. Geliştirme bittiğinde, çıkan ürünle bu “task”lar karşılaştırıldığında çok farklılıklar gözlemleniyor falan. Geliştirme sürecindeki en önemli sorunlardan biri sanırım da bu.

Bu noktada “User Story” kavramının çok iyi anlaşılıyor olması, fonksiyonel ihtiyaçları ortaya çıkarmada ve paylaşmada çok önemli. “User Story” basitçe; ürünü kullanan veya ürün sahibi için değerli olan ve anlam ifade eden fonksiyonel(?) özelliklerin belirtildiği ifadeler demek çok da yanlış olmaz sanırım. İfade yöntemi olarak bir çok kaynakta, belli formatlar da kartlar görebilirsiniz. Ama artık çokta tercih edilen bir yöntem olduğunu düşünmüyorum kendi tecrübelerimden dolayı. Pratikliğin önemli olduğu Agile yöntemlerde bu tarz kartlar hazırlamak falan sıkıcı olabilir. “User Story”leri postitler ile ifade ediyor olmak en kolay yöntem.Ki “User Story”lerin herkes tarafından kolayca ulaşılabilecek olması postitlerin sağa sola yapıştırılabiliyor olmasından dolayı da postitlere artı puan katan bir nokta.(: (Sponsor:Post-It)

Fonksiyonel özelliklerin ifade yöntemi dedik…Peki ne kadar ayrıntılı olacak bu ifade? Çok fazla değil…Ürün sahibi veya kullanıcı acısından değeri olan tek bir anlamlı cümle yeterli olacaktır.

As a user, I want to post a comment to your blog with my Facebook account,so that I do not have to create another account in your blog.

Yukarıdaki örnekteki gibi tek cümle olarak ifade ediliyor olması, yapılacak işlerin daha net ortaya çıkmasında faydalı olacaktır. “As a <rol>, I want to <amaç>, so <sebep>” şeklinde bir format Scrum’ı ortaya çıkaran kişilerin “User Story” için gösterdiği bir format. Amaç ve sebep ilişkisi açısından ele alındığında da ne kadar doğru bir ifade şekli olduğunu zaten kendi de gösteriyor. Burada bir başka önemli nokta “User Story”lerin herkes için aynı şeyi ifade ediyor olması gerekliliği. Takımdaki kişiler için farklı şeyler ifade ediyorsa bir “User Story”, onun için çok da anlamlı bir “User Story” demek doğru olmayacaktır.

Yukarıdaki örnekteki <rol>,<amaç> ve <sebep> kavramlarının netliği “User Story”nin anlamını güçlendirecektir. Buradaki;

  • Rol: Ürün sahibi,ürün kullanıcısı,geliştirici,testçi gibi proje ve takım içerisinde olan herkes olabilir.
  • Amaç: “User Story”nin ifade etmeye çalıştığı, ürün özelliği ya da fonksiyonu.
  • Sebep: Yapılacak ya da geliştirilecek olan özelliğin sebebi.

Başarılı ve doğru bir “User Story”nin dayandığı bir kaç özellik var. Tabi ki bunlar kesin ve doğru şeyler değil ama bir çok kaynakta benzer şeylerden bahsedildiğini göreceksiniz.”User Story”ler birbirinden olabildiğince bağımsız olmalıdır. Bu bir “User Story”nin net olarak anlaşılması için en önemli faktördür. Bazı ürün fonksiyonları geniş bir ifadeye sahip olabilir, bunları yapabildiğimiz kadar anlamlı parçalara ayırmak önemlidir.

“User Story”ler kural babında kesinlik ifade etmemelidir. Takım tarafından tartışılabilir ve geliştirilebilir. Zamanla değişecek ihtiyaçlardan dolayı bu yaklaşımda yazılması, değişen ihtiyaçları daha iyi görmede yardımcı olacaktır.Aynı zamanda “User Story”nin farklı bakış açıları ile doğru bir şey ifade etmesi de bu yolla olacaktır.”User Story”ler yukarıda da bir çok kere belirttiğim üzere değerli ve anlamlı olmalıdır. Açıkcası bence en önemli özellik bu.

“User Story”ler tahmin edilebilir olmalıdır. Bu tahminin gerçekçiliğinden çok, “User Story”lerden çıkacak “task”ların tahmininin gerçekliği daha önemlidir. Direk “User Story”e tahmini bir puan vermekten çok, tahmin sırasında oluşturulacak “task”lara tahmini bir puan vermek ve bunların toplamı ile “User Story”nin tahmini puanının ortaya çıkmasında daha doğru bir yol olduğunu söyleyebilirim.Bu konuda çok sorun yaşadık ama sonradan ayırdığımız “task”lara verdiğimiz tahmini zamanlar puanlarının daha anlamlı olduğu kanısına varmıştık.

“User Story”ler küçük ama anlamlı olmalıdır. Ne kadar büyük olursa, karmaşıklığı o kadar artar,anlamı o kadar derinleşir. Çok fazla küçük olursa da ifade etmeye çalıştığı kavram o kadar silik olur.

Şimdilik “User Story”ler ile ilgili olarak tecrübelerime göre bunları söyleyebilirim. Önceki yazılarımda da söylediğim gibi bu konuda ciddi bir bilgi paylaşımına girmek istiyorum, ilgileniyorsanız mutlaka fikirlerinizi, sorularınızı, eleştirilerinizi paylaşın.

Agile yazılım geliştirme metodlarından Scrum’da, geliştirme sürecinde, çıkacak ürünün özelliklerini ortaya çıkarabilmek ve bunları iyi analiz edebilmek çok önemli. X adında bir ürün geliştireceğimizi düşünelim. Belli bir amaç için geliştirdiğimize göre, bu amaç(lar) doğrultusunda ürünümüzün belli özellikleri olacaktır. Bu özelliklerin uygulanma açısından da çeşitli fonksiyonlar olacaktır. Tabi bütün bunlar son kullanıcı ya da ürün sahibinin ihtiyaçları ve üründe gerçekleştirmek istediği işlerden(scope) oluşacaktır.

Scrum’da bunların listesine “Product Backlog” deniyor. Scrum’ın uygulanabilmesi için olmazsa olmaz bir kavram bu “Product Backlog”. “Product Backlog” listesi oluşturulurken, analiz sonuçlarından ve daha önceki projelerdeki tecrübelerden yararlanılır. Bu liste sadece yapılacak ürünün özelliklerini içermek zorunda değildir. Ürünün özellikleri ile ilgili, önceki tecrübelerden ortaya çıkmış ve ürünü geliştirirken etki edebilecek kavramlarda bu listeye alınmalıdır. Teknik olarak geliştirme sürecinde direk olarak bir şey ifade etmeyen ama dolaylı olarak ürünün genelinde etki edebilecek kavramlar da bu liste dahilinde ele alınabilir.

Bu liste oluşturulurken, herkes katkıda bulunabilir. Geliştiriciden, ürün sahibine, proje yöneticisinden, test ekibine kadar geniş bir kesim bu listenin oluşmasını sağlar. Ne kadar çok katkı olursa o kadar sağlıklı bir “Product Backlog” çıkacaktır.Tabi herkesin katkı yapıyor olması, her katkının da bu listeye dahil olacağı anlamına gelmiyor. Tabi ki listeyi oluştururken de “scope”un dışına çıkmamak gerekiyor.

Bu listenin en önemli ve Scrum tarafından anlam taşıyan bir diğer özelliği listedeki maddelerin bir öncelik(priority) sırasına sahip olması. Bu öncelik sırası, sadece ürün sahibi(product owner) tarafından belirlenmelidir. Bunun nedeni az önce de kullandığım “scope” kavramının dışına çıkılmasını engellemektir.

Şimdilik bu kadar, bu konuda her türlü fikrinizi,düşüncenizi veya sorunuzu bekliyorum…

Bir önceki yazımda WPF’de kontrol içerisindeki kontrollerde oluşan “event” sorunundan bahsetmiştim. Aslında sorun değil, WPF’deki “event” yaklaşımının biraz farklılaştığını belirtmeye çalışmıştım. Bu yazıda biraz daha derinlere girip, WPF’deki “Routed Events”‘den bahsetmeye çalışacağım.

WPF, kullanıcı deneyiminin uygulamalarda daha rahat bir şekilde uygulanmasını amaçlıyordu hatırlarsanız. WPF’in ortaya ilk çıktığından beri Microsoft’un altını çizdiği nokta bu yönde. Bu bağlamda, standart bilgisayar uygulamalarında ki standart arayüzler yerine kullanıcının çok daha kolay kullanabileceği bir arayüz sunmak ve bu arayüz ile sunulan bilgileri de daha anlamlı bir görsellikte sunarak kullanıcı deneyimini uygulamalara katmak WPF’in ilerlediği yollardan bir tanesi diyebiliriz. Bu yaklaşımdan dolayı, WPF ile beraber alıştığımız kullanıcı kontrollerinden farklı bir yapı karşımıza çıkıyor. Tıkladığımız düğmeler WPF ile beraber daha farklı amaçlar için kullanılabilir hale geliyor. Ya da bir çok elemandan, seçim yapabileceğimiz kullanıcı kontrolleri içerik olarak daha anlamlı bilgiler içermeye başlıyor.

Mesela bir düğme(button)nin içine resim koyarak, düğmenin görselliğine farklı anlamlar yükleyebiliyoruz.Bu çok basit bir örnek oldu gerçi ama demek istediğim, WPF’de kullanıcı kontrollerini, farklılaştırarak zenginleştirebiliyoruz. Kontrolleri iç içe kullanabiliyoruz. Bir “button”(düğme) içine “image”(resim) kontrollü koymak gibi. Katmanlı bir kullanıcı kontrolü yapısı var demek biraz daha netleştirebilir belki.

“Routed Events” kavramı da bu yapıdan dolayı ortaya çıkıyor. Yukarıda bahsettiğim kontroller üzerinden örneklendirmek daha anlaşılır olacak sanırım. Aşağıdaki uyduruk resimde(:)) bir “button” içinde “image” var.

Şimdi “button”a tıklandığı zaman “click” olayı oluşur bildiğiniz üzere. Ve tıklandığı zaman ne olmasını istiyorsanız bu olaya(event) denk gelen metodda ilgili kodu yazarsınız. “button” tıklandığı zaman ne oluyorsa, aynı işlem üzerinde “image” kontrolü olan “button”a tıklandığında da olmalı. Tıklanan alan “image” kontrolüne denk geliyorsa tıklama işleminin “button” tarafından da anlaşılıyor olması lazım. Bundan dolayı “image” üzerinde bazı işlemlerin, “image”ı içeren kontroller tarafından da algılanabiliyor olması lazım. WPF bu işlemi “routed events” kavramı ile gerçekleştiriyor.Özetle WPF’de bir “event” başka elemanlara yönlendirilebiliyor.

Bir önceki yazıda gerçekleşen olayın sebebi bu yani. WPF’de bir uygulama geliştirirken, “routed events” kavramını kendi geliştireceğiniz kontrollerde kullanmanız kaçınılmaz olacaktır. İlerleyen yazılarda bununla ilgili çok basit bir örnek göstermeye çalışıyor olacağım…Şimdilik bu kadar.

Not: “button” ve “image” anlaşılır bir örnek olması açısından kullandığım kavramlar. WPF’deki mevcut tüm yapılar için “routed events” kavramı geçerlidir.

, ,

Geçen gün bir arkadaşımın WPF(Windows Presentation Foundation)’den çektiği dertleri Twitter’dan gördüm ve benzer bir sorunu yaşadığım için şaşkınlığını çok iyi anladım. WPF kavram olarak çok güzel şeyler vaad ediyor olsa da, açıkcası tam olarak oturmuş bir yapı olduğuna inanmıyorum. İlk çıktığı zamandan beri kendimce küçük uğraşlar ile WPF’i elimden geldiğince takip etmeye öğrenmeye çalıştım,çalışıyorum da. Diğer .NET Framework yapıları ile kıyaslandığında farklılıkları ve değişiklikler ciddi anlamda uğraştırıyor.Neyse çok dağıtmadan konuyu, özüne dönelim.

WPF’de “control” yapısı, ASP.NET ve Windows yapısına göre biraz daha farklı. Bu farklara değinmek şimdi uzayacağından sadece farklı olduğunun altını çizmek yeterli olacaktır şu aşamada.

Sorunumuz ne peki? TabControl içinde kullandığımız Listbox,Combobox gibi yapılarda “SelectionChanged” event’i(olayı) çalıştığı zaman tabcontrol’ün de “SelectionChanged” event’i çalışmakta.Bunun nedenlerini inceleyerek sorunu çözmek, WPF’i anlamak adına daha faydalı olacağından olayın en temeline inerek çözümü sunmaya çalışacağım.

WPF’de “Selector” diye bir sınıf var. Listbox,Combobox gibi seçme işleminin yapılabileceği kullanıcı kontrolleri bu sınıftan türemekte.  “Select” operasyonunun yapılacağı kontrollerin “Selector”dan türemesi kavram olarak bakıldığında çok normal. WPF’de TabControl diye bildiğimiz sekmeli bir yapı sunan kontrolde WPF’de “Selector”dan türemekte.Yani ListBox,Combobox ve TabControl aynı kategoride diyebiliriz daha basitçe.Bu kontrollerin “SelectionChanged” event’i Selector sınıfından gelmekte ve dinlenmekte. TabControl’ün veya Combobox’ın ne yazık ki kendilerine özgü düzenlenmiş bir SelectionChanged event’i yok.Bundan dolayı “Selector.SelectionChanged” event’i tetiklendiği zaman Selector sınıfından türeyen sınıflarda bu event’i kontrol etmeye çalıştıklarında başarılı olacaklardır.Yani daha açık bir şekilde; TabControl’ün SelectionChanged event’inde çalışan bir metodu olduğunu varsayalım:

81 protected void TabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)

82 {

83 //tab seçildi

84 }

Aynı şekilde Tabcontrol’ün içindeki bir ComboBox’ın da aynı event’de çalışacak bir metodu olduğunu varsayalım:

86 protected void Combobox1_SelectionChanged(object sender, SelectionChangedEventArgs e)

87 {

88 //combox’da seçildi

89 }

Uygulama çalıştığı zaman ComboBox’dan bir seçim yaptığınızda, ComboBox’ı içeren kontrolün(TabControl oluyor bu durumda) de SelectionChanged olduğu zaman çalışacak metod da çalışacaktır…Çok ilginç değil mi? Bunun nedeni yukarıdaki kısa açıklama. Ama asıl nedeni WPF’de ki event mekanizması.WPF ile beraber Routed Events diye bir kavram hayatımıza giriyor.Bir sonraki yazımda bunun ne olduğunu anlatmaya çalışacağım, çünkü WPF ile uğraşanlar için oldukça önemli bir şey olduğuna inanıyorum.Neyse sorunumuza dönelim…Şimdi en son combobox’ı seçmiştik ve tab kontrolününde metodu çalışmıştı. Bunu istemiyoruz tabi ki…Peki ne yapacağız…

Event argümanlarının(e parametresi oluyor metoddaki) “Handled” diye bir özelliği var. Bu özelliği “true” olarak değiştirdiğiniz zaman oluşan olayı(event) yakalamış olduğumuzu belirtiyoruz.

86 protected void Combobox1_SelectionChanged(object sender, SelectionChangedEventArgs e)

87 {

88 //combox’da seçildi

89 e.Handled = true;

90 }

Bu sayede TabControl’ün event’i çalışmamış oluyor…WPF ile geliştirme yaparken, bu tarz sorunları aslında sorun olarak değilde, değişiklik olarak algılamak gerekiyor sanırım.Neyse şimdilik bu kadar…Her türlü soru,sorun,düşünce fikir paylaşımına açığım,bekliyorum…(:

, ,

Projelerde yapılacak işlerin ne kadar süre içerisinde yapılacağını tahmin etme süreci oldukça sıkıntılı geçer. Her ne kadar yapılacak işlerin analizini iyi yapmış olmak bu sürece olumlu katkı sağlasa da, öngörülemeyen sorunların ya da ihtiyaçların etkilerini bu süreç kapsamında kestirmek zor olduğundan yapılan tahminler çok geçerli olmaz. Sürecin adı “Estimation”(tahmin) olarak geçtiği için, zaten kesin bir zaman birimi söylemek çok da mantıklı değil.Tahmin etmek bütün olay. Ama tabi ki bu tahminlerin bir değer taşıyor olması ve bu değerin farkında olmak gerekli.

Yazılım projelerinde de “estimation” yapılması gereken bir olay. Yani müşteriye verilecek sözden ya da kontrattaki maddelerden ayrı olarak, yazılım geliştirme sürecinde, sürece katkı sağlayacak bir kavram. Yazılım geliştirirken hangi adımlarda ne kadar süre harcandığını görmekte, geliştirme sürecince görev dağılımın iyi yapılmasına katkı sağlayacaktır.

“Planing Poker”, olarak geçen poker planlaması tahmin süreçlerinin en basiti ve etkili yöntemi olduğunu düşünüyorum kendi tecrübelerimden. Agile(çevik) yazılım geliştirme metodlarında  tercih edilen bu yöntem aynı zamanda oldukça da zevkli…

Basit olarak poker planlaması, projedeki “item”ların ne kadar süre içerisinde yapılacağını interaktif bir şekilde tahmin ederek gerçekleşir. Bu süre kavramı belli bir puanlama sistemi ile yapılır. Normal sayısal değerlerin kullanılabileceği gibi Fibonacci sayılarının(0,1,2,3,5,8,13,21,34….) kullanılması tavsiye edilir. Bunun nedeni, Fibonacci sayıları ile yapılan tahminlerin daha anlamlı olabilecek olması. Şöyle ki;  “item” için tahmini olarak verilecek zaman yükseldikçe, o tahminin anlamı da aynı şekilde bulanıklaşacaktır.Yani bir “item”a 20 birim ya da 22,23 birim şeklinde bir zaman tahmini veriliyor olması birim değerinin yüksek olmasından dolayı çok da bir şey ifade etmez. 20,22,23 şeklinde değil de zaman biriminin “yüksek” olması şeklinde daha anlamlıdır. Aynı şey zaman biriminin düşük olarak tahminlendiği “item”lar için geçerli değildir. Düşük zaman tahmini şeklinde belirlenen “item”lar, farklı şekilde yorumlanarak önceliklendirme konusunda etkili olabileceklerinden dolayı yukarıdaki gibi yorumlanmamalıdır.Bu arada hep zaman birimi olarak bahsettim. Ama peki birim olarak ne kullanmak gerekli? Tahminleme yapılırken kullanılan zaman birimi,”saat” ve “gün” şeklinde projenin büyüklüğüne göre değişkenlik gösterebilir.Ya da uyguladığınız geliştirme metodolijisi içerisinde belli bir puan sistemindeki puana da denk gelebilir.

Poker planlamasının nasıl yapıldığına geçelim şimdide. Öncelikle tahminlemenin yapılacağı olan “item”lar açıklanır. Bu işi geliştirme sürecine hakim bir kişinin yapması en doğru olacaktır. Ürün yöneticisi ya da projeye hakim olan proje yöneticisi gibi birinin bu süreçte bulunuyor olması, “item”ların açıklanmasında faydalı olacaktır.Bunun amaçı tahminlemeden önce “item”ların tüm geliştiriciler açısından aynı şeyi ifade ediyor olmasıdır. “item”lar herkes için aynı şeyi ifade etmiyor ise ortaya çıkan tahminlerdeki tutarsızlıklar çok büyük olacaktır.”item”ların içeriğini netleştirmek için bu aşamada “item”ları alt maddeler(task) ile açıklıyor olmak faydalı olacaktır. Açıkcası “item”ların net olmasının, tahminlerin faydalı bir çıktı ortaya koymasında çok önemli olduğunu düşünüyorum.

“item”lar netleştikten sonra, herkes tahminin gizli olarak yapar. Bir kağıda yazmak, ya da bu iş için kullanılan kartları seçmek(-ki iskambil kartları ya da önceden hazırlanmış Fibonacci kartları faydalı olabilir)  koşulu ile tahminler yapılır. Tahminler yapılırken, kafa karışıklığına yol açmamak için bu işlemin gizli yapılması şarttır. Daha sonra aynı anda herkes tahminin gösterir.Tahminlerdeki zaman birimlerinden en büyüğünü ve en küçüğünü belirten kişiler, neden bu tahminlemeyi yaptıklarına dair kısa açıklamalarda bulunur. Bu sayede başkaları tarafından öngörülemeyen şeyler ortaya çıkar ve tahminleme tekrar aynı şekilde herkes arasında yapılır ve ortak bir karar ortaya çıkar.Bu süreç 2-3 adım olabilir. Ama zaten en fazla 3.adımdan sonra ortak bir şeyler ortaya çıkacaktır.

Bu şekilde tüm “item”lar tek tek tahminlenir. Ortaya çıkan sonuç sadece tahmin açısından değil, geliştirme sırasında yapılacak işlerin netleşmesi açısından da çok önemlidir. Poker planlaması, geliştiricilerin takım içerisinde kendilerini daha düzgün ifade etmesini ve en önemlisi takım içerisindeki iletişimin gelişmesini sağlar. Her takım elemanı, bireysel olarak kendi potansiyelinin farkına daha kolay varır.Neyse şimdilik bu kadar…Kendi tecrübelerim dahilinde bu konu hakkında doğru ya da yanlış bir şekilde bir şeyler paylaşmak istedim. Fikir ve düşüncelerinizi iletmekten çekinmeyin, ciddi anlamda önemli benim için…