8 Ekim 2020 Perşembe

Hierarchical Cache - Hiyerarşik Önbellek

Giriş
Bize önce bir tane multimap lazım. Ancak bu multimap concurrent bir multimap olmalı.
Şöyle yaparız
public class ConcurrentMultiMap<K> {
  ConcurrentHashMap<Class<? extends K>,ConcurrentSkipListSet<K>> map = ...
  ...
}
Elimizde şöyle bir nesne olsun. Bu sınıf güncellenecek veriyi ve bu verinin kalıtım hiyerarşisini saklar.
public class DataEvent {
  private MyBaseObject data = ...;
  private Collection<Class<? extends MyBaseObject>> hierarchy = ...;

  Collection<Class<? extends MyBaseObject>> getHierarchy(){
    return hierarchy;
  }
  ... 
}
DataEvent'leri işleyen bir sınıf olsun. Bu sınıf gelen veriyi tüm ata sınıflara da ekler.
public class DataEventListener {
  private ConcurrentMultiMap<MyBaseObject> map;

  public void addToMap(DataEvent dataEvent){
    Collection<Class<? extends MyBaseObject>> hierarchy = dataEvent.getHierarchy();
    for(Class<? extends MyBaseObject> clazz : hierarchy){
      map.add(clazz,data);
    }
  }
}
Burada eksik kalan şey DataEvent nesnesini oluştururken data yanında bu data'ya ait üst sınıfları da verebilmek. Bunun için elimizde şöyle bir kod olsun
public class ClassCapsule<C> {
  private Class<? extends MyBaseObject> clazz;
  private HierarchicalCollection<Class<? extends MyBaseObject>> hierarchy; 

  public ClassCapsule(Class<? extends MyBaseObject> clazz){
    this.clazz = clazz;
    this.hierarchy = new HierarchicalCollection();
  }

  public void setParent(ClassCapsule<C> parent){
    hierarchy.setParent(parent.hierarchy);
  }

  public Collection<Class<? extends MyBaseObject> getHierarchy(){
    return hierarchy;
  }
}
HierarchicalCollection şöyle olsun
public class HierarchicalCollection<T> extends AbstractCollection {
  private Set<T> set = new HashSet<>();
  private HierarchicalCollection<T> parent;
  
  public setParentCollection(HierarchicalCollection<T> parent){
    this.parent = parent;
  }
  public Iterator<T> iterator(){
    return Iterators.concat(set.iterator(),parent.iterator());
  }
  public boolean contains(T object){
    return set.contains(object) || parent.contains(object);
  }
}
Şimdi elimizdeki sınıfları kalıtıma göre indeksleyelim
public class ClassCapsuleIndexer<C> {
  private Map<Class<? extends MyBaseObject>,ClassCapsule<C> capsuleMap = ...;

  public ClassCapsule<C> getClassCapsule(Class<? extends MyBaseObject> clazz){
    ClassCapsule<C> capsule = capsuleMap.get(clazz) 
    if (capsule == null){
      capsule = new ClassCapsule<C>(clazz);
      Class<? extends MyBaseObject> superClass = findSuperClass(clazz);
      if (superClass != null){
        classCapsule.setParent(getClassCapsuleFroClass(superClass));
      }
      capsuleMap.put(clazz,capsule);
    }
    return capsule;
  }
  
  private Class>? extends MyBaseObject> findSuperClass(Class<?> clazz){
    Class<? extends MyBaseObject> result = null;
    try {
      clazz.getSuperClass().asSubclass(MyBaseObject.class);
    } catch (ClassCastException e){
      ...
    }
   }
}
Böylece ClassCapsuleIndexer ile istenilen sınıf tipine ait ClassCapsule bulunur. ClassCapsule sınıfının getHierarchy() metodu ile ata sınıfların listesi elimize geçer. Biz de bu hiyerarşi üzerinde dolaşıp ConcurrentMultiMap'teki ata sınıflara ait key değerlerine de güncelleme yapabiliriz.

UTC ve Leap Second (Artık Saniye)

Giriş
Önce UTC, GPS ve atomik saat arasındaki farkı bilmek lazım. Çünkü hem GPS hem de UTC uluslararası atomik zamandan türetilmişler. Açıklaması şöyle
Both GPS time and UTC are derived from the atomic time TAI ...
TAI
TAI 400 tane atomik saatin ortalamasıdır. Saatlerin çoğu Cesium saatleridir. Bu saat Cesium 133 atomunun saniyede 9,192,631,770 defa salınım yapmasına dayanır. Açıklaması şöyle. TAI 1958 yılından veri var.
Synchronized on existing UT2 on January 1 1958.
TAI saatinde artık saniye yoktur.

