Yazılım Mühendisliği: Süreç, Gereksinim, Tasarım ve Kalite

Yazılım Mühendisliği: Süreç, Gereksinim, Tasarım ve Kalite

Yazılım yaşam döngüsü, proje yönetimi, ölçüm, risk, kalite, test, bakım, gereksinim, tasarım, nesne yönelimli analiz ve mimari üzerine kapsamlı ders notları.

Yazılım mühendisliği notlarını süreç modelleri, proje yönetimi, kalite, test, bakım, gereksinim ve tasarım arasında bağ kurmak için tutmuştum. İlk sürümün klasik yöntemlerini korurken daha sonraki yıllarda DevOps, sürekli teslim ve güncellenen kalite standartlarına ilişkin notlar ekledim. Tarihsel yöntemlerle güncel uygulama biçimlerini aynı şeymiş gibi sunmamaya dikkat ettim.

Ünite 1: Yazılım Mühendisliğine Giriş

Yazılım ve yazılım mühendisliği

Yazılım yalnız kaynak koddan oluşmaz. Çalışan programın yanında gereksinim tanımları, mimari ve ayrıntılı tasarım, testler, yapılandırma bilgileri, kullanıcı ve işletim belgeleri, bakım bilgileri ve dağıtım için gerekli diğer varlıklar da yazılım ürününün parçasıdır.

Yazılım mühendisliği, yazılım sistemlerinin planlı, ölçülebilir, sınanabilir ve sürdürülebilir biçimde geliştirilmesini amaçlayan mühendislik disiplinidir. Temel hedef yalnız çalışan kod üretmek değildir. Beklenen işlevleri doğru gerçekleştiren, belirlenen kalite özelliklerini sağlayan, ekonomik olarak geliştirilebilen ve yaşam döngüsü boyunca yönetilebilen yazılım üretmektir.

Yazılım mühendisliği şu alanlarla doğrudan ilişkilidir:

  • bilgisayar bilimi,
  • sistem mühendisliği,
  • proje yönetimi,
  • kalite yönetimi,
  • ekonomi,
  • insan-bilgisayar etkileşimi,
  • güvenlik,
  • işletim ve bakım.

Bir yazılım projesinde teknik olarak doğru çözüm yeterli değildir. Çözümün süre, bütçe, kalite, güvenlik ve bakım kısıtları içinde gerçekleştirilebilmesi gerekir.

Program, yazılım ve donanım

Program, belirli bir işi gerçekleştirmek üzere yazılmış komutlar bütünüdür. Yazılım ise programdan daha geniş bir kavramdır. Kaynak kodun yanında yapılandırma, veri tanımları, testler, gereksinimler, tasarım belgeleri, kullanım ve işletim bilgileri gibi ürünün geliştirilmesi ve yaşatılması için gerekli varlıkları da kapsar.

Donanım fiziksel olarak üretilir ve zamanla aşınabilir. Yazılım fiziksel olarak aşınmaz. Buna karşılık değişiklikler, bağımlılıkların yaşlanması, hatalı bakım ve artan karmaşıklık nedeniyle yazılımın sürdürülebilirliği zamanla bozulabilir.

Yazılım kopyalamanın marjinal maliyeti düşük olabilir. Asıl maliyet gereksinimlerin anlaşılması, tasarım, geliştirme, doğrulama, dağıtım, işletim ve bakım gibi mühendislik faaliyetlerinde oluşur. Bu nedenle yazılım maliyetini yalnız kod satırı veya kurulum kopyası üzerinden değerlendirmek doğru değildir.

Yazılım mühendisi ve üretim ortamı

Yazılım mühendisi yalnız program yazan kişi değildir. Yazılım ürününün yaşam döngüsü boyunca teknik kararların, insan ilişkilerinin, kalite hedeflerinin ve proje kısıtlarının birlikte yönetilmesine katkı verir.

Bir yazılım üretim ortamında genellikle şu roller bulunabilir:

  • ürün veya iş alanı sorumluları,
  • gereksinim ve sistem analistleri,
  • yazılım mimarları,
  • geliştiriciler,
  • test ve kalite uzmanları,
  • veri tabanı ve altyapı uzmanları,
  • güvenlik uzmanları,
  • işletim ve destek ekipleri.

Küçük ekiplerde aynı kişi birden fazla rol üstlenebilir. Büyük sistemlerde ise sorumluluklar daha belirgin biçimde ayrılır. Önemli olan rol adları değil, karar ve sorumluluk sınırlarının açık olmasıdır.

Yazılım sistemlerinin sınıflandırılması

Yazılım sistemleri kullanım alanı ve çalışma biçimine göre farklı sınıflarda incelenebilir:

  • sistem yazılımları,
  • iş ve bilgi sistemleri,
  • gömülü ve gerçek zamanlı sistemler,
  • bilimsel ve mühendislik yazılımları,
  • web ve dağıtık uygulamalar,
  • mobil uygulamalar,
  • veri yoğun sistemler,
  • yapay zeka ve karar destek sistemleri.

Bir ürün birden fazla sınıfa aynı anda girebilir. Örneğin gerçek zamanlı çalışan bir gömülü sistem aynı zamanda ağ üzerinden dağıtık hizmetlerle haberleşebilir.

Yazılım krizinden günümüze

Yazılım mühendisliğinin bağımsız bir disiplin olarak ortaya çıkmasında 1960'ların sonlarında belirginleşen yazılım krizi önemli rol oynadı. Donanım hızla gelişirken büyük yazılım projeleri:

  • bütçeyi aşabiliyor,
  • planlanan zamanda tamamlanamıyor,
  • beklenen işlevleri eksik karşılıyor,
  • çok sayıda hata içeriyor,
  • bakım sırasında hızla karmaşıklaşıyordu.

Sorunun yalnız programlama dili veya donanım yetersizliği olmadığı anlaşıldı. Gereksinimlerin yönetilmesi, mimari tasarım, ekip organizasyonu, konfigürasyon yönetimi, test, kalite güvencesi ve bakımın da mühendislik disiplini içinde ele alınması gerekiyordu.

Bugün aynı problem farklı ölçekte devam eder. Modern sistemler dağıtık servisler, mobil istemciler, bulut ve uç altyapıları, güvenlik bileşenleri, yapay zeka modelleri, veri hatları ve üçüncü taraf bağımlılıkları içerebilir. Yazılım mühendisliğinin temel problemi yine aynıdır: karmaşıklığı denetim altında tutmak.

Yazılım sorunlarının temel kaynakları

Yazılım projelerindeki güçlükler genellikle tek bir nedene indirgenemez. Yaygın sorunlar şunlardır:

  • gereksinimlerin eksik veya sürekli değişmesi,
  • sistem sınırlarının yanlış belirlenmesi,
  • tasarım kararlarının belgelenmemesi,
  • mimari borcun büyümesi,
  • maliyet ve süre tahminlerinin gerçekçi olmaması,
  • testin geliştirme sürecinin sonuna bırakılması,
  • sürüm ve değişiklik yönetiminin zayıf olması,
  • ekip içi iletişim sorunları,
  • teknik borcun kontrolsüz büyümesi,
  • güvenlik ve işletilebilirliğin sonradan düşünülmesi.

Yazılım mühendisliği bu sorunların hiçbirini tamamen ortadan kaldırmaz. Ama sorunların erken görünür hale gelmesini, ölçülmesini ve yönetilebilir hale gelmesini sağlar.

Hataların yaşam döngüsünde yayılması

Yazılım geliştirme aşamaları birbirine girdi üretir. Gereksinim aşamasındaki bir yanlış tasarıma, kodlamaya, teste ve kullanıcı belgelerine kadar taşınabilir.

Basit zincir şöyledir:

Yanlış gereksinim
      ↓
Yanlış tasarım
      ↓
Yanlış gerçekleştirim
      ↓
Yanlış veya eksik test beklentisi
      ↓
Üretim hatası

Bu nedenle hatanın erken bulunması genellikle daha ucuzdur. Bununla birlikte belirli bir hata için sabit ve evrensel bir maliyet çarpanı yoktur. Etki; sistemin büyüklüğüne, kritikliğine, dağıtım biçimine ve değişikliğin yayıldığı bileşenlere göre değişir.

Bu düşünce modern geliştirmede gereksinim incelemeleri, erken prototipleme, sürekli entegrasyon, otomatik test ve kısa geri bildirim çevrimleriyle desteklenir.

Yazılım geliştirme yaşam döngüsü

Bir yazılım sistemi genel olarak şu etkinliklerden geçer:

  1. ihtiyaç ve kapsamın belirlenmesi,
  2. gereksinimlerin çıkarılması ve analizi,
  3. mimari ve ayrıntılı tasarım,
  4. gerçekleştirim,
  5. doğrulama ve test,
  6. dağıtım,
  7. işletim,
  8. bakım ve geliştirme,
  9. kullanım dışına çıkarma.

Bu sıra her projede doğrusal olmak zorunda değildir. Çevik ve artımlı modellerde aynı etkinlikler küçük çevrimler halinde tekrar edilir.

ISO/IEC/IEEE 12207:2026 yazılım yaşam döngüsünü edinim, tedarik, geliştirme, işletim, bakım ve kullanımdan kaldırmaya kadar uzanan ortak bir süreç çerçevesi içinde ele alır. Modern yaklaşımda yazılım geliştirme, kodlama aşamasından çok daha geniş bir yaşam döngüsüdür.

Yazılım geliştirme planı

Yazılım geliştirme planı projenin nasıl yürütüleceğini belirler.

Plan en az şu sorulara yanıt vermelidir:

  • Ne geliştirilecek?
  • Neden geliştirilecek?
  • Kim geliştirecek?
  • Hangi kaynaklar kullanılacak?
  • Hangi süreç izlenecek?
  • Ne kadar sürecek?
  • Ne kadar maliyet oluşturacak?
  • Başlıca riskler nelerdir?
  • Kalite nasıl ölçülecek?
  • Değişiklikler nasıl yönetilecek?
  • Ürün ne zaman kabul edilmiş sayılacak?

Plan bir kez hazırlanıp değişmeden kalan belge değildir. Yeni bilgi geldikçe tahminler ve riskler güncellenir.

Gereksinim analizi

Gereksinim analizi, sistemin ne yapması gerektiğini ve hangi kısıtlar altında çalışacağını belirler.

Gereksinimler yalnız işlevleri içermez. Şunlar da gereksinimdir:

  • performans,
  • güvenlik,
  • kullanılabilirlik,
  • erişilebilirlik,
  • güvenilirlik,
  • bakım yapılabilirlik,
  • mevzuat uyumu,
  • veri bütünlüğü,
  • platform ve arabirim kısıtları.

Gereksinim analizi tasarımdan önce "ne" sorusunu netleştirir. Tasarım ise "nasıl" sorusunu yanıtlar.

Tasarım

Tasarım, gereksinimleri gerçekleştirilebilir bir teknik yapıya dönüştürür.

İki düzeyde düşünülebilir:

Mimari tasarım: Sistemin büyük bileşenlerini, sorumluluklarını, veri ve kontrol ilişkilerini belirler.

Ayrıntılı tasarım: Bileşenlerin iç yapısını, sınıfları, veri yapılarını, algoritmaları ve arabirim ayrıntılarını belirler.

Tasarımın amacı yalnız diyagram üretmek değildir. Karmaşıklığı uygun sınırlara bölmek ve değişikliğin etkisini kontrol altında tutmaktır.

Yazılımın sınanması

Test, geliştirilen sistemin beklenen davranışı sağlayıp sağlamadığını araştırır.

Test yalnız sona bırakılan kabul işlemi değildir. Modern geliştirmede test:

  • birim düzeyinde,
  • bileşenler arasında,
  • sistem düzeyinde,
  • kabul düzeyinde,
  • performans ve güvenlik açısından

yaşam döngüsünün tamamına yayılır.

Test hatanın varlığını gösterebilir. Bütün olası hataların bulunmadığını kanıtlayamaz. Bu nedenle test, inceleme, statik analiz, tip sistemi, kod gözden geçirme ve çalışma zamanı gözlemlenebilirliği gibi başka kalite mekanizmalarıyla birlikte kullanılmalıdır.

Bakım ve geliştirme

Yazılımın teslim edilmesi yaşam döngüsünün sonu değildir.

