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:
- ihtiyaç ve kapsamın belirlenmesi,
- gereksinimlerin çıkarılması ve analizi,
- mimari ve ayrıntılı tasarım,
- gerçekleştirim,
- doğrulama ve test,
- dağıtım,
- işletim,
- bakım ve geliştirme,
- 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:
- Başlangıç,
- Tekrarlanabilir,
- Tanımlanmış,
- Yönetilebilir,
- 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ımAvantajı 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
\ /
KodlamaSol 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:
- hedefler ve alternatifler belirlenir,
- riskler analiz edilir,
- çözüm geliştirilir ve doğrulanır,
- 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
↓
MonitoringCASE 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 / KLOCAncak 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:
- kapsamı ve varsayımları tanımla,
- ürünü veya işleri bölümlere ayır,
- büyüklüğü tahmin et,
- geçmiş proje verilerini kullan,
- ekip ve teknoloji etkilerini değerlendir,
- risk payını belirle,
- sonucu bağımsız yöntemlerle karşılaştır,
- 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^dKlasik 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ğerlendirRisk 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:
- sorunun tanımı,
- gereksinimler,
- çözüm yaklaşımı,
- geliştirme süreci,
- ekip ve organizasyon,
- iş kırılımı,
- zamanlama,
- maliyet,
- risk,
- kalite ve test,
- 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:
- belirlenir,
- süreleri tahmin edilir,
- bağımlılıkları çıkarılır,
- kaynaklara atanır,
- 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 + n2Gerçek program uzunluğu:
N = N1 + N2Tahmini uzunluk:
N^ = n1 log2(n1) + n2 log2(n2)Hacim:
V = N log2(n)Zorluk:
D = (n1 / 2) x (N2 / n2)Efor:
E = D x VHalstead ö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 + 2Burada:
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 + 2Polarak 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 denetlenirBeyaz 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:
- kontrol akış grafını oluşturur,
- karmaşıklığı hesaplar,
- bağımsız yolları belirler,
- 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 <= 100ise güçlü test adayları:
0, 1, 2, 99, 100, 101değ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 TestsBu 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
↓
KurulumDeğ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:
- konfigürasyon öğelerini belirleme,
- baseline oluşturma,
- sürüm kontrolü,
- değişiklik kontrolü,
- durum muhasebesi,
- 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ıtEtki 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ımTemel 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
↓
PostconditionDurum 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 couplingolarak ö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 CBu 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ı cohesionBu 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 örnekleriSı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: sonucDağı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_EDILDIGeç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ıflarbilgisini 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 Bile 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 <- SunucuSunucu 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ı sunucusuBasit 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ış servislerModern 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 bildirimBu 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
↓
İşletimzinciri 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.