UTC
TAI'den sonra UTC 1970 yılında ortaya çıkıyor. İlk ortaya çıktığında TAI ile olan farkı 10 saniye. Özetlersek açıklaması şöyle
- Redefined in 1970 to include leap seconds.
- Resynchronized on January 1st 1972 to be exactly 10 seconds behind TAI.
- 27 leap seconds have been introduced since then.
- UTC is now 37 seconds behind TAI.
- UTC = TAI - 37s at present.
Şeklen şöyle


GPS
En son olarak ta GPS 1980 yılında ortaya çıkıyor. Açıklaması şöyle. Yani GPS ve UTC 6 Ocak 1980 yılında aynı olarak şekilde başlamışlar.
GPS time and UTC were equal on January 6 1980
Özetlersek açıklaması şöyle. GPS için "internal representation reset" ne anlama geliyor bilmiyorum.
- Defined as equal to UTC at midnight on January 6th 1980 when UTC was 19 seconds behind TAI.
- 18 leap seconds were added to UTC since then.
- GPS time is now 18 seconds ahead of UTC.
- The internal representation of GPS time was reset (due to week counter finite size) on August 21 1999 and April 7 2019, and this may happen every 1024 weeks. Conversion programs have to take this into account. While the start time is changed each time, the offset with TAI is not modified.
- GPS time = TAI - 19s (always).
- GPS time = UTC + 18s at present.

GPS Tekrar Ayarlanmamıştır
Açıklaması şöyle
GPS time is never resynchronized; its offset from TAI is the number of leap seconds which existed on January 6 1980, that is 19.
Açıklaması şöyle
GPS time was set to match UTC in 1980, but has since diverged. The lack of corrections means that GPS time remains at a constant offset with International Atomic Time (TAI) (TAI – GPS = 19 seconds).
Fakat UTC sürekli tekrar ayarlanıyor. Açıklaması şöyle. Dolayısıyla TAI ve GPS arasındaki fark hep sabitken, UTC gittikçe daha da geri kalıyor.

2017'de Durum
UTC, TAI'den toplamda 37 saniye, GPS'ten 18 saniye geride.
As of 1 January 2017, when another leap second was added, TAI is exactly 37 seconds ahead of UTC. The 37 seconds results from the initial difference of 10 seconds at the start of 1972, plus 27 leap seconds in UTC since 1972.
2020'de Durum
Açıklaması şöyle. UTC - GPS farkı halen 18 saniye
The UTC–GPS offset as of 5-March-2020 is 18 seconds.
2021'de Durum
Şeklen şöyle. GPS ve TAI arasındaki 19 saniye hep sabit. UTC, TAI'den toplamda 37 saniye geride.



UTC'nin Ayarlanması Nasıldır
UTC , UTC1 isimli dünyanın dönüşünü ölçen bir başka standarda göre ara sıra tekrar ayarlanır. UTC1 dünya çapındaki bazı gözlemevlerinin yaptığı ölçümlerin ortalaması gibi düşünülebilir. Eğer UTC1 artık saniye olmasına karar verirse, UTC de tekrar ayarlanır.

Artık saniye dünyanın dönüşündeki yavaşlamadan kaynaklanıyor. 

GPS Sinyali UTC Saati de Bildirir
GPS'te 3 tane saat var. Açıklaması şöyle
There are three kinds of time available from GPS: GPS time, UTC as estimated and produced by the United States Naval Observatory, and the times from each free-running GPS satellite's atomic clock.
POSIX Günü ve UTC Farklı Şeylerdir
POSIX günü 86,400 saniye uzunluğunda tanımlanmış. Ancak gerçek hayatta günler daha uzun veya kısa da olabilir. Bu tutarsızlığı gidermek için genellikle aynı saniyenin tekrarlanması çözümü kullanılıyor. Açıklaması şöyle.
POSIX time doesn't include leap seconds, and is not implemented the same way in every UNIX, so it routinely gets inconsistent for several seconds every couple of years. It is not a high-precision time scale, and there is little point correcting it for relativistic effects which are smaller than it can represent.
Aşağıda bu konuyla ilgili bir karikatür var.


Leap Second POSIX'te Problem Sebep Olur Mu?
Why Does the Leap Second Cause Problems? başlıklı soruda ntpd servisinin artık saniye mesajı alınca bazı Linux çekirdeklerinde hataya sebep olabildiğine dair bir soru ve açıklamalar mevcut. Anladığım kadarıyla ntpd adjtimex sistem çağrısını kullanarak saati ayarlıyor.