Kullanım sırasında:

  • hatalar düzeltilir,
  • çalışma ortamına uyarlamalar yapılır,
  • yeni işlevler eklenir,
  • performans iyileştirilir,
  • güvenlik açıkları giderilir,
  • bağımlılıklar güncellenir,
  • teknik borç azaltılır.

Bakım maliyeti özellikle uzun ömürlü sistemlerde geliştirme maliyetinin önemli bölümünü oluşturabilir. Bu nedenle bakım yapılabilirlik, ilk tasarım aşamasından itibaren bir kalite hedefidir.

Süreç olgunluğu

Ders notlarında yazılım süreç olgunluğu beş seviyeli klasik Capability Maturity Model, CMM üzerinden ele alınır:

  1. Başlangıç,
  2. Tekrarlanabilir,
  3. Tanımlanmış,
  4. Yönetilebilir,
  5. Optimize edilmiş.

Bu model yazılım süreçlerinin kişisel çabadan kurumsal ve ölçülebilir süreçlere doğru olgunlaşmasını açıklamak için önemlidir.

Güncel karşılığı CMMI ailesidir. CMMI V3.0, yalnız yazılım geliştirmeyi değil geliştirme, hizmet, tedarikçi yönetimi, güvenlik, emniyet, veri, insan ve sanal çalışma gibi daha geniş kurumsal yetenek alanlarını bütünleşik biçimde ele alır.

Temel fikir değişmemiştir:

Süreç iyileştirme, tek tek kişilerin kahramanca çabasından tekrarlanabilir ve ölçülebilir kurumsal yeteneğe geçiştir.

Yazılım süreç modelleri

Bir süreç modeli, yaşam döngüsü etkinliklerinin hangi sırayla ve hangi geri besleme mekanizmalarıyla yürütüleceğini tanımlar.

Tek bir süreç modeli bütün projeler için en iyi değildir. Seçim şu özelliklere bağlıdır:

  • gereksinimlerin kararlılığı,
  • güvenlik ve emniyet kritiklik düzeyi,
  • teslim sıklığı,
  • ekip büyüklüğü,
  • mevzuat yükü,
  • müşteri geri bildirimi ihtiyacı,
  • teknik belirsizlik,
  • risk düzeyi.

Gelişigüzel ve tarihsel doğrusal modeller

Sistematik süreç kullanılmadan kişisel alışkanlıklara göre yapılan geliştirme, tarihsel olarak gelişigüzel model biçiminde açıklanmıştır. Küçük ve geçici programlarda çalışabilir görünse de izlenebilirlik, bakım, ekip çalışması ve tekrar üretilebilirlik açısından zayıftır.

Barok model, yaşam döngüsü aşamalarını doğrusal biçimde ele alan ve belgelemeye ayrı bir aşama gibi ağırlık veren tarihsel yaklaşımdır. Temel sınırlaması, geri dönüş ve değişiklik mekanizmalarını yeterince açık tanımlamamasıdır.

Bu modellerin güncel değeri doğrudan uygulanmalarından çok, yazılım mühendisliğinin neden süreç, izlenebilirlik ve sürekli belge üretimi gerektirdiğini göstermeleridir.

Şelale modeli

Şelale modelinde süreç ana aşamalar halinde ilerler:

Gereksinimler
    ↓
Tasarım
    ↓
Gerçekleştirim
    ↓
Test
    ↓
Dağıtım
    ↓
Bakım

Avantajı aşamaların ve çıktılarının açık olmasıdır.

Zayıf yönü, gereksinimlerin erken ve büyük ölçüde sabitlenmesini varsaymasıdır. Geç bulunan yanlış gereksinim pahalı geri dönüşlere neden olabilir.

Şelale yaklaşımı tamamen geçersiz değildir. Gereksinimleri kararlı, sözleşmeli ve güçlü dokümantasyon gerektiren bazı projelerde halen uygun olabilir.

V modeli

V modeli, doğrulama ve geçerleme faaliyetlerini geliştirme aşamalarıyla eşleştirir.

Kavramsal yapı:

Gereksinimler ---------------- Kabul testi
      \                       /
   Sistem tasarımı ------- Sistem testi
        \                 /
      Mimari ---------- Entegrasyon testi
          \             /
       Ayrıntılı tasarım
             \       /
              Kodlama

Sol taraf tanımlama ve tasarım, sağ taraf karşılık gelen test düzeylerini gösterir. Temel mesaj, test planlamasının kodlama bittikten sonra başlamaması gerektiğidir.

Gereksinimler kabul testinin, mimari tasarım sistem ve entegrasyon testlerinin, ayrıntılı tasarım ise birim testlerinin dayanağını oluşturur.

V modeli özellikle güçlü izlenebilirlik, doğrulama ve düzenleyici kanıt gerektiren projelerde öğretici bir çerçevedir.

Prototip destekli V yaklaşımı

Klasik notlarda VP süreç modeli, V modelinin üretim tarafına farklı düzeylerde prototipleme eklenmiş biçimi olarak ele alınır.

Amaç her aşamada belirsizliği azaltmaktır:

  • kullanıcı gereksinimi için arayüz prototipi,
  • mimari belirsizlik için teknik prototip,
  • gerçekleştirim riski için deneysel kod.

Prototipin hangi soruyu yanıtlamak için geliştirildiği baştan belirlenmelidir. Aksi halde geçici kodun fark edilmeden üretim sistemine dönüşmesi riski vardır.

Prototipleme

Prototipleme, gereksinim veya tasarım belirsizliğini azaltmak için sistemin sınırlı bir modelinin oluşturulmasıdır.

Prototip:

  • kullanıcı arabirimini sınamak,
  • teknik yapılabilirliği görmek,
  • gereksinimleri netleştirmek,
  • riskli teknik varsayımları denemek

için kullanılabilir.

Bir prototipin üretim sistemine dönüşeceği varsayılmamalıdır. Hızlı hazırlanan prototipte alınan kısa vadeli tasarım kararları doğrudan kalıcı sisteme taşınırsa teknik borç oluşabilir.

Dördüncü kuşak tekniklerinden kod üretimine

Ders notlarında 4GT, Fourth Generation Techniques yüksek düzeyli tanımlardan kod üretme yaklaşımı olarak ele alınır.

Bu fikir günümüzde farklı biçimlerde yaşamaktadır:

  • model güdümlü geliştirme,
  • kod üreticiler,
  • ORM ve şema üreticileri,
  • low-code platformları,
  • API tanımından istemci ve sunucu kodu üretimi,
  • Infrastructure as Code,
  • yapay zeka destekli kod üretimi.

Temel sınır aynıdır. Otomasyon kod yazma maliyetini azaltabilir, ancak doğru gereksinim, mimari ve doğrulama gereksinimini ortadan kaldırmaz.

Evrimsel ve araştırma tabanlı geliştirme

Evrimsel geliştirmede ilk çalışan sürüm belirli kapsamda tam işlev sunar. Sonraki sürümler yeni kullanıcı grupları, sahalar veya gereksinimlerle genişler.

Bu yaklaşım özellikle büyük ve çok birimli yapılarda pilot uygulama ile başlayıp edinilen deneyimin sonraki yayılımlara aktarılmasına uygundur. En önemli gereksinimlerden biri güçlü değişiklik ve konfigürasyon yönetimidir.

Araştırma tabanlı geliştirmede sonuç baştan kesin değildir. Bir deneyin çıktısı sonraki adımı belirler. Bu nedenle klasik sabit kapsam, sabit süre ve sabit maliyet varsayımları zayıflar.

Araştırma prototipi çoğu zaman kalıcı ürün değil, teknik bir soruya cevap veren deneysel varlıktır. Başarısız deney de bilgi üretebilir.

RAD

Rapid Application Development, RAD hızlı geri bildirim, prototipleme ve bileşenlerin yeniden kullanımını öne çıkarır.

RAD'in temel düşüncesi büyük bir ürünü uzun süre kapalı biçimde geliştirmek yerine kısa çevrimlerde çalışan parçalar üretmektir.

Bugünkü çevik geliştirme, sürekli teslim ve low-code yaklaşımında bu düşüncenin farklı izleri görülebilir.

Artımlı model

Artımlı modelde sistem parçalara ayrılır. Her artımda analiz, tasarım, gerçekleştirim ve test yapılır.

Artım 1 -> kullanılabilir ürün
Artım 2 -> daha geniş ürün
Artım 3 -> daha geniş ürün

Önemli avantajı erken çalışan ürün sağlamasıdır. Kullanıcı geri bildirimi sonraki artımlara yansıtılabilir.

Spiral model

Boehm'in spiral modeli iteratif geliştirmeyi risk analizi ile birleştirir.

Her çevrimde genel olarak:

  1. hedefler ve alternatifler belirlenir,
  2. riskler analiz edilir,
  3. çözüm geliştirilir ve doğrulanır,
  4. sonraki çevrim planlanır.

Spiral modelin ayırt edici özelliği yalnız iteratif olması değil, her iterasyonda riski karar mekanizmasının merkezine koymasıdır.

Çevik geliştirme

Modern yazılım mühendisliğinde çevik yöntemler kısa geri bildirim çevrimlerini, çalışan yazılımı, ekip içi işbirliğini ve değişime uyumu öne çıkarır.

Çeviklik plansızlık değildir. Planlama daha kısa ufuklarda ve daha sık yapılır.

Çevik geliştirmede de:

  • mimari kararlar,
  • kalite,
  • test,
  • güvenlik,
  • konfigürasyon yönetimi,
  • ölçüm

gereklidir.

DevOps ve sürekli teslim

Modern yazılım yaşam döngüsünde geliştirme ile işletim arasındaki sınır önemli ölçüde daralmıştır.

DevOps yaklaşımı:

  • sürüm kontrolü,
  • otomatik derleme,
  • sürekli bütünleme,
  • otomatik test,
  • sürekli teslim,
  • altyapının kodla yönetimi,
  • izleme ve gözlemlenebilirlik

gibi pratikleri ortak çalışma modeli altında bütünleştirir.

IEEE SWEBOK V4.0, Agile ve DevOps konularını yazılım mühendisliğinin genel bilgi alanlarına daha belirgin biçimde dahil eder.

CASE araçları

CASE, Computer-Aided Software Engineering, analiz, tasarım, kodlama, test ve dokümantasyon etkinliklerinin yazılım araçlarıyla desteklenmesini ifade eder.

Tarihsel CASE ortamlarında:

  • diyagram araçları,
  • veri sözlükleri,
  • kod üreticileri,
  • tasarım depoları

bir arada bulunurdu.

Bugün aynı amaç daha geniş bir araç zinciriyle karşılanır:

Issue Tracker
    ↓
Git
    ↓
IDE
    ↓
Build
    ↓
Static Analysis
    ↓
Automated Tests
    ↓
CI/CD
    ↓
Artifact Repository
    ↓
Deployment
    ↓
Monitoring

CASE kavramının kalıcı yönü, yazılım mühendisliği işlemlerinin araçlarla otomatikleştirilmesi ve ortak bilgi tabanı üzerinden izlenebilir hale getirilmesidir.

Ünite 2: Yazılım Proje Yönetimi

Proje yönetiminin amacı

Yazılım proje yönetimi teknik geliştirme faaliyetleriyle insan, süre, bütçe ve risk yönetimini birleştirir.

Başlıca sorular şunlardır:

  • kapsam nedir,
  • teslimatlar nelerdir,
  • kim hangi işten sorumludur,
  • süre ne kadardır,
  • maliyet ne olacaktır,
  • hangi riskler vardır,
  • ilerleme nasıl ölçülecektir.

Yazılım projesi yalnız görev listesinden oluşmaz. İşler arasında bağımlılıklar vardır ve belirsizlik yüksektir.

Etkin proje yönetimi

Etkin yönetim üç temel unsuru birlikte ele alır:

İnsan: Ekip yapısı, yetkinlik, iletişim ve sorumluluk.

Problem: Çözülecek sorunun kapsamı, karmaşıklığı ve sınırları.

Süreç: Geliştirmenin hangi yöntem ve denetim mekanizmalarıyla yürütüleceği.

Teknik olarak güçlü bir ekibin yanlış kapsamla çalışması başarısızlığa yol açabilir. İyi tanımlanmış bir projenin kötü iletişimle yürütülmesi de aynı sonucu üretebilir.