git merge seçeneği - Belirtilen Bir Dalı Alır ve Mevcut Dal İle Birleştirir

Giriş 
Belirtilen dalı mevcut dal ile birleştirmek için kullanılır. Bu komut yerine squash veya rebase kullanılabilir. Açıklaması şöyle
Merge the specified branch into the current branch
Merge ve Conflict
Merge işleminde conflict çıkma olasılığı var. Bu yüzden sıkça merge yapmakta fayda var. Açıklaması şöyle
Delaying things only means it's more likely for others to get code into your merge target, making the merge worse
Merge ve Unit Test
Her iki dalda da unit testlerin geçmesi, merge işleminde sonra da testlerin geçeceği anlamına gelmez. Dolayısıyla master branch'te de testlerin koşması gerekir.

Kullanım
Feature isimli branch açtığımızda şeklen şöyle olur
Merge işleminden sonra şöyle olur. Yani commit tarihçemizi veya sıramızı muhafaza eder

Pull Request vs. Merge Request
Açıklaması şöyle
Pull Request in Bitbucket and GitHub or Merge Request in GitLab are the features made for more convenient code review and change management. Though they have different names, these features are equivalent, as they both do the same git merge command to merge feature branches or forks with the existing code.
Bitbucket Pull Request şeklen şöyle.

Birleştirme işleminden sonra kaynak dalı silmek isteyebiliriz. Şöyle yaparız


Kullanım
Bulunduğumuz dala ismi belirtilen daldaki değişiklikleri birleştirir.

Örnek
Şöyle yaparız
git checkout develop
git merge feature/[JIRA-ID]-description
Yani "develop" dalına geçtikten sonra "feature/[JIRA-ID]-description" dalındaki değişiklikleri develop'a birleştirmek isteriz.

Örnek
Şöyle yaparız
# Get repo changes
git fetch origin

# Go to our feature branch
git checkout feature

# Commit some work
...

# Go to main branch
git checkout master

# Merge feature to main branch
git merge --no-ff feature

# Push to origin
git push origin main

# We can delete the feature branch safely
git branch -d feature
-squash seçeneği
Açıklaması şöyle. Yani commit tarihçesini veya sırasını muhafaza etmez, bizim commitleri en sona ekler.
In this case a new commit in the origin branch will be created, containing all of the commits created in our feature branch.
Şeklen şöyle olur


Örnek
Şöyle yaparız. release branch'e geçtikten sonra bugfix ve feature branch'lerini release branch'e birleştiririz
git checkout release/[YY.MM]
git merge --squash bugfix/[JIRA-ID]-description
git merge --squash feature/[JIRA-ID]-description

Örnek
Şöyle yaparız
# Get repo changes
git fetch origin

# Go to our feature branch
git checkout feature

# Commit some work
...


# Go to main branch
git checkout main

# Merge feature to main branch
git merge --squash feature

# Push to origin
git push origin main

# We can delete the feature branch safely
git branch -d feature

-X seçeneği
Örnek
Şöyle yaparız. otherbranch o anda checkout etmiş olduğumuz branch ile birleştirilir. Yani
develop <- otherbranch şeklindedir.
Burada patience git'e patience algoritmasını kullanması söyleniyor.
git merge -X patience otherbranch

Elektronik Taarruz Sistemleri - Elektronik Attack (Eski Adı Electronic Countermeasures)

Giriş
Bu konu çok karışık bir konu. O yüzden sadece anladığımı kabaca özetlemeye çalışacağım. Konuya da kesinlikle hakim değilim :)

Elektronik Taarruz Sistemleri eskiden Electronic Countermeasures (ECM) olarak isimlendiriliyordu. Dolayısıyla uçaklardaki sistemlere halen ECM Pod deniliyor.

Elektronik Taarruz Sistemleri
Şu şekilde tasnif edilebilir
- Radar Elektronik Taarruz
- Muhabere Elektronik Taarruz
- Dekoylar
Elektronik Taarruz'un aktif ve pasif olmak üzere iki türü vardır. Esasen karıştırmayı mekanik ve elektronik olarak ta gruplamak mümkün ancak ben yukarıdaki gibi gruplamayı daha uygun buluyorum.

Pasif Karıştırma basittir. Radarın huzmesi önüne atılan yansıtıcılar ile yapılan karıştırma tekniğidir. Bakınız chaff

1. Aktif Karıştırma

Radar Tipleri
Radarlar çeşitli şekillerde sınıflandırılabilirler
1. Konuşlandıkları ortam : 
İşlevleri şöyle olabilir 
Havada konuşlu, 
Karada konuşlu, 
Denizde Konuşlu gibi
2. İşlevlerine göre 
İşlevleri şöyle olabilir 
Arama Radarı
Takip Radarı
Atış Yeri Tespit Radarı
3. Dalga şekillerine göre
Dalga Şekilleri şöyle olabilir
- Sürekli Dalga (Continious Wave)
- Darbeli Dalga (Pulse Wave)
1.1. Radar Elektronik Taarruz Sistemleri
Açıklaması şöyle
Radar jamming and deception is a form of electronic countermeasures that intentionally sends out radio frequency signals to interfere with the operation of radar by saturating its receiver with noise or false information. Concepts that blanket the radar with signals so its display cannot be read are normally known as jamming, while systems that produce confusing or contradictory signals are known as deception, but it is also common for all such systems to be referred to as jamming.
Darbeli dalgada Darbe Genişliği ve Darbe Tekrar Aralığı belirtilir.

1.2 Jamming Yöntemleri 
Aktif Karıştıma da kendi içinde ikiye ayrılır.

1. Noise Jamming
2. False Target Generation veya Deception Jamming

Açıklaması şöyle
ECM can consist of (1) noise jamming that enters the receiver via the antenna and increases the noise level at the input of the receiver, (2) false target generation, or repeater jamming, by which hostile jammers introduce additional signals into the radar receiver in an attempt to confuse the receiver…
1.2.1 Noise Jamming
Açıklaması şöyle. Jammer tarafından gönderilen sinyal gürültü yaratır
Noise jammers modulate the jamming signal with AM or phase noise.
Uygulayabileceği bazı karıştırma (jamming) teknikleri şu şekilde tasnif edilebilir. 
- Spot (Nokta)
- Barrage (Baraj)
- Sweep (Tarama)
- Spot tekniğinde sadece belirtilen frekansta karıştırma yapılır. Açıklaması şöyle. Bu teknik frekans atlamalı radarlarda etkili değil.
Spot jamming or spot noise occurs when a jammer focuses all of its power on a single frequency. This overwhelms the reflection of the original radar signal off the targets, the "skin return" or "skin reflection", making it impossible to pick out the target on the radar display. This technique is only useful against radars that broadcast on a single frequency, and can be countered by changing the frequency or other operational parameters like the pulse repetition frequency (PRF) so the jammer is no longer broadcasting on the same frequency or at the right times. While multiple jammers could possibly jam a range of frequencies, this would consume many resources and be of little effect against modern frequency-agile radars that constantly change their broadcasts.
- Barrage tekniğinde merkez frekans belirtilir. Sağında ve solunda belirtilen aralıkta aynı anda karıştırma yapılır. Açıklaması şöyle
Barrage jammers attempt to overwhelm the radar receiver with an interfering signal in the received frequency band.
Bu yöntemde jammer'ın gücü azalır. Açıklaması şöyle
Barrage jamming is the jamming of multiple frequencies at once by a single jammer. The main drawback of this technique is that the jammer spreads it’s power across multiple frequencies, making it comparatively less powerful at a single frequency.
- Sweep tekniğinde belirtilen iki frekans arasında hızlıca atlayarak karıştırma yapılır. Açıklaması şöyle
Sweep jamming is the process of shifting a jammer’s full power from one frequency to another. This “sweeping” motion jams multiple frequencies in quick succession, although not all at the same time. 
1.2.2. False Target Generation
Açıklaması şöyle
Deceptive jammers use either a repeater or a memory to produce a replica of a radar return with appropriate modifications in time or frequency. Repeater jammers modify and retransmit received radar signals so the resulting echo relays inaccurate position.
Uygulayabileceği aldatma teknikleri şu şekilde tasnif edilebilir
- False Target (Sahte Hedef)
- Rage Gate Pull In (Mesafe Kapısı Çekme)
- Rage Gate Pull Off (Mesafe Kapısı İtme)
- Velocity Gate Pull In (Hız Kapısı Çekme)
- Velocity Gate Pull Off (Hız Kapısı İtme)
- Cross Polarization (Çapraz Polarizasyon)
- Cross Eye (Şaşı Göz)
- Blinking Jamming (Dönüşümlü Karıştırma)
1.2.3 Radar burn-through
Açıklaması şöyle. Jammer'a rağmen artık hedeften geri yansıyan sinyalin gizlenemediği yani radarın baskı altına alınamadığı mesafedir.
The burn-through range is the distance from the radar at which the jamming is ineffective. When a target is within this range, the radar receives an adequate target skin return to track it. 
1.2.4 Look Through - Ara Bakış
Elektronik Taarruz sistemi belli aralıklarla susarak, Elektronik Destek sisteminin karşı tarafı tekrar dinleyebilmesine izin verir.