Proje kaynakları

Yazılım projesinin kaynakları yalnız geliştiricilerden oluşmaz.

Üç temel kaynak grubu düşünülebilir:

İnsan kaynakları: Analiz, mimari, geliştirme, test, güvenlik, işletim ve alan uzmanlığı.

Donanım kaynakları: Geliştirme makineleri, test ortamları, sunucular, ağ ve özel aygıtlar.

Yazılım kaynakları: İşletim sistemleri, veri tabanları, derleyiciler, geliştirme araçları, lisanslar, test ve izleme araçları.

Kaynak planlaması yalnız sayı belirlemek değildir. Kaynağın ne zaman gerekli olduğu da önemlidir. Test ortamına projenin son haftasında ihtiyaç duyulması ile baştan itibaren ihtiyaç duyulması aynı planlama problemi değildir.

Proje ekiplerinin oluşturulması

Projede iş sahibi ile yüklenici veya geliştiren ekip farklı kuruluşlar olabilir. Bu durumda teknik sorumluluk kadar karar ve kabul sorumluluğu da açık tanımlanmalıdır.

Bir ekip yapısında en az şu görevler görünür olmalıdır:

  • ürün ve kapsam kararı,
  • teknik mimari kararları,
  • geliştirme,
  • test ve kalite,
  • değişiklik onayı,
  • kabul,
  • işletim sorumluluğu.

İletişim maliyeti ekip büyüdükçe artar. Bu nedenle yalnız daha fazla kişi eklemek projenin daha kısa sürede tamamlanacağını garanti etmez.

Yazılım ölçümü

Ölçüm proje hakkında nesnel veri sağlar.

Ölçümler şu amaçlarla kullanılabilir:

  • tahmin,
  • kalite değerlendirmesi,
  • verimlilik analizi,
  • risk takibi,
  • süreç iyileştirme,
  • geçmiş projelerle karşılaştırma.

Ölçümün kendisi amaç değildir. Karar vermeyi desteklemeyen metrik gereksizdir.

Doğrudan ölçümler

Doğrudan ölçülebilen değerlere örnekler:

  • geliştirme süresi,
  • iş gücü,
  • maliyet,
  • kod satırı,
  • hata sayısı,
  • test sayısı,
  • bellek kullanımı,
  • gecikme,
  • işlem kapasitesi.

Klasik notlarda LOC ve KLOC önemli ölçülerdir.

Örneğin:

Verimlilik = KLOC / kişi-ay
Hata yoğunluğu = hata / KLOC

Ancak kod satırı sayısı dil, programlama stili ve kullanılan kütüphanelerden etkilenir. Çok kod üretmek tek başına yüksek verimlilik değildir.

Dolaylı ölçümler

Doğrudan sayılamayan özellikler başka ölçümler üzerinden değerlendirilir.

Örnekler:

  • karmaşıklık,
  • güvenilirlik,
  • bakım yapılabilirlik,
  • kalite,
  • işlevsel büyüklük.

Fonksiyon noktası

Function Point yaklaşımı yazılım büyüklüğünü kod satırından bağımsız olarak işlevsel özellikler üzerinden tahmin etmeye çalışır.

Klasik yaklaşımda:

  • dış girdiler,
  • dış çıktılar,
  • sorgular,
  • iç mantıksal dosyalar,
  • dış arabirim dosyaları

sayılır ve ağırlıklandırılır.

Eski ders yaklaşımında düzeltilmiş fonksiyon noktası şu biçimde ifade edilir:

FP = UFP x (0.65 + 0.01 x ΣFi)

Burada UFP düzeltilmemiş fonksiyon noktası, Fi ise genel sistem özelliklerinin etki değerleridir.

Fonksiyon noktalarının temel avantajı programlama dilinden bağımsız bir işlev büyüklüğü sağlamaya çalışmasıdır.

LOC ve FP karşılaştırması

LOC:

  • kolay sayılabilir,
  • gerçekleşmiş ürün üzerinde nettir,
  • dile ve kodlama yaklaşımına bağımlıdır,
  • erken tahminde zayıftır.

Fonksiyon noktası:

  • işlevsel büyüklüğe odaklanır,
  • daha erken tahmin edilebilir,
  • değerlendirme kurallarında yorum gerektirir,
  • algoritmik veya altyapı yoğun projelerde tek başına yeterli değildir.

Hiçbir metrik tek başına proje başarısını ölçmez.

Maliyet tahmini

Yazılım maliyeti tahmini belirsizlik içerir.

Tahmin şu etkenlerden etkilenir:

  • ürün büyüklüğü,
  • gereksinim belirsizliği,
  • ekip deneyimi,
  • teknoloji,
  • güvenlik ve kalite gereksinimleri,
  • entegrasyon sayısı,
  • yeniden kullanım,
  • zaman baskısı,
  • dağıtık ekip yapısı.

Tek bir sayı vermek yerine varsayımlar ve belirsizlik aralığı belirtilmelidir.

Maliyet kestirim metodolojisi

Kestirim tek bir formül çalıştırmak yerine düzenli bir süreç olarak ele alınmalıdır:

  1. kapsamı ve varsayımları tanımla,
  2. ürünü veya işleri bölümlere ayır,
  3. büyüklüğü tahmin et,
  4. geçmiş proje verilerini kullan,
  5. ekip ve teknoloji etkilerini değerlendir,
  6. risk payını belirle,
  7. sonucu bağımsız yöntemlerle karşılaştır,
  8. proje ilerledikçe tahmini güncelle.

Function Point, COCOMO, uzman görüşü ve analitik iş kırılımı birbirinin rakibi olmak zorunda değildir. Farklı yöntemlerden elde edilen sonuçlar çapraz kontrol amacıyla birlikte kullanılabilir.

Uzman görüşü

Deneyimli kişilerin benzer projelerden edindikleri bilgiyle tahmin yapması basit ve sık kullanılan yöntemdir.

Avantajı hızdır.

Zayıf yönü kişisel önyargı ve deneyime bağımlılıktır.

Delphi yöntemi

Delphi yönteminde birden fazla uzman birbirinden bağımsız tahmin yapar. Sonuçlar karşılaştırılır ve gerekçeler paylaşıldıktan sonra yeni turlar yapılır.

Amaç tek baskın görüşün diğer katılımcıları etkilemesini azaltmak ve ortak tahmine yaklaşmaktır.

Analitik tahmin

Proje alt işlere bölünür. Her iş için süre ve efor tahmini yapılır.

Toplam efor ≈ alt işlerin eforlarının toplamı

Bu yaklaşım Work Breakdown Structure düşüncesiyle uyumludur.

En büyük risk, görünmeyen entegrasyon ve koordinasyon işlerinin unutulmasıdır.

COCOMO

COCOMO, Constructive Cost Model, Barry Boehm tarafından yazılım eforunu kod büyüklüğüne göre tahmin etmek için geliştirilmiştir.

Klasik temel biçim:

Efor = a x KLOC^b
Süre = c x Efor^d

Klasik COCOMO üç proje sınıfı tanımlar:

| Proje tipi | a | b | c | d | | --- | ---: | ---: | ---: | ---: | | Organic | 2.4 | 1.05 | 2.5 | 0.38 | | Semi-detached | 3.0 | 1.12 | 2.5 | 0.35 | | Embedded | 3.6 | 1.20 | 2.5 | 0.32 |

Model tarihsel olarak önemlidir. Modern projelerde doğrudan eski katsayıların kullanılması doğru değildir. COCOMO II daha yeni geliştirme modellerini, yeniden kullanımı ve farklı maliyet sürücülerini ele alan devam modelidir.

COCOMO'nun sınav açısından önemli fikri şudur:

Yazılım büyüklüğü arttıkça efor doğrusal olmak zorunda değildir.

Putnam-Norden-Rayleigh modeli

PNR yaklaşımı proje personel ihtiyacının zamana göre değişimini Rayleigh eğrisiyle ilişkilendirir.

Klasik yaklaşımda yazılım büyüklüğü, teknoloji katsayısı, toplam efor ve teslim süresi arasında güçlü ilişki vardır.

Önemli sonuç şudur:

Takvimi keyfi biçimde kısaltmak için yalnız daha fazla personel eklemek maliyeti orantılı biçimde çözmez.

Bu düşünce büyük yazılım projelerindeki iletişim ve koordinasyon maliyetleriyle birlikte değerlendirilmelidir.

Risk yönetimi

Risk, gerçekleşmesi kesin olmayan ancak gerçekleşirse projeyi etkileyen olay veya koşuldur.

Risk yönetiminin temel çevrimi:

Riskleri belirle
    ↓
Olasılık ve etkiyi değerlendir
    ↓
Önceliklendir
    ↓
Yanıt planla
    ↓
İzle
    ↓
Yeniden değerlendir

Risk kategorileri

Ders notlarında riskler şu başlıklarda ele alınır:

  • ürün büyüklüğü,
  • işletme,
  • müşteri,
  • süreç,
  • teknoloji,
  • geliştirme ortamı,
  • personel.

Bu sınıflandırma bugün de kullanılabilir.

Ürün büyüklüğü riskleri

Risk göstergeleri:

  • büyüklüğün tahmin edilenden fazla olması,
  • veri hacminin hızlı büyümesi,
  • bileşen sayısının artması,
  • çok fazla entegrasyon noktası.

İşletme riskleri

Örnekler:

  • bütçe değişikliği,
  • kurumsal öncelik değişimi,
  • mevzuat,
  • tedarikçi bağımlılığı,
  • ürünün ekonomik değerini kaybetmesi.

Müşteri riskleri

  • gereksinim kararlarının gecikmesi,
  • paydaşların çelişkili beklentileri,
  • kabul kriterlerinin belirsizliği,
  • erişilemeyen alan uzmanları.

Süreç riskleri

  • süreçlerin tanımlı olmaması,
  • kalite kontrolünün zayıflığı,
  • test otomasyonunun olmaması,
  • değişikliklerin izlenememesi.

Teknoloji riskleri

  • olgunlaşmamış teknoloji,
  • bilinmeyen performans sınırları,
  • üçüncü taraf bağımlılığı,
  • donanım veya platform uyumsuzluğu,
  • güvenlik açıkları.

Geliştirme ortamı riskleri

  • araç zinciri kararsızlığı,
  • derleme altyapısının güvenilmezliği,
  • test ortamlarının üretimi temsil etmemesi,
  • yetersiz CI/CD altyapısı.

Personel riskleri

  • kritik bilginin tek kişide toplanması,
  • ekip değişimi,
  • yetkinlik eksikliği,
  • iletişim kopukluğu,
  • görev yükünün dengesizliği.

Risk yanıtları

Bir risk için dört temel yaklaşım düşünülebilir:

  • önleme,
  • azaltma,
  • aktarma,
  • kabul.

Risk kaydı en az:

  • açıklama,
  • olasılık,
  • etki,
  • sorumlu,
  • azaltma eylemi,
  • tetikleyici,
  • durum

bilgilerini içermelidir.

Yazılım proje planı

Proje planı kapsam, kaynak, organizasyon, zaman ve risk bilgisini bir araya getirir.

Başlıca bölümler:

  1. sorunun tanımı,
  2. gereksinimler,
  3. çözüm yaklaşımı,
  4. geliştirme süreci,
  5. ekip ve organizasyon,
  6. iş kırılımı,
  7. zamanlama,
  8. maliyet,
  9. risk,
  10. kalite ve test,
  11. konfigürasyon yönetimi.

Proje organizasyonu

Klasik üç yapı:

Fonksiyonel organizasyon: Çalışanlar uzmanlık birimlerinde gruplanır.

Proje organizasyonu: Ekip doğrudan proje için oluşturulur.

Matris organizasyon: Fonksiyonel ve proje yapıları birlikte kullanılır.

Matris yapıda bir kişinin hem teknik birim yöneticisine hem proje yöneticisine karşı sorumluluğu olabilir.

Ekip yapıları

Klasik ders yaklaşımında ekipler demokratik, şef kontrollü veya hiyerarşik yapılarda incelenir.

Modern ekiplerde yapı daha esnektir. Ancak temel problem aynıdır:

  • karar yetkisi,
  • iletişim yolu,
  • teknik liderlik,
  • sorumlulukların dağılımı