1.2. Muhabere Elektronik Taarruz
Açıklama yaz

1.3. Decoy Sistemleri
Decoy (Türkçesi yem) kelimesinin açıklaması şöyle
Decoy, deceptive device used to draw an enemy away from a more important target.
Decoy Sistemleri platformun dışında çalışırlar. Bunlar şöyle olabilir
- Radar Decoy
- Towed RF Decoy (Çekili RF Dekoy)
- Air Launched Cruise Decoy
- Floating RF Decoy (Yüzer Dekoy)
- Disposable(Expendable) RF Decoy (Sarfedilebilir Aktif RF Dekoy)
 Towed Decoy
Açıklaması şöyle. Uçaklar tarafından kullanılır. RF güdümlü füzeleri üzerine çeker.
One method of defeating radar-guided missile attacks is to tow a decoy behind the host aircraft that is a more attractive radar target than the aircraft itself, so that the attacking missile chooses the towed decoy as opposed to the aircraft. 
Modern towed decoy sistemleri fiber-optik kablo ile uçağa bağlıdır ve uçaktan kumanda edilerek farklı tehditlere cevap verebilir.

Floating Decoy
Açıklaması şöyle. Gemiler tarafından kullanılır. RF güdümlü füzeleri üzerine çeker.
A ship having identifiable radar hot spots along its length is protected against radar homing missile attack by a floating decoy, which may be towed. The decoy has a plurality of radar return signal generators spaced along its length, with the amplitudes and spacing of the generators emulating the amplitudes and spacing of the hot spots. The homing missile is seduced away from the ship and toward the decoy.
Disposable RF Decoy
Açıklaması şöyle
Disposable decoys (also known as expendable decoys) are very small RF jamming devices that can be released by aircraft. Essentially, they are the mixture of ECM pod and chaff, they are released like chaff but operate like an ECM pod. Early generation of expandable decoy only consist of simple TWT and repeater, letting them retransmit signal with more power to appear like more attractive target, but modern expandable decoy such as Brite cloud are equipped with DRFM, thus allowing them to use many complex jamming techniques that traditionally only used by dedicate jamming systems.

7 Ekim 2020 Çarşamba

Graph Database

Giriş 
Graph database olarak Neo4j sıkça duyulan bir isim. OrientDB de bir graph database olarak kullanılabiliyor.

Graph Database İçinde Supernodes (Celebrity Nodes)
Açıklaması şöyle
A supernode is a node in a graph dataset with unusually high amounts of incoming or outgoing edges. 
Supernode'lar tıkanma noktaları oluşturduklarından için bunları daha rahat yönetmek için temel iki yöntem var. Bunlar şöyle
Option 1: Splitting Up Supernodes
Option 2: Vertex-Centric Indexes
Splitting Up Supernodes
Sharding işlemine benzer. 

Vertex-Centric Indexes
Supernode'a bağlı vertex'leri teker teker dolaşmak yerine bir indeks kullanarak hızlı erişilebilir hale getirmek

Graph İşlerini Relational Database İle Halletmek
Eğer Graph Database kullanamıyorsak ve elimizde sadece Relational Database varsa, bir graph yapısını taklit etmek mümkün. Bunun için 3 tane yol var. Açıklaması şöyle. PostgreSQL için LTREE Extension kullanılabilir
1. Adjacency list: each element has a reference to its immediate parent; root elements have a null parent. To find all descendants of a particular element, one needs to use "WITH RECURSION"-like clause. However, the clause is not supported in Spring Data JPQL. Other options, like @OneToManyself-reference or @NamedEntityGraphs annotations, either make too many separate SELECT calls or don't work recursively (see this post of Juan Vimberg for details). So this approach alone is not enough for our requirements, but let's keep it in mind.

2. Enumerated path (AKA materialized path): every element keeps the information about all its ancestors. For example, if the node with id=n3 has its parent id=n2 and its grandparent id=n1, then n3 has a string "n1.n2.n3", where "." is a delimiter. To naively find all descendants of a node n3, for example, we need to do a SELECT call with LIKE "n1.n2.n3.%". This is an extremely costly operation because we need to scan the whole table of comments and it takes a long time to compare strings. This approach will do, but we need a faster index. 