açık olmalıdır.

Proje zamanlaması

Zamanlama için işler:

  1. belirlenir,
  2. süreleri tahmin edilir,
  3. bağımlılıkları çıkarılır,
  4. kaynaklara atanır,
  5. kritik yol belirlenir.

Gantt çizelgesi

Gantt çizelgesi işleri zamana göre gösterir.

Avantajı takvimi okunabilir kılmasıdır.

Tek başına karmaşık bağımlılıkları açıklamakta yetersiz kalabilir.

PERT ve CPM

PERT ve CPM işlerin bağımlılıklarını ağ biçiminde gösterir.

Critical Path Method, toplam proje süresini belirleyen kritik yolu bulmaya odaklanır.

Kritik yoldaki bir iş gecikirse başka telafi yoksa proje de gecikir.

PERT belirsiz süre tahminlerinde klasik olarak üç tahmin kullanabilir:

iyimser
en olası
kötümser

Ünite 3: Yazılım Kalite Yönetimi ve Test

Yazılım kalitesi

Kalite yalnız "az hata" anlamına gelmez.

Kaliteli yazılım:

  • gereksinimleri karşılar,
  • beklenen koşullarda güvenilir çalışır,
  • performans hedeflerine uyar,
  • güvenli davranır,
  • kullanıcı için anlaşılabilir ve kullanılabilir olur,
  • bakım ve değişikliğe elverişli olur.

ISO/IEC 25010:2023 ürün kalitesini dokuz ana özellik altında ele alan güncel kalite modelidir. Bu model işlevsel uygunluk, performans verimliliği, uyumluluk, etkileşim yeteneği, güvenilirlik, güvenlik, bakım yapılabilirlik, esneklik ve emniyet gibi kalite boyutlarını sistematik biçimde değerlendirmek için kullanılabilir.

Kalite ölçütleri

Bir kalite özelliği doğrudan ölçülemiyorsa onu temsil eden göstergeler kullanılır.

Örnekler:

  • hata yoğunluğu,
  • başarısızlık oranı,
  • test kapsaması,
  • çevrimsel karmaşıklık,
  • değişiklik başına etkilenen dosya sayısı,
  • ortalama onarım süresi,
  • yanıt süresi,
  • güvenlik açığı sayısı.

Metrik ile gerçek kalite özelliği aynı şey değildir. Metrik yalnız gösterge olabilir.

Halstead ölçütleri

Halstead ölçütleri kaynak kodun işleç ve işlenen sayılarına dayanır.

Tanımlar:

n1 = farklı işleç sayısı
n2 = farklı işlenen sayısı
N1 = toplam işleç kullanımı
N2 = toplam işlenen kullanımı

Program sözlüğü:

n = n1 + n2

Gerçek program uzunluğu:

N = N1 + N2

Tahmini uzunluk:

N^ = n1 log2(n1) + n2 log2(n2)

Hacim:

V = N log2(n)

Zorluk:

D = (n1 / 2) x (N2 / n2)

Efor:

E = D x V

Halstead ölçütleri program metninin belirli nicel özelliklerini verir. Doğrudan yazılım kalitesinin kesin ölçüsü olarak görülmemelidir.

McCabe çevrimsel karmaşıklığı

McCabe ölçütü kontrol akış grafındaki bağımsız yürütme yollarının sayısıyla ilişkilidir.

Tek bağlı bir kontrol akış grafında:

V(G) = E - N + 2

Burada:

  • E: kenar sayısı,
  • N: düğüm sayısıdır.

Birden fazla bağlı bileşen için genel ifade:

V(G) = E - N + 2P

olarak yazılabilir.

Basit programlarda çevrimsel karmaşıklık yaklaşık olarak:

karar noktası sayısı + 1

şeklinde de düşünülebilir.

Karmaşıklık arttıkça sınanması gereken bağımsız yollar artar. Bu nedenle metrik test tasarımı ve bakım riski açısından yararlıdır.

Belirli bir eşik bütün projeler için evrensel kalite sınırı değildir. Değer, modülün bağlamıyla birlikte değerlendirilmelidir.

Kalite güvencesi

Quality Assurance, QA, kalitenin süreç boyunca sistematik biçimde güvence altına alınmasıdır.

Kalite güvencesi:

  • süreç tanımları,
  • standartlar,
  • gözden geçirmeler,
  • test stratejisi,
  • ölçümler,
  • konfigürasyon yönetimi,
  • denetimler

gibi etkinlikleri kapsar.

Kalite kontrolü

Kalite kontrolü belirli ürün ve çıktıları değerlendirir.

Örneğin:

  • gereksinim incelemesi,
  • tasarım incelemesi,
  • kod incelemesi,
  • test sonucu analizi,
  • kabul kontrolü.

Kalite güvence daha geniş süreç yaklaşımıdır. Kalite kontrol ise ürün ve çıktı üzerinde doğrulama yapar.

Teknik gözden geçirme

Gözden geçirme, hatayı çalıştırma aşamasından önce bulmayı amaçlar.

İyi bir teknik inceleme:

  • belirli kapsamla yapılır,
  • kontrol listesi kullanabilir,
  • bulguları kaydeder,
  • kişiyi değil ürünü değerlendirir,
  • düzeltmenin takibini yapar.

Statik inceleme erken hata bulmanın en düşük maliyetli yollarından biri olabilir.

Yazılım testinin amacı

Testin temel soruları:

  • Sistem doğru ürünü mü gerçekleştiriyor?
  • Ürün doğru biçimde mi gerçekleştirildi?
  • Tanımlanan koşullarda hatalı davranış var mı?
  • Kalite hedefleri sağlanıyor mu?

Verification daha çok ürünün tanıma ve tasarıma uygunluğunu, validation ise geliştirilen ürünün gerçek kullanıcı ihtiyacını karşılayıp karşılamadığını sorgular.

Test düzeyleri

Modern test sınıflandırması genel olarak:

  • birim testi,
  • entegrasyon testi,
  • sistem testi,
  • kabul testi

düzeylerini içerir.

Bunlara performans, güvenlik, kullanılabilirlik, dayanıklılık ve geri dönüş gibi kalite testleri eklenebilir.

ISO/IEC/IEEE 29119 serisi yazılım testi için ortak kavramlar, test süreçleri, test dokümantasyonu ve test teknikleri çerçevesi sunar.

Birim testi

Birim testi en küçük mantıksal yazılım birimini sınar.

İyi bir birim testi:

  • hızlı,
  • tekrarlanabilir,
  • bağımsız,
  • deterministik

olmalıdır.

Bağımlılıklar gerektiğinde test double, fake veya mock ile ayrıştırılabilir.

Test sürücüsü ve test desteği

Klasik yapısal testte henüz bulunmayan üst veya alt modüllerin yerine geçici programlar kullanılabilir.

Driver, test edilen modülü çağıran geçici üst bileşendir.

Stub, test edilen modülün çağırdığı fakat henüz bulunmayan alt bileşenin yerine geçer.

Bu kavramlar modern mock ve test double yaklaşımlarının tarihsel temelidir.

Bütünleme testi

Entegrasyon testi bileşenlerin kendi başlarına değil birlikte doğru çalışıp çalışmadığını araştırır.

Başlıca riskler:

  • veri biçimi uyuşmazlığı,
  • protokol hatası,
  • transaction sınırı,
  • zaman aşımı,
  • hata yayılımı,
  • sürüm uyumsuzluğu.

Yukarıdan aşağı bütünleme

Üst seviye modüllerden başlanır. Alt bileşenler başlangıçta stub ile temsil edilir.

Avantajı üst seviye kontrol akışının erken görülmesidir.

Aşağıdan yukarı bütünleme

Alt düzey bileşenlerden başlanır. Üst çağırıcılar için driver kullanılabilir.

Avantajı temel hizmetlerin erken doğrulanmasıdır.

Sistem testi

Sistem testi ürünün bütününü gerçek veya gerçeğe yakın ortamda değerlendirir.

Fonksiyonların yanında:

  • performans,
  • kapasite,
  • güvenlik,
  • kurtarma,
  • kurulum,
  • uyumluluk

gibi özellikler de sınanabilir.

Kabul testi

Kabul testi sistemin kullanıcı veya sözleşme gereksinimlerini karşılayıp karşılamadığını değerlendirir.

Kabul kriterleri gereksinim aşamasında belirlenmelidir.

Hata ayıklama

Test hata olduğunu gösterir. Debugging, hatanın kaynağını bulup düzeltme işlemidir.

Genel çevrim:

Hata gözlenir
    ↓
Tekrarlanabilir hale getirilir
    ↓
Kök neden bulunur
    ↓
Düzeltme yapılır
    ↓
Test tekrar çalıştırılır
    ↓
Regresyon denetlenir

Beyaz kutu testi

Beyaz kutu testi programın iç yapısını dikkate alır.

Amaç:

  • karar yollarını,
  • koşulları,
  • döngüleri,
  • veri akışını

sınamaktır.

Temel yol testi

McCabe çevrimsel karmaşıklığı bağımsız yol sayısının belirlenmesinde kullanılabilir.

Temel yol testi:

  1. kontrol akış grafını oluşturur,
  2. karmaşıklığı hesaplar,
  3. bağımsız yolları belirler,
  4. bu yolları çalıştıracak testleri tasarlar.

Döngü testi

Döngüler için tipik sınırlar:

  • sıfır tekrar,
  • bir tekrar,
  • normal tekrar,
  • üst sınırın hemen altı,
  • üst sınır,
  • üst sınırın üzeri

gibi durumlarla sınanır.

Kara kutu testi

Kara kutu testinde programın iç yapısından çok giriş ve beklenen çıktı ilişkisi değerlendirilir.

Eşdeğer bölümlere ayırma

Girdi uzayı benzer davranması beklenen sınıflara ayrılır.

Örneğin geçerli yaş aralığı:

0..17
18..65
66+

Her sınıftan temsilci değer seçilebilir.

Sınır değer analizi

Hatalar sınıf sınırlarında sık görülür.

Bir aralık:

1 <= x <= 100

ise güçlü test adayları:

0, 1, 2, 99, 100, 101

değerleridir.

Neden-sonuç grafı ve karar tabloları

Birden fazla mantıksal koşulun birleşimi çok sayıda durum oluşturuyorsa karar tablosu veya neden-sonuç grafı kullanılabilir.

Bu teknik özellikle iş kurallarının kombinasyonlarını sistematik test etmeye yarar.

Test planlama ve test belirtimleri

Test planı hangi kalitenin hangi düzeyde ve hangi kaynaklarla doğrulanacağını belirler.

Temel içerik:

  • kapsam,
  • test düzeyleri,
  • test ortamları,
  • giriş ve çıkış kriterleri,
  • sorumlular,
  • veri hazırlığı,
  • bağımlılıklar,
  • hata raporlama yöntemi,
  • takvim,
  • kabul ölçütleri.

Test belirtimi ise belirli test koşullarını ve beklenen sonuçları daha ayrıntılı tanımlar.

Gereksinimden teste izlenebilirlik kurulursa bir gereksinimin doğrulanıp doğrulanmadığı açık biçimde görülebilir.

Yaşam döngüsü boyunca doğrulama ve geçerleme

Doğrulama ve geçerleme yalnız test ekibinin son aşamadaki işi değildir.

Örnek eşleştirme:

Gereksinim -> gereksinim incelemesi + kabul testi tasarımı
Mimari     -> mimari inceleme + sistem/entegrasyon test tasarımı
Kod        -> statik analiz + birim testi
Paket      -> entegrasyon + sistem testi
Ürün       -> kabul ve işletim doğrulaması

Bu yaklaşım V modelinin temel mantığıyla uyumludur.

Regresyon testi

Bir değişiklik sonrası daha önce çalışan davranışların bozulmadığını doğrulayan testlere regresyon testi denir.

Otomasyonun en yüksek değer sağladığı alanlardan biridir.

Sürekli test

CI/CD sistemlerinde testler kod değişikliğiyle birlikte otomatik çalıştırılabilir.

Tipik hat:

Commit
  ↓
Build
  ↓
Static Analysis
  ↓
Unit Tests
  ↓
Integration Tests
  ↓
Package
  ↓
Deployment Tests

Bu yapı hatanın değişiklikten kısa süre sonra görünür hale gelmesini sağlar.