3. Nested sets & nested intervals: every node has two numbers - left and right; the numbers make up an interval. All descendants of this node have their intervals within their ancestor's intervals. This data structure allows us to find all descendants very quickly, but makes inserts and deletes extremely slow (see this post for details and this post for benchmarks). So, this approach on its own is not enough for us either, but it gives a valuable clue on how to index our data.
Materialized Path
Açıklaması şöyle. Hiyerarşik veriyi ilişkisel veri tabanında saklamayı sağlar.
Materialized paths allow you to "project" three-dimensional datasets (graph objects) into a fundamentally two-dimensional data structure (tables) without losing data 
Örnek
Elimizde şöyle bir tablo olsun
Name – humanoids
Path – /animals/mammals/primates/humanoid
IsGroup – false
Path alanında tutulan veri hiyerarşik ve şöyle
/animals/mammal/primates/humanoids
/animals/mammal/primates/chimpanzees
/animals/birds/parrots
Açıklaması şöyle
Now, if we need to count all species in our single table database that are of type mammals, we can easily accomplish that using the following SQL:
Şöyle yaparız
select count(*) from species where path like '/animals/mammals/%' and IsGroup=false
Açıklaması şöyle
Flipping the above IsGroup value to true returns all groups of species beneath mammals.
Örnek
Elimizde şöyle bir tablo olsunn
The table has columns:

- name (varchar)
- location_type (int) enum values: (1,2,3)
- ancestry (varchar)

id name ancestry
1 root null
5 node '1'
12 node '1/5'
22 leaf '1/5/12'
Parent nesnesi olanları bulmak için şöyle yaparız
SELECT * FROM geolocations
WHERE EXISTS (
   SELECT 1 FROM geolocations g2
   WHERE g2.ancestry = 
      CONCAT(geolocations.ancestry, '/', geolocations.id)
)

Scaled Agile Framework (SAFe)

Giriş
Yazıya başlamadan önce içimden "Yet Another Process Framework" demek geliyor. Youtube nasıl "Useless Marshall Arts" videoları ile doluysa bu framework te benim gözümde aynı.

Neyse : ) Yine de notlarımızı alalım. 

Mission Driven Development yöntemi SAFe'ten daha hafif olduğunu iddia ediyor

SAFe Nedir?
Açıklaması şöyle. Yani çevik prensiplerin (agile principles) büyük şirketlerde daha fazla ölçeklenerek (scale up) tüm kurum seviyesinde kullanılmasını amaçlıyor.
SAFe is a framework that explains an approach for scaling agile for working in larger enterprises and bigger teams, working on the same or multiple products.
Tarihçesi
Açıklaması şöyle
SAFe was first developed in the field and was elaborated in Dean Leffingwell's books and blog. Version 1.0 is the first official release in 2011. 
Aslında kısa bir geçmişi olmasına rağmen hızlı bir şekilde güncellenerek sürüm atlamış. Ben bu yazıyı yazarken 5. sürüme gelmişler. Açıklaması şöyle
Starting at its first release in 2011 already five major versions have been released[10] while the latest edition, version 5.0, was released in January 2020.
Safe Konfigürasyon Türleri
Bunlar şöyle
- Essential SAFe
- Large Solution SAFe
- Portfolio SAFe
- Full SAFe

Agile Release Train (ART)
Konfigürasyon Türlerini anlamadan önce ART'yi anlamak gerekir. Açıklaması şöyle.  Tüm tüm takımların aynı anda başlaması ve aynı anda release vermesi anlamına geliyor.
Synchronizing deliverables
Agile frameworks are designed to enable the development team to be autonomous and free to design how they work. SAFe acknowledges that, at the scale of many tens or hundreds of development teams, it becomes increasingly chaotic for teams to fully self-organize.It therefore puts some constraints on this, so that where teams are working on the same product, their deliverables can be better synchronized for releasing together, although this has been one area in which SAFe has been criticized.
Roller Nelerdir?
Agile Release Train, Program seviyesinde düşünülüyor. Bu seviye için de 3 tane rol düşünülmüş. Açıklaması şöyle. Bu roller Product Manager, System Architect ve Release Train Engineer
SAFe collects small product teams (often Scrum teams) into “Agile Release Trains” — groups of teams with an additional layer of management roles spanning each group at what is called the “Program level”.
Generally these roles impede the autonomy of teams. They add process and communication overhead out of proportion with the value they provide.
These roles include a Product Manager (PM), a System Architect (SA), and a Release Train Engineer (RTE).
Bir başka açıklama şöyle
What Are the Different Roles in a SAFe Framework? 
SAFe Scrum Master (SSM)
You might know that a traditional Scrum Master concentrates on the basics of a team-level Scrum. In contrast, when it comes to the SAFe Scrum Master, he is entitled to look into the intricacies of the entire organization and then strategize and execute around the Program Increment. 