Ünite 4: Yazılım Bakımı ve Konfigürasyon Yönetimi

Yazılım bakımı

Yazılım fiziksel olarak aşınmaz. Ancak çevresi ve gereksinimleri değişir.

Bakım dört temel sınıfta ele alınabilir:

Düzeltici bakım: Hataları giderir.

Uyarlayıcı bakım: İşletim sistemi, donanım, API, mevzuat veya dış ortam değişikliklerine uyum sağlar.

İyileştirici bakım: Performans, kullanılabilirlik veya işlevlerde geliştirme yapar.

Önleyici bakım: Gelecekteki hata ve bakım maliyetini azaltmak için iç yapıyı iyileştirir.

Kurulum ve yerinde destek

Kurulum, yalnız yazılım dosyalarını hedef ortama kopyalamak değildir.

Kurulum planı şu konuları kapsayabilir:

  • sürüm ve bağımlılıklar,
  • veri dönüşümü,
  • erişim yetkileri,
  • yedekleme,
  • geri dönüş planı,
  • kullanıcı eğitimi,
  • doğrulama testleri,
  • izleme ve destek sorumluluğu.

Üretime geçiş sonrası ilk dönem, geliştirme ekibi ile işletim ekibi arasında yoğun bilgi aktarımı gerektirebilir.

Bakım süreç modeli

Bir bakım talebi küçük bir kod değişikliğinden ibaret görülmemelidir. Gerektiğinde yaşam döngüsünün ilgili adımları yeniden çalıştırılır:

Sorun / değişiklik talebi
        ↓
Çözümleme
        ↓
Tasarım
        ↓
Gerçekleştirim
        ↓
Sistem ve regresyon testi
        ↓
Kabul
        ↓
Kurulum

Değişiklik büyüdükçe etki analizi ve konfigürasyon yönetiminin önemi artar.

Bakım yapılabilirlik

Bakım yapılabilirlik bir sistemin ne kadar kolay anlaşılabildiği, değiştirilebildiği ve doğrulanabildiğiyle ilgilidir.

Bakımı kolaylaştıran özellikler:

  • düşük bağımlılık,
  • yüksek iç tutarlılık,
  • açık arabirimler,
  • modüler tasarım,
  • otomatik test,
  • anlaşılır kod,
  • güncel dokümantasyon,
  • izlenebilir gereksinimler,
  • gözlemlenebilir çalışma zamanı davranışı.

Bakım maliyetinin azaltılması

Bakım maliyetini yalnız bakım döneminde azaltmak mümkün değildir.

Geliştirme sırasında:

  • temiz mimari sınırlar,
  • otomatik test,
  • kod inceleme,
  • teknik borç yönetimi,
  • sürüm kontrolü,
  • tekrarlanabilir derleme,
  • iyi loglama

bakım maliyetini doğrudan etkiler.

Yazılım konfigürasyonu

Bir yazılım ürünü çok sayıda yapılandırma öğesinden oluşur.

Örnekler:

  • kaynak kod,
  • gereksinim belgeleri,
  • tasarım belgeleri,
  • testler,
  • derleme betikleri,
  • bağımlılık tanımları,
  • veritabanı şemaları,
  • dağıtım manifestoları,
  • kullanıcı belgeleri.

Belirli bir sürümü tekrar üretebilmek için bu öğelerin hangi versiyonlarının birlikte kullanıldığı bilinmelidir.

Yazılım konfigürasyon yönetimi

Software Configuration Management, SCM, yazılım ürünündeki değişikliklerin tanımlanması, izlenmesi, denetlenmesi ve doğrulanmasıdır.

Temel etkinlikler:

  1. konfigürasyon öğelerini belirleme,
  2. baseline oluşturma,
  3. sürüm kontrolü,
  4. değişiklik kontrolü,
  5. durum muhasebesi,
  6. konfigürasyon denetimi.

Baseline

Baseline, belirli bir anda kabul edilmiş ve değişiklikleri denetim altına alınmış konfigürasyon durumudur.

Örneğin:

  • onaylı gereksinim seti,
  • test edilen sürüm,
  • üretime çıkan release

baseline olarak ele alınabilir.

Değişiklik kontrolü

Değişiklik şu çevrimle yönetilebilir:

Değişiklik isteği
    ↓
Etki analizi
    ↓
Onay / ret
    ↓
Gerçekleştirim
    ↓
Test
    ↓
Sürümleme
    ↓
Kayıt

Etki analizi yapılmadan küçük görünen bir değişiklik farklı modülleri ve belgeleri bozabilir.

Konfigürasyon denetimi

Denetim şu soruları yanıtlar:

  • Doğru dosyalar mı kullanıldı?
  • İstenen değişiklikler gerçekten yapıldı mı?
  • Test edilen sürüm ile dağıtılan sürüm aynı mı?
  • Belgeler ve kod aynı baseline'a mı ait?
  • Onaysız değişiklik var mı?

Durum raporlama

Konfigürasyon durumu:

  • hangi sürümlerin bulunduğunu,
  • hangi değişikliklerin uygulandığını,
  • hangi taleplerin açık olduğunu,
  • hangi baseline'ın üretimde olduğunu

gösterebilmelidir.

Sürüm kontrolü

Modern konfigürasyon yönetiminin merkezi araçlarından biri dağıtık sürüm kontrol sistemleridir.

Git gibi sistemler:

  • commit geçmişi,
  • branch,
  • merge,
  • tag,
  • değişiklik karşılaştırma,
  • geri dönüş

işlevleri sunar.

Ancak konfigürasyon yönetimi Git'ten daha geniştir. Derleme araçları, bağımlılıklar, artefakt depoları, ortam ayarları ve dağıtım manifestoları da yönetilmelidir.

Modern konfigürasyon zinciri

Kaynak kod
   ↓
Sürüm kontrolü
   ↓
CI derlemesi
   ↓
Testler
   ↓
Sürüm numarası
   ↓
İmzalı / tanımlı artefakt
   ↓
Artefakt deposu
   ↓
Dağıtım

Temel hedef:

Aynı kaynak ve konfigürasyondan aynı ürünün yeniden üretilebilmesi.

Ünite 5: Yazılım Gereksinim Analizi

Yazılım gereksinimleri

Gereksinim, sistemin sağlaması gereken yetenek, özellik veya kısıttır.

Gereksinimler genel olarak:

  • iş gereksinimleri,
  • kullanıcı gereksinimleri,
  • sistem gereksinimleri,
  • yazılım gereksinimleri

düzeylerinde ele alınabilir.

İşlevsel gereksinimler

Sistemin yapacağı işi tanımlar.

Örneğin:

Sistem, yetkili kullanıcının bir siparişi iptal edebilmesini sağlamalıdır.

İşlevsel olmayan gereksinimler

Sistemin çalışma niteliğini veya kısıtlarını tanımlar.

Örnekler:

  • sorgu 200 ms altında yanıt vermeli,
  • veri aktarımı şifreli olmalı,
  • sistem belirli yük altında çalışmalı,
  • hizmet belirli erişilebilirlik hedefini sağlamalı.

İşlevsel olmayan gereksinimler ölçülebilir yazılmadığında test edilmesi güçleşir.

Gereksinim spesifikasyonu

Software Requirements Specification, SRS, gereksinimleri düzenli ve doğrulanabilir biçimde tanımlar.

İyi gereksinim:

  • açık,
  • tek anlamlı,
  • gerekli,
  • tutarlı,
  • gerçekleştirilebilir,
  • doğrulanabilir,
  • izlenebilir

olmalıdır.

ISO/IEC/IEEE 29148:2018 gereksinim mühendisliği süreçleri ve gereksinim bilgi öğeleri için güncel temel standartlardan biridir.

Gereksinim ile tasarım ayrımı

Gereksinim:

Sistem ne yapmalı?

Tasarım:

Sistem bunu nasıl yapacak?

Gereksiz tasarım kararlarını gereksinim içine gömmek çözüm alanını daraltabilir.

Bazı durumlarda teknoloji seçimi gerçek bir kısıt olduğundan gereksinim olabilir. Ayrım bağlama göre yapılmalıdır.

İzlenebilirlik

Her önemli gereksinim:

  • kaynağına,
  • tasarım kararına,
  • gerçekleştirim bileşenine,
  • test durumuna

bağlanabilmelidir.

İş ihtiyacı
   ↓
Gereksinim
   ↓
Tasarım
   ↓
Kod
   ↓
Test

İzlenebilirlik özellikle güvenlik kritik, emniyet kritik ve düzenlemeye tabi sistemlerde önemlidir.

Mevcut sistemin incelenmesi

Yeni sistem geliştirilecekse mevcut işleyişin anlaşılması gereksinim analizinin önemli parçasıdır.

İnceleme sırasında:

  • iş adımları,
  • kullanılan belgeler ve kayıtlar,
  • girdi ve çıktılar,
  • iş kuralları,
  • mevzuat ve yönergeler,
  • mevcut sorunlar,
  • kullanıcıların fiili çalışma biçimleri

araştırılır.

Mevcut sistemin yaptığı her şey yeni sisteme aynen aktarılmak zorunda değildir. Ama mevcut davranış bilinmeden kaldırılan bir işlevin gerçek gereksinim olup olmadığı anlaşılamaz.

Gereksinim çıkarma teknikleri

Gereksinim verisi farklı yöntemlerle toplanabilir.

Görüşme: Alan uzmanıyla doğrudan ve derin bilgi alışverişi sağlar.

Anket: Çok sayıda kullanıcıdan standart biçimde veri toplamayı kolaylaştırır.

Gözlem: Kullanıcının söylediği süreç ile gerçekte uyguladığı süreç arasındaki farkı gösterebilir.

Belge inceleme: Formlar, raporlar, yönergeler, kayıtlar ve mevzuat üzerinden mevcut sistemi açıklar.

Örnekleme ve istatistiksel inceleme: Büyük veri veya belge kümelerinde temsil edici örneklerle çalışma maliyetini azaltır.

Atölye çalışması: Birden fazla paydaşın çelişkili gereksinimlerini aynı ortamda görünür hale getirir.

Belirsiz ve zayıf yapılandırılmış problemlerde senaryo, prototip ve kavramsal model kullanmak soyut beklentileri somutlaştırabilir.

Veri modelleme

Gereksinim analizinde veri modeli sistemin hangi bilgileri tuttuğunu ve bu bilgilerin nasıl ilişkilendiğini gösterir.

Klasik araçlar:

  • varlık-ilişki modeli,
  • veri sözlüğü.

ER modeli yüksek düzeyde varlık ve ilişkileri gösterir. Veri sözlüğü alanların anlamını, tipini, uzunluğunu, geçerli değerlerini ve kullanım yerlerini ayrıntılandırır.

Güncel projelerde aynı ihtiyaç ilişkisel şema modelleri, domain modelleri, JSON Schema, Protobuf veya API sözleşmeleri gibi farklı tekniklerle karşılanabilir.

Kullanıcı arayüzü prototipleme

Arayüz prototipi gereksinimlerin erken doğrulanmasına yardımcı olur.

Prototip üzerinden kullanıcı:

  • hangi bilgiyi göreceğini,
  • hangi veriyi gireceğini,
  • işlem sırasını,
  • hata ve onay davranışını

daha somut biçimde değerlendirebilir.

Prototip görsel tasarım yarışması değildir. Ana amacı belirsiz gereksinimleri erken ortaya çıkarmaktır.

Analiz modelinin değerlendirilmesi

Analiz çıktıları en az şu açılardan gözden geçirilmelidir:

  • tamlık,
  • tutarlılık,
  • olurluluk,
  • izlenebilirlik,
  • model düzeyleri arasında denge.

DFD ayrıştırmasında üst düzey süreç ile alt düzey diyagramın dış veri akışları uyumlu olmalıdır. Bu özellik klasik terminolojide balancing olarak bilinir.

Formal spesifikasyon

Formal spesifikasyon matematiksel veya kesin tanımlı notasyonlarla sistem davranışını ifade eder.

Avantajları:

  • belirsizliği azaltır,
  • tutarsızlıkların bulunmasını kolaylaştırır,
  • bazı özelliklerin ispatlanmasına izin verir.

Dezavantajı:

  • uzmanlık gerektirir,
  • maliyetlidir,
  • bütün sistemler için aynı ölçüde gerekli değildir.

Formal yöntemler özellikle kritik protokoller, güvenlik mekanizmaları ve doğruluğun yüksek önem taşıdığı bileşenlerde değerlidir.

İlişkisel notasyonlar

Sistemin girdileriyle çıktıları arasındaki ilişkileri matematiksel biçimde tanımlar.

Önkoşul ve sonkoşul yaklaşımı buna örnektir.

Precondition
    ↓
Operation
    ↓
Postcondition

Durum yönelimli notasyonlar

Sistemin belirli durumlarını ve olaylarla yaptığı geçişleri tanımlar.

Modern karşılığı olarak UML state machine diyagramları kullanılabilir.

Karar tabloları

Çok sayıda koşul ve sonucun bulunduğu iş kurallarını tablo halinde gösterir.

| Koşul A | Koşul B | Sonuç | | --- | --- | --- | | Evet | Evet | İşlem 1 | | Evet | Hayır | İşlem 2 | | Hayır | Evet | İşlem 3 | | Hayır | Hayır | İşlem 4 |

Karar tabloları hem gereksinim analizi hem test üretimi için yararlıdır.

Geçiş tabloları

Durum makinesini tablo biçiminde gösterebilir.

| Mevcut durum | Olay | Yeni durum | | --- | --- | --- | | Bekliyor | Başlat | Çalışıyor | | Çalışıyor | Durdur | Bekliyor | | Çalışıyor | Hata | Hata |

Petri ağları

Petri ağları eşzamanlı ve olay güdümlü sistemleri modellemekte kullanılabilir.

Temel öğeler:

  • yer,
  • geçiş,
  • token.

Özellikle paralellik, senkronizasyon ve kaynak paylaşımı analizinde kuramsal değer taşır.

Gereksinim analizi ilkeleri

Analiz sırasında:

  • problem alanı anlaşılmalı,
  • sistem sınırı çizilmeli,
  • dış aktörler belirlenmeli,
  • veri ve işlevler modellenmeli,
  • hata ve istisna durumları düşünülmeli,
  • gereksinimler önceliklendirilmeli,
  • kabul kriterleri tanımlanmalıdır.

Veri akışına yönelik analiz

Veri akışına yönelik yöntemler sistemde bilginin nereden geldiğine, hangi süreçte dönüştüğüne ve nereye gittiğine odaklanır.

Veri akış diyagramları

Data Flow Diagram, DFD, dört temel öğe kullanır:

  • dış varlık,
  • süreç,
  • veri akışı,
  • veri deposu.

Bağlam diyagramında sistem tek süreç olarak gösterilir.

Daha alt düzeylerde süreçler ayrıştırılır.

Önemli ilke balancing'dir. Üst düzeyde görülen dış veri akışları alt düzey ayrıştırmada kaybolmamalı veya gerekçesiz yenileri ortaya çıkmamalıdır.

Veri sözlüğü

Veri sözlüğü sistemdeki veri öğelerinin anlamını tanımlar.

Bir veri öğesi için:

  • ad,
  • açıklama,
  • tür,
  • uzunluk,
  • format,
  • geçerli değerler,
  • kaynağı,
  • kullanıldığı yerler

tutulabilir.

Modern sistemlerde şema tanımları, API sözleşmeleri ve veri katalogları aynı amacın daha gelişmiş örnekleridir.

İşlevsel betimleme

DFD sürecin ne yaptığını gösterir ancak iç mantığı ayrıntılı açıklamaz.

Bir sürecin iç davranışı:

  • yapılandırılmış doğal dil,
  • karar tablosu,
  • karar ağacı,
  • durum modeli,
  • pseudocode

ile tanımlanabilir.

Veri yapısına yönelik tarihsel yöntemler

Warnier-Orr ve Jackson System Development yöntemleri program yapısını veri yapısının düzeninden türetmeye çalışan tarihsel yöntemlerdir.

Bu yaklaşımlar günümüzde yaygın geliştirme yöntemi değildir. Ancak kalıcı düşünceleri önemlidir:

  • verinin yapısı yazılım yapısını etkiler,
  • hiyerarşi açık modellenmelidir,
  • sıralama, seçim ve yineleme yapıları sistematik ifade edilmelidir.

Modern projelerde bu ihtiyaçlar daha çok:

  • UML sınıf ve nesne modelleri,
  • durum ve etkinlik diyagramları,
  • domain modeling,
  • veri şemaları,
  • API sözleşmeleri

ile karşılanır.

Ünite 6: Yazılım Tasarımı

Tasarımın amacı

Tasarım, gereksinimlerden uygulanabilir teknik yapıya geçiştir.

İyi tasarım:

  • karmaşıklığı bölümlere ayırır,
  • değişiklik etkisini sınırlar,
  • bileşen sorumluluklarını netleştirir,
  • arabirimleri açık tanımlar,
  • kalite hedeflerini mimariye taşır.

Mimari ve veri tasarımı

Mimari tasarım sistemin ana yapı taşlarını ve aralarındaki ilişkileri belirler.

Veri tasarımı ise:

  • veri modelleri,
  • saklama biçimleri,
  • veri sahipliği,
  • yaşam döngüsü,
  • bütünlük,
  • erişim desenleri

üzerinde durur.

Dağıtık sistemlerde "veri kime aittir?" sorusu bileşen sınırlarının önemli belirleyicisidir.

Yazılım mimarisi

Yazılım mimarisi sistemi oluşturan bileşenleri, bunların sorumluluklarını ve etkileşim biçimlerini kapsar.

Mimari kararlar özellikle şu kalite özelliklerini etkiler:

  • performans,
  • güvenlik,
  • ölçeklenebilirlik,
  • kullanılabilirlik,
  • bakım yapılabilirlik,
  • dağıtılabilirlik.

Mimari stil amaç değil, gereksinime verilen cevaptır.

Katmanlı, olay güdümlü, istemci-sunucu, mikroservis veya modüler monolit gibi yapılar doğru bağlamda kullanılmalıdır.

Modülerlik

Sistem yönetilebilir parçalara ayrılır.

İyi modül:

  • belirli sorumluluğa sahiptir,
  • iç ayrıntısını gizler,
  • açık bir arabirim sunar,
  • başka modüllere gereksiz bağımlılık kurmaz.

Modülerliğin amacı dosya sayısını artırmak değil, değişikliğin etkisini sınırlamaktır.

Cohesion ve coupling

Cohesion, bir modül içindeki öğelerin aynı amaca ne kadar bağlı olduğunu gösterir. Yüksek olması tercih edilir.

Coupling, modüller arasındaki bağımlılık derecesidir. Gereksiz coupling azaltılmalıdır.

Genel hedef:

yüksek cohesion
düşük coupling

olarak özetlenir.

Soyutlama

Soyutlama gereksiz ayrıntıyı gizleyerek probleme uygun seviyede düşünmeyi sağlar.

Örneğin:

dosyayı_oku()

işlemini kullanan kodun disk sektörleri veya sistem çağrılarının ayrıntısını bilmesi gerekmez.

Soyutlama karmaşıklığı yok etmez. Karmaşıklığın görülmesi gereken yerde görünmesini sağlar.

Bilginin gizlenmesi

Information hiding, bir bileşenin değişmesi muhtemel iç kararlarını dışarıdan gizlemesidir.

Örneğin bir veri erişim bileşeni verinin hangi fiziksel veri tabanında saklandığını çağıran koddan gizleyebilir.

Bu ilke değişikliğin yayılmasını azaltır.

Yapısal programlama

Yapısal programlama kontrol akışını:

  • sıralama,
  • seçim,
  • yineleme

gibi açık yapılara dayandırır.

Amaç kontrol akışını anlaşılır tutmaktır.

Modern programlama dilleri daha zengin yapılara sahip olsa da bu temel ilke geçerlidir.

Ön tasarım

Ön tasarım gereksinimlerden genel çözüm yapısına geçiştir.

Başlıca çıktılar:

  • mimari yapı,
  • veri tasarımı,
  • temel bileşenler,
  • dış arabirimler,
  • performans ve güvenlik yaklaşımı.

Ayrıntılı tasarım

Ayrıntılı tasarım bileşenlerin iç gerçekleştirim kararlarını tanımlar.

Örnekler:

  • sınıf yapıları,
  • algoritmalar,
  • veri yapıları,
  • API imzaları,
  • hata yönetimi,
  • transaction sınırları,
  • eşzamanlama kuralları.

Tasarım ilkeleri

Kalıcı tasarım ilkeleri şunlardır:

  • sorumlulukları ayır,
  • gereksiz bağımlılığı azalt,
  • değişmesi muhtemel ayrıntıyı gizle,
  • arabirimleri küçük ve açık tut,
  • tekrarı azalt,
  • gereksiz genellemeler üretme,
  • test edilebilirliği düşün,
  • hata durumlarını normal tasarımın parçası yap.

Kaynak notlardaki fan-in ve fan-out kavramları bugün de bağımlılık analizi açısından değerlidir.

Çok yüksek fan-out bir bileşenin çok sayıda başka bileşene bağımlı olduğunu ve değişiklik riskinin büyüyebileceğini gösterebilir.

Yapısal tasarım ve tarihsel akış dönüşümleri

Yapısal tasarım yöntemleri veri akış modelinden modül yapısı çıkarmaya çalışır.

Klasik iki akış türü:

Transform flow: Veri sisteme girer, dönüşüm merkezinden geçer ve çıktı biçimine dönüşür.

Giriş akışı -> Dönüşüm merkezi -> Çıkış akışı

Transaction flow: Bir giriş olayı belirli işlem yolunu seçer.

           -> İşlem A
Girdi -> seçim -> İşlem B
           -> İşlem C

Bu yöntemler günümüz mimari tasarımında doğrudan standart yöntem değildir. Bununla birlikte veri akışı ile sorumlulukların modüllere ayrılması arasındaki ilişkiyi anlamak açısından değerlidir.

Ayrıntılı tasarım notasyonları

Ayrıntılı tasarımda algoritma ve karar mantığı farklı notasyonlarla ifade edilebilir:

  • pseudocode,
  • karar tabloları,
  • akış diyagramları,
  • durum makineleri,
  • UML activity ve sequence diyagramları.

Notasyonun amacı kodu ikinci kez yazmak değil, önemli kontrol ve veri ilişkilerini açık hale getirmektir.

Ortak alt sistemler

Kurumsal yazılımlarda bazı teknik işlevler iş alanından bağımsız biçimde tekrar ortaya çıkar:

  • kimlik doğrulama ve yetkilendirme,
  • güvenlik,
  • yedekleme ve kurtarma,
  • iletişim,
  • arşivleme,
  • veri dönüşümü ve göç,
  • loglama ve denetim izi,
  • yapılandırma yönetimi.

Bu özellikler sonradan eklenen yardımcı kodlar değil, mimari tasarımın parçasıdır.

Tasarımın gözden geçirilmesi

Tasarım incelemesi gerçekleştirim başlamadan önce pahalı hataları bulmayı amaçlar.

Başlangıç tasarım incelemesinde:

  • mimari sınırlar,
  • ana veri akışları,
  • teknoloji kararları,
  • kalite gereksinimleri

incelenir.

Ayrıntılı tasarım incelemesinde:

  • modül sorumlulukları,
  • veri yapıları,
  • API sözleşmeleri,
  • hata yönetimi,
  • eşzamanlama,
  • test edilebilirlik

değerlendirilir.

Bağlaşım ve yapışıklık

Klasik Türkçe notlarda bağlaşım coupling, yapışıklık ise cohesion karşılığı olarak kullanılır.

Coupling arttıkça bir modüldeki değişikliğin başka modüllere yayılma olasılığı artar.

Cohesion, aynı modül içindeki öğelerin ortak amaca ne kadar hizmet ettiğini gösterir.

İyi tasarımın genel yönü:

düşük gereksiz coupling
yüksek anlamlı cohesion

Bu iki özellik tek bir formülle bütün tasarım kalitesini ölçmez. Mimari bağlam ve bağımlılık türü birlikte değerlendirilmelidir.

Tasarım notasyonları

Tarihsel yöntemlerde yapı şemaları ve özel diyagram notasyonları kullanılmıştır.

Günümüzde UML 2.5.1 ortak modelleme standardı olarak kullanılabilir.