SAFe Product Owner (POPM)
The SAFe Product Owner is a multi-tasker responsible for budgeting, defining the priorities, and determining the workflow.  

SAFe Advanced Scrum Master
The Advanced Scrum Master with Scaled agile framework is a senior to the SAFe Scrum Master. He is responsible for assisting in interactions with the product management team, architects, and other project stakeholders at the enterprise level.  

SAFe Agilist (SA)
An Agilist is a lean-thinking manager who introduces and implements the principles and values of the Lean-Agile Mindset. The Scaled agile framework agilist is primarily responsible for creating and leading efficient teams throughout the agile framework implementation roadmap.

Release Train Engineer (RTE) 
The Release Train Engineer is another essential individual responsible for applying their Lean-Agile knowledge to deliver the final product value. 
Product Manager Ne Yapar
Açıklaması şöyle.
The SA and PM define and break up larger pieces of work (often inherited from the portfolio process above) and then pass the pieces into the teams.
Release Train Engineer Ne Yapar
Açıklaması şöyle.
Release Train Engineers define consistent cross-team process and cadence, and handle many operational tasks. 
Large Solution SAFe Konfigürasyonu
Açıklaması şöyle. Yani program seviyesinden de büyük bir süreç
...groups of groups of teams with analogous roles to those at the program level, but spanning Release Trains.
Allowing time for innovation
Sanırım SAFe'teki tek hoşuma giden şey bu. 1 hafta (veya artık ne kadarsa) öğrenme için vakit ayrılması. Açıklaması şöyle.
The SAFe planning cycle recommends including an additional iteration after a release, so that teams can improve their practices and are ready for the next planning increment. 
SAFe Agile Değil Eleştirisi
SAFe bürokratik, fazlasıyla karmaşık, planlamaya fazla önem veriyor ve değer katan şeyleri değil, planları öne çıkarıyor eleştirileri var. 

Ancak bence asıl önemli şey, SAFe'in kullanmayı düşündüğü diğer çevik süreçleri de bozduğu eleştirisi
Takımların kendini organize eden (self organizing), bağımsız (autonomous) ekipler yerine, yukarıdan yönetilen ekipleri öne çıkarıyor eleştirisi zaten en vurucu nokta.


5 Ekim 2020 Pazartesi

Domain Driven Design - Anemic Domain Model

Giriş
Bu konuyu ilk olarak burada gördüm. Bu konuda vurgulanan şey Bounded Context içindeki modelin hiç bir logic içermemesi. Normalde beklenen şey şöyle.
The Domain Model should be useful for the problem we're trying to solve. The model is there to enforce the business rules that we have ...
Örnek
Elimizde şöyle bir Spring servisi olsun.
@Service
public class ExpenseService {
  private ExpenseRepo expenseRepo;
  private AuthenticationBO authenticationBO;
  ...
  // other injected classes

  @Override
  @Transactional
  public void createExpense(ExpenseDTO expenseDTO) throws ValidationException {
    validateExpense(expenseDTO);
    ExpenseEntity expenseEntity = new ExpenseEntity();
    initExpenseEntity(expenseEntity, expenseDTO);
    expenseRepo.save(expenseEntity);
  }

  ...
  // other methods
  private void initExpenseEntity(ExpenseEntity expenseEntity, ExpenseDTO expenseDTO) {
    UserEntity userEntity = authenticationBO.getLoggedUser();
    expenseEntity.setUser(userEntity);
    expenseEntity.setPrice(expenseDTO.getPrice());
    expenseEntity.setComment(expenseDTO.getComment());
    expenseEntity.setDate(LocalDateTime.now());
    initExpenseTypes(expenseEntity, expenseDTO.getTypes());
  }
  ...
  // other methods
}
Bu kodda domain nesnesi sadece getter/setter'lardan oluştuğu için anemic kabul ediliyor. Zararı şöyle
Official Spring tutorials teach us that domain objects shouldn’t have any methods except getters and setters and they should be POJOs. Many authors (like Martin Fowler) consider it an antipattern and call it the Anemic Domain Model.