Sık kullanılan diyagramlar:

  • use case,
  • class,
  • object,
  • sequence,
  • state machine,
  • activity,
  • component,
  • deployment,
  • package.

Her projede bütün UML diyagramlarının çizilmesi gerekmez. Belirsizliği azaltan diyagram kullanılmalıdır.

Kullanıcı arabirimi tasarımı

Arabirim tasarımı yalnız ekranın görsel düzeni değildir.

İyi arayüz:

  • kullanıcı görevini destekler,
  • tutarlı davranır,
  • hatayı önlemeye çalışır,
  • hata olduğunda anlaşılır geri bildirim verir,
  • gereksiz bilişsel yük oluşturmaz,
  • erişilebilirliği gözetir.

Arabirim problemleri

Yaygın sorunlar:

  • tutarsız komutlar,
  • anlaşılmaz hata mesajları,
  • sistem durumunun görünmemesi,
  • geri alma olanağının olmaması,
  • aşırı bilgi,
  • kritik işlemlerde yetersiz doğrulama,
  • klavye ve ekran okuyucu erişiminin düşünülmemesi.

Modern kullanıcı deneyimi tasarımında erişilebilirlik temel kalite gereksinimidir.

Ünite 7: Nesne Yönelimli Analiz ve Tasarım

Nesne yönelimli yaklaşım

Nesne yönelimli yaklaşım veri ile bu veri üzerinde çalışan davranışı aynı kavramsal birim altında düzenler.

Temel kavramlar:

  • kimlik,
  • sınıf,
  • nesne,
  • kapsülleme,
  • kalıtım,
  • çok biçimlilik,
  • mesajlaşma veya yöntem çağrısı.

Nesne

Nesne:

  • kimliğe,
  • duruma,
  • davranışa

sahiptir.

Aynı değerlere sahip iki nesnenin kimliği farklı olabilir.

Sınıf

Sınıf benzer nesnelerin ortak yapısını ve davranışını tanımlar.

Sınıf
  ↓
Nesne örnekleri

Sınıf kavramı gerçek dünya sınıflandırmasını doğrudan kopyalamak zorunda değildir. Yazılım tasarımındaki sorumluluklara göre oluşturulur.

Kapsülleme

Kapsülleme bir nesnenin iç durumunun kontrollü arabirim üzerinden değiştirilmesini sağlar.

Amaç her alan için getter/setter yazmak değildir. Nesnenin geçerli durum kurallarını kendi sınırı içinde korumaktır.

Kalıtım

Kalıtım bir sınıfın başka sınıfın özellik ve davranışlarını genişletmesini sağlar.

Kalıtım güçlü bir yeniden kullanım aracıdır ancak sınıflar arasında sıkı bağ oluşturabilir.

Bu nedenle modern tasarımda yalnız "is-a" ilişkisi açık ve davranışsal olarak doğru olduğunda kullanılmalıdır.

Birçok durumda composition daha esnek olabilir.

Çok biçimlilik

Polymorphism, aynı arabirim üzerinden farklı gerçekleştirimlerin kullanılabilmesidir.

Örneğin:

Depolama
  ├─ DosyaDepolama
  ├─ VeritabaniDepolama
  └─ NesneDepolama

Çağıran kod somut gerçekleştirim yerine ortak sözleşmeye bağımlı olabilir.

Bu yaklaşım genişletilebilirliği artırır.

Nesne yönelimli analiz

Nesne yönelimli analizde problem alanındaki:

  • aktörler,
  • varlıklar,
  • sorumluluklar,
  • ilişkiler,
  • olaylar,
  • durumlar

belirlenir.

Amaç doğrudan sınıf kodu yazmak değil, problem alanını nesne ve etkileşimler üzerinden anlamaktır.

Coad-Yourdon yaklaşımı

Coad-Yourdon yöntemi nesne yönelimli analizin erken sistematik yöntemlerindendir.

Modeli:

  • konu,
  • nesne,
  • yapı,
  • özellik,
  • işlev

katmanlarıyla ele alır.

Tarihsel önemi vardır ancak bugün yaygın modelleme dili değildir.

Bu yaklaşımın kalıcı fikri:

Analiz, veri yapısından ayrı olarak nesnelerin kimliğini, ilişkilerini ve davranışını birlikte ele almalıdır.

Booch yaklaşımı ve UML

Booch yöntemi nesne yönelimli tasarımın önemli tarihsel yöntemlerinden biridir.

Booch, Rumbaugh ve Jacobson'ın yaklaşımları daha sonra UML'in oluşumunda birleşmiştir.

Bu nedenle eski Booch diyagramlarını ezberlemek yerine güncel karşılıkları olan UML diyagramlarını bilmek daha değerlidir.

UML sınıf diyagramı

Sınıfları ve aralarındaki yapısal ilişkileri gösterir.

+----------------+
| Siparis        |
+----------------+
| id             |
| tarih          |
+----------------+
| iptalEt()      |
+----------------+
        |
        | 1
        |
        | *
+----------------+
| SiparisSatiri  |
+----------------+

Başlıca ilişkiler:

  • association,
  • aggregation,
  • composition,
  • inheritance,
  • dependency.

Sequence diyagramı

Nesneler arasındaki mesajların zaman sırasını gösterir.

Örneğin:

Kullanici -> SiparisServisi: iptalEt()
SiparisServisi -> Depo: rezervasyonuBirak()
SiparisServisi -> Odeme: iadeEt()
SiparisServisi -> Kullanici: sonuc

Dağıtık sistemlerde çağrı sırası ve sorumlulukları anlamak için yararlıdır.

State machine diyagramı

Bir nesnenin yaşam döngüsünü durumlar üzerinden gösterir.

OLUSTURULDU
    ↓ onay
ONAYLANDI
    ↓ sevk
SEVK_EDILDI
    ↓ teslim
TESLIM_EDILDI

Geçiş kuralları karmaşık iş süreçlerinde açık model sağlar.

Activity diyagramı

İş veya kontrol akışını gösterir.

Paralel işler, kararlar ve süreç adımlarını görselleştirmek için kullanılabilir.

Package diyagramı

Kod veya model öğelerinin paketler halinde nasıl gruplandığını ve bağımlılıklarını gösterir.

Paket sınırları mimari bağımlılıkların yönetiminde önemlidir.

Component diyagramı

Sistemin dağıtılabilir veya değiştirilebilir büyük bileşenlerini ve arayüzlerini gösterir.

Modern servis ve modüler uygulama mimarilerinde yararlıdır.

Kullanım durumları

Use case, bir aktörün sistemle belirli hedefe ulaşmak için yaptığı etkileşimi tanımlar.

Bir kullanım durumu tipik olarak:

  • aktör,
  • önkoşul,
  • temel akış,
  • alternatif akışlar,
  • hata durumları,
  • sonkoşul

bilgilerini içerir.

Use case ekran tasarımı değildir. Kullanıcı veya dış sistem açısından gözlenebilir hedefi açıklar.

CRC kartları

Class-Responsibility-Collaborator, CRC yaklaşımı sınıfları erken analiz aşamasında basit kartlarla düşünmeyi sağlar.

Her kart:

Sınıf
- Sorumluluklar
- İşbirliği yaptığı sınıflar

bilgisini içerir.

CRC'nin değeri ayrıntılı kod üretmek değil, sorumlulukların doğru nesnelere dağıtılmasını tartışmaktır.

Nesne ilişkileri

Nesne modellerinde başlıca ilişkiler:

  • association,
  • dependency,
  • aggregation,
  • composition,
  • inheritance.

Composition güçlü yaşam döngüsü sahipliğini, sıradan association ise daha gevşek ilişkiyi ifade edebilir.

Çoklu kalıtım bazı dillerde desteklenir ancak isim çakışması ve karmaşık sınıf hiyerarşileri oluşturabilir. Arayüz ve composition çoğu durumda daha sade alternatif sağlar.

Eşzamanlılık ve alt sistem tasarımı

Nesne yönelimli tasarım yalnız sınıf yapısı değildir. Sistem eşzamanlı çalışıyorsa:

  • hangi işlerin ayrı thread veya süreçte çalışacağı,
  • paylaşılan durumun nerede tutulacağı,
  • senkronizasyon sınırlarının ne olacağı,
  • mesajlaşma veya kuyrukların nasıl kullanılacağı

belirlenmelidir.

Alt sistem tasarımında ayrıca:

  • görev yönetimi,
  • veri yönetimi,
  • kaynak yönetimi,
  • kullanıcı arayüzü,
  • dış sistem iletişimi

ayrı sorumluluk alanları olarak ele alınabilir.

Tasarım kalıpları

Design pattern, tekrar eden tasarım problemine bağlama bağlı genel çözüm şablonudur.

Kalıp doğrudan kopyalanacak kod değildir.

Örnekler:

  • Strategy,
  • Observer,
  • Factory Method,
  • Adapter,
  • Decorator.

Bir kalıp ancak gerçekten çözdüğü problem varsa kullanılmalıdır. Gereksiz pattern kullanımı tasarımı sadeleştirmek yerine karmaşıklaştırabilir.

Tasarımın tamamlanması

Nesne yönelimli tasarım yalnız sınıf diyagramı üretmekle tamamlanmaz.

Tasarım şu sorulara yanıt vermelidir:

  • Hangi nesne hangi sorumluluğa sahip?
  • Verinin sahibi kim?
  • İş kuralları nerede?
  • Hangi bağımlılıklar ters çevrilmeli?
  • Hangi işlemler transaction sınırı oluşturuyor?
  • Hata nasıl yayılıyor?
  • Nesneler hangi yaşam döngüsüne sahip?
  • Paralel erişim nasıl yönetiliyor?

SOLID ile bağlantı

Modern nesne yönelimli tasarımda SOLID ilkeleri sınıf ve modül sınırlarını değerlendirmek için kullanılabilir:

  • Single Responsibility Principle,
  • Open/Closed Principle,
  • Liskov Substitution Principle,
  • Interface Segregation Principle,
  • Dependency Inversion Principle.

Bunlar katı kurallar değil, bağımlılık ve değişiklik maliyetini düşünmek için tasarım ilkeleridir.

Composition over inheritance

Kalıtım yalnız kod tekrarını azaltmak için kullanılmamalıdır.

Composition:

Nesne A
   |
   +--> Hizmet B

ile davranış çalışma zamanında daha esnek birleştirilebilir.

Bu nedenle modern tasarımda "composition over inheritance" sık kullanılan bir ilkedir.

Nesne yönelimli tasarımın sınırları

Her problem nesne yönelimli model gerektirmez.

Fonksiyonel, veri yönelimli, olay güdümlü veya veri akışı tabanlı tasarım kimi problemlerde daha doğal olabilir.

Mühendislik yaklaşımı paradigmadan önce probleme bakar.

Ünite 8: Gerçekleştirim ve Kodlama

Gerçekleştirim aşaması

Gerçekleştirim, tasarım kararlarının çalıştırılabilir yazılıma dönüştürülmesidir.

Bu aşamada yalnız kod yazılmaz. Aynı zamanda:

  • veri tabanı nesneleri,
  • yapılandırma,
  • derleme sistemi,
  • bağımlılıklar,
  • test kodu,
  • dağıtım paketleri

üretilir.

Gerçekleştirim tasarımdan kopuk yürütülmemelidir. Kod sırasında yeni teknik bilgi ortaya çıkarsa tasarım da güncellenmelidir.

Yazılım geliştirme ortamları

Geliştirme ortamı şu araçların birlikte çalışmasından oluşur:

  • programlama dili ve derleyici,
  • IDE veya editör,
  • sürüm kontrol sistemi,
  • build aracı,
  • paket ve bağımlılık yöneticisi,
  • veri tabanı sistemi,
  • test araçları,
  • statik analiz araçları,
  • hata ayıklayıcı,
  • CI/CD sistemi.

Araç seçimi projenin gereksinimine göre yapılmalıdır. Bir aracın popüler olması tek başına teknik gerekçe değildir.

Programlama dilleri

Programlama dili seçimi şu ölçütlerle değerlendirilir:

  • problem alanına uygunluk,
  • çalışma zamanı performansı,
  • bellek ve gerçek zaman gereksinimleri,
  • ekosistem,
  • güvenlik özellikleri,
  • ekip deneyimi,
  • hedef platform,
  • bakım ve destek süresi.