With Anemic Domain Design, all a program’s logic is kept in the business logic layer (classes with Service or BO suffixes). Then domain objects don’t have methods that operate with class fields, hence the object doesn’t have behavior. That breaks OOP principles, GRASP patterns, and prevent us from implementing design patterns.
Bu kodu zengin alan modeli (rich domain model) kapsamında şu hale getirebiliriz. Bu sefer de @Entity nesnesi içine Repository eklemek zorunda kaldık. Bence bu da iyi değil
@Entity
public class ExpenseEntity {
  ...
  @Autowired // model has dependency from other layers and from infrastructure
  private ExpenseRepo expenseRepo;
  @Autowired
  private AuthenticationBO authenticationBO;
  @Autowired
  private UserRepo userRepo;
  ...
  @Transactional
  public void createExpense(ExpenseDTO expenseDTO) {
    // model does too much!
    validateExpense(expenseDTO);
    ExpenseEntity expenseEntity = new ExpenseEntity();
    initExpenseEntity(expenseEntity, expenseDTO);
    expenseRepo.save(expenseEntity);
  }
  private void initExpenseEntity(ExpenseEntity expenseEntity, ExpenseDTO expenseDTO) {
    UserEntity userEntity = authenticationBO.getLoggedUser();
    expenseEntity.setUser(userEntity);
    ...
    initExpenseTypes(expenseEntity, expenseDTO.getTypes());
  }
  private void initExpenseTypes(ExpenseEntity expenseEntity, List<String> types) {
    // model persists to a DB other objects!
    List<ExpenseTypeDictEntity> expenseTypes = new ArrayList<>();
    types.forEach(x -> {
      ExpenseTypeDictEntity typeDict = expenseTypeDictRepo
        .findByNameIgnoreCase(x.trim())
        .orElseGet(() -> createExpenseTypeDict(x));
       ...
    });
    expenseEntity.setExpenseTypeDict(expenseTypes);
  }
  private ExpenseTypeDictEntity createExpenseTypeDict(String name) {...}
}
Bu kodun şu akışa uygun hale gelmesi gerekir.
Böylece alan nesneleri ile JPA teknolojisi birbirinden ayrılabilir. Yani basit bir kural olarak alan modeli teknolojiden bağımsız olmalıdır. Açıklaması şöyle.
The business logic pertaining to the Product class can exist within the class itself and the business logic for the domain can be tested in isolation. The Product class contains data fields and these can be persisted to a database. As part of that process the data fields are first wrapped in another class, and then transformed into a JPA entity before being persisted. 
Örnek
Yine sadece Spring servisleri kullanan bir başka örnek şöyle
@Transactional
public void clearBills(Long customerId) {
  // Get bills needed for clearing
  ClearContext context = getClearContext(customerId);
  // Verify that the amount is legal
  checkAmount(context);
  // Determine whether coupons are available and return the deductible amount
  CouponDeductibleResponse deductibleResponse = couponDeducted(context);
  // clear all bills
  DepositClearResponse response = clearBills(context);
  // Send repayment reconciliation message
  repaymentService.sendVerifyBillMessage(customerId, context.getDeposit());
  // Update account balance
  accountService.clear(context, response);
  // Dealing with cleared coupons, used up or unbound
  couponService.clear(deductibleResponse);
  // Save coupon deduction records
  clearCouponDeductService.add(context, deductibleResponse);
}
Örnek - Anemic Mesajlaşma Sistemi
Bir mesajlaşma yazılımını güncellerken şöyle bir durumla karşılaştım. Güncellediğimiz yazılım, mesajlar arasında graph tarzı ilişkiler tutuyordu. Mesajlar ara katman yazılımından gelen ve behaviour içermeyen, sadece veri içeren nesnelerdi.

Mesajları çeşitli durumlara göre sıralayan (örneğin öncelik) bir servis katmanı da yoktu.

Dolayısıyla domain sadece getter/setter'lardan oluşan data nesnelerinin graph'ından ibaretti.

Örnek - Anemic İstek (Request) Sistemi
Bir  yazılım, çeşitli istekler gönderiyordu. Bu istekler bir ICD mesajında tanımlıydı. Ancak istekleri sarmalayan bir domain nesnesi yoktu. Gönderilen istekler farklı listelerde saklanıyordu. Mesela sentList, acceptedList, deniedList gibi. Gelen cevaba göre istek farklı listeye taşınıyordu. Bir zaman sonra farklı bir liste daha eklenmesi gerekti. Bu liste notHitList yani işlenen ancak istenilen sonucun alınamadığı bir listeydi. Kod çorbaya döndü.

Domain anemic olmasaydı, Request nesnesi diye bir şey olurdu. Bu nesnenin status diye bir alanı olurdu. Bu alan tüm listelerin bir enum'u şeklinde olurdu. Yeni liste eklemek yerine yeni enum eklenir ve elimizde tek bir liste olurdu

Aslında her gönderilen istek bir Request içinde saklansa