Tek bir dil bütün yazılım sınıfları için en iyi değildir.

Veri tabanı yönetim sistemleri

VTYS geleneksel dosya kullanımına göre:

  • ortak veri modeli,
  • veri sözlüğü ve metadata,
  • veri bağımsızlığı,
  • eşzamanlı kullanıcı desteği,
  • transaction,
  • bütünlük sınırlamaları,
  • erişim denetimi,
  • sorgulama

olanakları sunar.

İlişkisel, belge, anahtar-değer, grafik ve zaman serisi gibi veri modelleri farklı gereksinimlere cevap verir. Veri tabanı seçimi yalnız geliştirme kolaylığına göre değil, veri tutarlılığı ve erişim deseni üzerinden yapılmalıdır.

Hazır kütüphaneler ve bileşenler

Her işlevi yeniden geliştirmek yerine güvenilir kütüphane ve bileşenlerden yararlanmak üretim maliyetini azaltabilir.

Buna karşılık her bağımlılık:

  • sürüm,
  • güvenlik,
  • lisans,
  • bakım,
  • tedarik zinciri

riski getirir.

Bu nedenle üçüncü taraf kod da ürün konfigürasyonunun parçasıdır.

Kodlama stili

Kodlama stilinin amacı estetik birlikten önce okunabilirlik ve ortak çalışma sağlamaktır.

Temel ilkeler:

  • anlamlı isimler,
  • tutarlı biçimleme,
  • küçük ve belirgin sorumluluklar,
  • gereksiz tekrarın azaltılması,
  • karmaşık koşulların sadeleştirilmesi,
  • hata yollarının görünür olması.

Yorum satırı kodun ne yaptığını tekrar etmemeli; gerekçe, varsayım veya dış kısıt gibi koddan anlaşılamayan bilgiyi açıklamalıdır.

Olağandışı durum yönetimi

Hata yönetimi normal kontrol akışının parçasıdır.

Hatalar kabaca:

  • geçersiz girdi,
  • beklenen iş kuralı ihlali,
  • geçici altyapı hatası,
  • kalıcı dış sistem hatası,
  • programlama hatası

olarak ayrılabilir.

Her hata için aynı mekanizma uygun değildir. Retry yalnız geçici olduğu bilinen hatalarda anlamlıdır.

Bir exception yakalanıp sessizce yok edilmemelidir. Sistem ya hatayı düzeltebilmeli ya da yeterli bağlamla üst katmana aktarabilmelidir.

Kod gözden geçirme

Code review yalnız biçim hatası aramak için yapılmaz.

İnceleme sırasında:

  • doğruluk,
  • güvenlik,
  • veri ve sınır durumları,
  • concurrency,
  • hata yönetimi,
  • test edilebilirlik,
  • gereksiz karmaşıklık,
  • API uyumu

kontrol edilir.

Otomatik formatter ve linter ile bulunabilen sorunları insan incelemesine bırakmak verimsizdir. İnsan incelemesi daha çok semantik ve tasarım problemlerine odaklanmalıdır.

Ünite 9: Yazılım Mimarileri

Mimari yaklaşım

Yazılım mimarisi sistemi büyük sorumluluk alanlarına ve iletişim sınırlarına böler.

Mimari seçim:

  • performans,
  • güvenilirlik,
  • güvenlik,
  • ölçeklenebilirlik,
  • dağıtım,
  • ekip yapısı,
  • bakım maliyeti

üzerinde uzun süreli etki oluşturur.

İstemci-sunucu mimarisi

İstemci bir hizmet talep eder. Sunucu hizmeti sağlar.

İstemci -> İstek -> Sunucu
İstemci <- Yanıt <- Sunucu

Sunucu farklı hizmet türlerini sağlayabilir:

  • dosya,
  • veri tabanı,
  • uygulama,
  • web,
  • kimlik,
  • mesajlaşma.

Güncel dağıtık sistemlerde aynı uygulama aynı anda hem istemci hem sunucu rolü oynayabilir.

İki katmanlı mimari

İki katmanlı yapıda kullanıcı arayüzü ve uygulama mantığının önemli bölümü istemcide, veri hizmeti sunucuda bulunabilir.

İstemci uygulaması <-> Veri tabanı sunucusu

Basit sistemlerde düşük ek katman maliyeti sağlar. Çok sayıda istemci olduğunda dağıtım ve sürüm yönetimi zorlaşabilir.

Üç katmanlı mimari

Üç temel katman:

Sunum
  ↓
Uygulama / İş mantığı
  ↓
Veri

İstemci veri tabanına doğrudan erişmek yerine uygulama katmanına bağlanır.

Avantajları:

  • iş mantığının merkezileştirilmesi,
  • güvenlik sınırlarının belirginleşmesi,
  • istemci dağıtımının sadeleşmesi,
  • yatay ölçeklendirme olanaklarıdır.

N katmanlı ve dağıtık mimariler

Üç katmanlı model daha fazla teknik katmana ayrılabilir:

  • API gateway,
  • web katmanı,
  • uygulama servisleri,
  • mesajlaşma,
  • cache,
  • veri katmanı.

Katman sayısı arttıkça dağıtık sistem maliyetleri de artar:

  • ağ gecikmesi,
  • kısmi arıza,
  • gözlemlenebilirlik gereksinimi,
  • transaction karmaşıklığı.

Web mimarisi

Klasik web yapısı:

Tarayıcı
   ↓ HTTP
Web / Uygulama sunucusu
   ↓
Veri ve dış servisler

Modern web uygulamalarında:

  • REST veya RPC API'leri,
  • gerçek zamanlı bağlantılar,
  • CDN,
  • ters proxy,
  • kimlik servisleri,
  • istemci tarafı uygulamalar

aynı sistem içinde bulunabilir.

Tarihsel WAP yaklaşımı

WAP, sınırlı yetenekli erken mobil aygıtlar için geliştirilen tarihsel kablosuz uygulama mimarisidir. Mobil tarayıcıların, HTML/CSS/JavaScript desteğinin ve genel IP tabanlı mobil ağların gelişmesiyle temel uygulama modeli olmaktan çıkmıştır.

Kalıcı ders, istemci kapasitesi ve ağ özelliklerinin uygulama protokolü ile kullanıcı arayüzü tasarımını doğrudan etkileyebilmesidir.

Bileşen tabanlı mimari

Bileşen, açık bir sözleşme üzerinden kullanılan ve iç gerçekleştirimini gizleyen yeniden kullanılabilir yazılım parçasıdır.

İyi bir bileşen:

  • açık arayüze,
  • sınırlı sorumluluğa,
  • değiştirilebilir gerçekleştirim yapısına,
  • belgelenmiş bağımlılıklara

sahiptir.

Tarihsel COM/DCOM, JavaBeans ve benzeri teknolojiler bileşen yaklaşımının erken örnekleridir. Günümüzde aynı düşünce:

  • modüller,
  • paketler,
  • kütüphaneler,
  • servisler,
  • plugin sistemleri

üzerinden devam eder.

Servis yönelimli ve mikroservis mimarileri

Servis yönelimli yaklaşım işlevleri ağ üzerinden açık sözleşmelerle sunar.

Mikroservis mimarisi bu fikri daha küçük ve bağımsız dağıtılabilir hizmetlere uygular.

Avantajları bağlama göre:

  • bağımsız dağıtım,
  • ekip özerkliği,
  • farklı ölçeklendirme profilleri

olabilir.

Maliyetleri:

  • dağıtık transaction,
  • ağ hataları,
  • operasyon yükü,
  • gözlemlenebilirlik,
  • sürüm uyumluluğudur.

Bu nedenle küçük bir sistemin mikroservislere bölünmesi otomatik olarak daha iyi mimari oluşturmaz.

Ünite 10: CASE, Araç Zincirleri ve Değişim Mühendisliği

CASE kavramı

CASE araçları yazılım yaşam döngüsünün mühendislik etkinliklerini bilgisayar desteğiyle yürütmeyi amaçlar.

Tarihsel sınıflandırmada araçlar:

  • gereksinim,
  • süreç modelleme,
  • veri modelleme,
  • proje planlama,
  • risk analizi,
  • tasarım,
  • kod üretimi,
  • test,
  • kalite,
  • konfigürasyon,
  • belgeleme

işlevlerine göre ayrılır.

CASE araçlarının bütünleştirilmesi

Bütünleşik bir mühendislik ortamında üç tür bütünlük önemlidir.

Veri bütünlüğü: Bir araçta üretilen model veya metadata diğer araçlar tarafından da kullanılabilir.

Denetim bütünlüğü: Bir araç diğerini iş akışının parçası olarak tetikleyebilir.

Arabirim bütünlüğü: Kullanıcı araçlar arasında benzer etkileşim ve çalışma modeli görür.

Günümüzde bu bütünleşme tek büyük CASE ürünü yerine API'ler, Git, CI/CD ve standart dosya biçimleri üzerinden dağıtık araç zincirleriyle sağlanabilir.

Modern mühendislik araç zinciri

Gereksinim / issue
       ↓
Sürüm kontrolü
       ↓
Kod inceleme
       ↓
Build
       ↓
Statik analiz
       ↓
Test
       ↓
Paket / artefakt
       ↓
Dağıtım
       ↓
İzleme
       ↓
Geri bildirim

Bu zincirin en önemli özelliği izlenebilirliktir. Bir üretim sürümündeki değişiklik hangi gereksinim, commit, build ve test sonucundan geldiğiyle ilişkilendirilebilmelidir.

CASE aracı seçimi

Araç kullanımı kendi başına verimlilik sağlamaz.

Değerlendirme ölçütleri:

  • proje büyüklüğü,
  • ekip deneyimi,
  • öğrenme maliyeti,
  • bütünleşme gereksinimi,
  • lisans ve işletim maliyeti,
  • dışa aktarılabilir veri biçimleri,
  • tedarikçi bağımlılığı.

Basit bir projede ağır bir süreç aracı verimi azaltabilir. Büyük ve uzun ömürlü projelerde ise izlenebilirlik ve otomasyon maliyeti kısa sürede geri kazanılabilir.

Tersine ve yeniden mühendislik

Reverse engineering, mevcut sistemden daha üst düzey bilgi çıkarmayı amaçlar.

Örnekler:

  • koddan çağrı grafı çıkarma,
  • veri tabanından ER modeli üretme,
  • binary veya protokolden davranış analizi,
  • bağımlılık haritası oluşturma.

Reengineering, mevcut sistemi daha sürdürülebilir yapıya dönüştürür.

Bu süreç:

Mevcut sistem
     ↓
Analiz / tersine mühendislik
     ↓
Model ve bilgi kazanımı
     ↓
Yeniden tasarım
     ↓
Dönüşüm / modernizasyon
     ↓
Doğrulama

şeklinde düşünülebilir.

Eski sistemlerde eksik dokümantasyon nedeniyle kod, veri tabanı, çalışma zamanı kayıtları ve kullanıcı davranışı birlikte incelenebilir.

Genel Çerçeve

Yazılım mühendisliği konuları birbirinden bağımsız değildir.

Bir gereksinim değiştiğinde:

Gereksinim
    ↓
Etki analizi
    ↓
Mimari / tasarım
    ↓
Kod
    ↓
Test
    ↓
Konfigürasyon
    ↓
Sürüm
    ↓
Dağıtım
    ↓
İşletim

zinciri etkilenebilir.

Proje yönetimi bu zincirin süre ve kaynaklarını yönetir.

Kalite yönetimi çıktının beklenen özellikleri sağlamasını gözetir.

Konfigürasyon yönetimi hangi değişikliğin hangi sürümde olduğunu izler.

Test değişikliğin doğruluğunu denetler.

Bakım sistemi yaşam döngüsü boyunca ayakta tutar.

Gereksinim analizi yanlışsa iyi kod yanlış problemi çözer.

Mimari kötü ise doğru gereksinim pahalı ve kırılgan biçimde gerçekleştirilir.

Test zayıfsa hatalar kullanıcıya kadar ulaşır.

Konfigürasyon yönetimi yoksa doğru kodun hangi sürümde olduğu bilinmez.

Bu nedenle yazılım mühendisliği "iyi programlama"dan daha geniştir.

Bu sayfanın QR kodu