28 Kasım 2019 Perşembe

Redundancy - Yedeklilik

Giriş
Türkçesi yedeklilik. Redundancy Fault Tolerance- Arızaya Dayanıklılık için kullanılabilecek yöntemlerden bir tanesi.

1. Failover - Yedeğe Geçiş
Ana ve yedek olmak üzere iki sistem bulunur. Ana sistem arızalanınca yedeğe geçiş (failover) gerçekleşir. Failover'ı tesbit ederken Split Brain Scenario problemine dikkat etmek gerekir.

SSS maddesi şöyle olabilir.
System shall run on two identical servers for redundancy.
2. Triple Modular Redundancy
Açıklaması şöyle.
Also known as Triple Mode Redundancy (or TMR), this is a form of redundancy where three systems perform the same process and their results are checked by a majority voting system that in turn, produces a single output (see next image). If one of the three systems fails, then the other two will correct it by providing the accurate output to the voting system.
3. Aynı Yazılımın Farklı Donanım İle Yedeklenmesi
Aviyonik Dünyasında şöyle bir yaklaşım var.
Redundancy is not only achieved by multiplying the computers, but also by diversifying them. On Airbus airliners, two different computers are used (one with Intel chips, the other with Motorola chips in case of the A320) and software is written twice, one for control, the other for monitoring, by two teams which are not allowed to interact.
Airbus'ta hayata geçirilmesi şöyle
Despite the nonrecurring costs induced by dissimilarity, it is fundamental that the five computers all be of different natures to avoid common mode failures. These failures could lead to the total loss of the electrical flight control system. Consequently, two types of computers may be distinguished:
2 ELAC (elevator and aileron computers) and 3 SEC (spoiler and elevator computers) on A320/A321 and,
3 FCPC (flight control primary computers) and 2 FCSC (flight control secondary computers) on A330/A340.
Taking the 320 as an example, the ELACs are produced by Thomson-CSF around 68010 microprocessors and the SECs are produced in cooperation by SFENA/Aerospatiale with a hardware based on the 80186 microprocessor. We therefore have two different design and manufacturing teams with different microprocessors (and associated circuits), different computer architectures, and different functional specifications. At the software level, the architecture of the system leads to the use of four software packages (ELAC control channel, ELAC monitor channel, SEC control channel, and SEC monitor channel) when, functionally, one would suffice.
4. Forward Error Correction
Mesajlaşma protokollerinde kullanılır. Açıklaması şöyle.
Forward Error Correction (or FEC) adds redundancy into the message itself, that way the receiver can verify the actual data and correct a limited amount of errors detected due to noisy or unstable channels.
Redundancy Olarak Çift Motor
Açıklaması şöyle.
In aeronautics, redundancy is of primary concern. Having at least two engines is common for civilian aircraft.
Redundancy Olarak RAID Disk
RAID Disk yazısına taşıdım

20 Kasım 2019 Çarşamba

GoF - Observer Örüntüsü

Giriş
GoF kitabından Observable nesnesine Subject deniliyor ancak ben bu yazıda Java'daki gibi Observer ve Observable isimlendirmesini kullanacağım.

Observer en temel tasarım örüntülerinden bir tanesi. Değişen nesne, değişikliğini diğerlerine haber verir. En basit kullanım şeklinde, Observer ve Observable aynı thread üzerinde çalışırlar.

Esneklik
Observer örüntüsünün en sevdiğim tarafı bağımlılıkların sıralamasının kolayca değiştirme imkanı tanıması. Elimizde şöyle bir bağımlılık yapısı olsun. Bu bağımlılık aynı zamanda yazılımdaki akışı da belitir.
A - feed -> B <- observe - C
A bileşeni B'yi besler. C ise B'yi izler.

Eğer D isimli yeni bir işlem tipi daha gelirse D de kolaylıkla B'ye abone olabilir. Böylece akışı değşitirmek kolaylaşır.
A - feed -> B <- observe - D -> call C
Fix Everything Yöntemi
Observer tetiklenince idempotent olarak tabi edilen ve herşeyi baştan yapan bir metod çağırır. Idempotency Nedir yazısına taşıdım

Diğer
1. Observer işlevini gören sınıfa Processor, Controller (!) gibi isimler verildiğini gördüm. Proje içinde tutarlı bir isimlendirme yapmak gerekir.

2. Observer ile Reactive Programming birbirleri ile ilintili.

AntiPattern
Antipattern bir probleme bulunan faydasız hatta zararlı çözümdür.

Örnek
Bir projede Observable kendisine takılı Observer'ları bir başka thread içinde yani arka planda tetikliyordu. Bu debug etmeyi inanılmaz zorlaştırıyor. Observer kendisine gelen çağrıyı yine kendisi karar vererek arka plandaki bir başka thread içinde işlemeye karar vermeli. Bu kararın Observable nesnesine bırakılması bence doğru değil!

Java
Observable Sınıfı yazısına taşıdım.

C#
GoF - Observer Örüntüsü yazısına taşıdım.

State Notification Örüntüsü
Observer ile yakından ilgili bir başka örüntü StateNotification. Observer'dan farkı, olay oluştuktan sonra bile yeni eklenen Observer'ın tetiklenebilmesi.
Örnek
En kolay örnek javascript'teki ready() metodu. Açıklaması şöyle. Bu metod doküman yüklendikten sonra bile aşağıdaki kodu çalıştırınca tetikleniyor.
That depends upon whether it is really an Event or State Notification (which is what ready is). If it is an event, then you don't tell the listener about all prior events. If it is State Notification, then you tell them immediately after they have subscribed and you are in the specified state.
Şöyle yaparız.
$(document).ready(function () {
    console.log("Works.");
});


Renk Uzayı - HSV (HSB)

Giriş
HSV (Hue, Saturation, Value) anlamına gelir. Açıklaması şöyle. Yani HSV değerleri ile oynayınca RGB değerlerinin bir kaç tanesi değişir.
The HSB model is also known as HSV (Hue, Saturation, Value) model. The HSV model was created in 1978 by Alvy Ray Smith . It is a nonlinear transformation of the RGB color space. In other words, color is not defined as a simple combination (addition/substraction) of primary colors but as a mathematical transformation.
Hue : Renk tonu. Ana rengi belirtir.

Saturation : Rengin doygunluğudur. Hue rengine katılan beyaz ışıktır. Bu değeri yüzde olarak vermek daha kolay. 100% değeri en doygun renk anlamına gelir.  Doygun renkler daha canlı görünürler ve göze daha çok batarlar.
Doygunluk azaldıkça renk grileşir

Value/Brigtness : Aynı zamanda Brigtness olarak ta bilinir. Parlaklık. Bu değeri yüzde olarak daha kolay. Bu değer 0 ise renk siyahtır.
Şeklen şöyle. Burada ufak bir sorun var. V değeri 0.5 olmasına rağmen sağdaki dik çubuktaki beyaz nokta dikey olarak tam ortaya gelmiyor.



Hue Değerine Göre Sıralamak
Hue - yani renk tonuna göre - sıralamak gökkuşağını elde etmek için kullanılabilir.

Açıklaması şöyle.
HSV (also known as HSB) is a color model that transforms RGB colors to make them easier to manipulate and reason with. An HSV color consists of three components, in the following order:

- Hue is an angle from red at 0 to yellow to green to cyan to blue to magenta to red.(7)
- A component called "saturation", the distance of the color from gray and white (but not necessarily from black), is 0 or greater and 1 or less.
- A component variously called "value" or "brightness" is the distance of the color from black and is 0 or greater and 1 or less.
Örnek
Farklı String nesnelerine farklı HSV rengi üretmek için şöyle yaparız.
1. String.hashCode() ile hashCode bulunur.
2. hashCode / (float)X yapılarak hue değeri hesaplanır
3. hashCode / Integer.MAX_VALUE ile (0.0 - 1.0) arasında saturation hesaplanır. Gerekirse saturation belli bir aralıkta olacak şekilde alt ve üst sınır da verilebilir.
4. Brigtness hep 0.9 verilir.
Örnek
Android'de Color.colorToHSV () metodu ile ARGB'den HSV'ye geçiş yapılabilir.

Örnek
Java'da şöyle yaparız.
final float hue = random.nextFloat();
// Saturation between 0.1 and 0.3
final float saturation = (random.nextInt(2000) + 1000) / 10000f;
final float luminance = 0.9f;
final Color color = Color.getHSBColor(hue, saturation, luminance);
- Hue değeri herhangi bir float sayı olabilir.

- Saturation 0.0 ve 1.0 arasında değer alır. Rengin parlaklığıdır. Bu değer 1 ise renkler çok parlak görünür. 0.1 ve 0.3 arasındaki değerler göze daha rahat hitap eden renkler verirler.

- Value 0 is renk siyahtır. 0.9 değeri göze daha rahat hitap eden renkler verirler.


15 Kasım 2019 Cuma

GoF- Chain of Responsibility Örüntüsü

Giriş
Not : GoF Tasarım Örüntüleri yazısına bakabilirsiniz.

Chain of Responsibility - Davranışsal Örüntü
Bu örüntü genellikle statik bir zincir şeklinde kullanılır. Ancak dinamik bir zincir kurulması da mümkün. Transformation, filter gibi işlemler için ideal bir çözümdür.

Zincir kurarken her halka bir sonraki halkayı çağırabilir veya bir Facade yardımıyla halkaların çağrılması sağlanabilir. Örneğin Loglama çatılarındaki loglama işlemi bir çok Appender sınıfının bir Facade tarafından çağrılması şeklindedir.

Zincir Mekanizması
Herhangi bir mekanizma kullanılabilir. En kolay bir arayüzü çağrı ile tetiklemek. QT'deki signal/slot bile kullanılabilir.

Diğer Seçenekler
Zincir yerine "Parameter Object" kullanılabilir.


11 Kasım 2019 Pazartesi

SDD Kontrol Listesi - CheckList

SDD Gözden Geçirilirken Nelere Dikkat Edilir?
Clarity, Completeness, Compliance, Consistency, Correctness, Interfaces, Maintainability, Performance, Reliability, Testability, Traceability gibi bir çok etmene bakılabilir.

Peki bunlarla ne kastediliyor. Açıklaması şöyle.
Simplicity -- the design must be simple, both in implementation and interface. It is more important for the interface to be simple than the implementation.

Correctness -- the design must be correct in all observable aspects. Incorrectness is simply not allowed.

Consistency -- the design must not be inconsistent. A design is allowed to be slightly less simple and less complete to avoid inconsistency. Consistency is as important as correctness.

Completeness -- the design must cover as many important situations as is practical. All reasonably expected cases must be covered. Simplicity is not allowed to overly reduce completeness.
Bu prensiplerden biraz taviz verilirse karşımıza şu çıkar.
The worse-is-better philosophy is only slightly different:

Simplicity -- the design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.

Correctness -- the design must be correct in all observable aspects. It is slightly better to be simple than correct.

Consistency -- the design must not be overly inconsistent. Consistency can be sacrificed for simplicity in some cases, but it is better to drop those parts of the design that deal with less common circumstances than to introduce either implementational complexity or inconsistency.

Completeness -- the design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must be sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.
SDD Gözden Geçirmelerinde Sıkça Karşılaşılan Problemler
Doküman genelinde kullanılan kısaltmaların Acronyms listesinde olmaması. Gözden geçirenler arasında QA ve Sistem Mühendisinin olmaması.

Functional Programming Pure Function - Yan Etkisi Yoktur ve Aynı Girdi İçin Aynı Sonucu Verir

Giriş
Açıklaması şöyle. Yani yan Etkisi Yoktur ve Aynı Girdi İçin Aynı Sonucu Verir
Most sources define a pure function as having the following two properties:
- Its return value is the same for the same arguments.
- Its evaluation has no side effects.
Önemli Not
Object Oriented programlamaya alışkın olanların itirazı şöyle
“This is puristic nonsense!” you say. “Intellectual masturbation! Software should be modeled after real-world, mutable objects!”
Functional programlamaya alışkın olanların itirazı da şöyle. Çünkü OO şeklinde yazılan bazı kodlar gerçekten çok büyük ve anlaması zor olabiliyor.
You shouldn't need several hours to understand what a method, class, or package does. If you need a lot of mental effort to even start programming, you will run out of energy before you can produce quality. Reduce the cognitive load of your code and you will reduce its amount of bugs.
Aslında Functional veya Object Oriented programlamadan sadece birisini tercih etmek zorunda değiliz. Bu ikisi kolayca bir arada kullanılabiliyor.

Functinal Programming bize öncelikle kodu işlevsel daha küçük parçalara bölme imkanı veriyor. Buna "Partitioning by Functionality" veya "Breaking It Up Into Composable Units" diyebiliriz. Bu bölümleme esnasında yukarıdaki 2 kurala da uyunca anlaması, okuması ve test etmesi daha kolay kodlar ortaya çıkıyor

Pure Function Örnekleri
Örnek

Şöyle yaparız.
const add = (x, y) => x + y;

add(2, 4); // 6
Impure Function Örnekleri
Örnek
Şu kod impure çünkü harici state'ı değiştiriyor.
let x = 2;

const add = (y) => {
  return x += y;
};

add(4); // x === 6 (the first time)
add(4); // x === 10 (the second time)
Örnek
Şu kod impure çünkü harici state'i okuyor veya tutuyor.
const exchangeRate =  fetchFromDatabase(); // evaluates to say 0.9 for today;

const dollarToEuro = (x) => {
  return x * exchangeRate;
};

dollarToEuro(100) //90 today

dollarToEuro(100) //something else tomorrow
Bu kodu değiştirmek için şöyle yaparız.
const exchangeRate =  fetchFromDatabase(); // evaluates to say 0.9 for today;

const dollarToEuro = (x, exchangeRate) => {
  return x * exchangeRate;
};
2. Döngü
Functional dillerderde aşağıdaki gibi döngüler impure olarak kabul edilirler.
int as_int(char *str)
{
  int acc; /* accumulate the partial result */

  for (acc = 0; isdigit(*str); str++) {
    acc = acc * 10 + (*str - '0');
  }

  return acc;
}
Döngüler diğer metodlar kullanılarak yapılır.
int as_int(char *str)
{
  return fold(takeWhile(isdigit, str), 0, int function(char *chr, int acc) {
      return acc * 10 + (chr - '0');
    });
}

8 Kasım 2019 Cuma

GoF - Adapter Örüntüsü

Giriş
Adapter bir Yapısal Örüntüdür. Adapter iki standart arayüzü birbirine dönüştürmek için kullanılır. Burada dikkat edilmesi gereken kelime arayüz kelimesi. Örneğin VGA girişini DVI çıkışına çeviren fiziksel nesne de adaptördür. Adapter örüntüsü de fiziksel nesne ile aynı işlevi yapar.

Kavramlar
1. Target Interface - Client tarafından bilinen arayüzdür.
2. Adaptee Interface - Kullanılmak istenen ancak Target Interface'e uymayan arayüzdür
3. Adapter - Bizim yazdığımız kod. Adaptee nesnesini Target Interface ile uyumlu hale getirir.

Adapter Gerçekleştirimleri
Açıklaması şöyle. Tüm Adapter örüntüleri kalıtım kullanmak zorundadır.
The GoF lists three different approaches to design a Target API for adaptation. The first two are recognizable as a couple of their Behavioral design patterns.

1. Template Method
2. Strategy
3. Closures (what Smalltalk calls code blocks)
Template Method
Normalde Eğer Strategy kullanıyorsak Adapter sınıfımızın constructor metoduna belli bir tip geçmek gerekir. Yani bir adapter bir target ile çalışır. Ancak elimizde daha fazla target nesne varsa template kullanabiliriz.
Örnek
Şöyle yaparız. Burada amaç Point bekleyen metoda örneğin Line geçebilmek. GenericLineAdapter kullanarak hangi tipte Line olursa olsun onu Point bekleyen metoda geçebiliriz.
template<class T>
struct GenericLineAdapter : Point {
  T&      m_line;
  GenericLineAdapter(T &line) : m_line(line) {}
  void draw(){ m_line.draw(); }
};
Strategy
Bu örüntünün iki çeşidi olsa da her iki yöntemde de Adapter, ihtiyaç duyduğumuz Target arayüzünü gerçekleştirmek zorundadır.
- Eğer Target bir sınıf ise Adapter mecburen kalıtır.
- Eğer Target bir arayüz ise Adapter bu arayüzü gerçekleştirir.

1. Object Adapter Türevi - Composition
Adapter sınıfı Target arayüzünden kalıtır/gerçekleştirir ve verilen Adaptee nesnesini sarmalar. Yani klasik composition çözümü uygulanır. Eğer Target sınıfının gerçekleştirilmesi gereken çok sayıda metodu varsa, zor bir çözüm halini alabilir.

Örnek
Şöyle yaparız. Mevcut kod yani draw_point() metodu Point nesnesi alıyor. Ancak biz Line nesnesi kullanmak istiyoruz. LineAdapter ile bu iş halledilebilir.
struct Point {
  int32_t     m_x;
  virtual void draw(){ cout<<"Point\n"; }
};


struct Point2D : Point {
  int32_t     m_y;
  void draw(){ cout<<"Point2D\n"; }
};


void draw_point(Point &p) {
  p.draw();
}


struct Line {
  Point2D     m_start;
  Point2D     m_end;
  void draw(){ cout<<"Line\n"; }
};

struct LineAdapter : Point {
  Line&       m_line;
  LineAdapter(Line &line) : m_line(line) {}
  void draw(){ m_line.draw(); }
};

int main() {
  Line l;
  LineAdapter lineAdapter(l);
  draw_point(lineAdapter);
  return EXIT_SUCCESS;
}
1.1 Pluggable Adapter
Bu aslında Closure veya Functional Interfaces ile kurulan bir yapı. Açıklaması şöyle.
A distinguishing feature of pluggable adapters is that the name of a method called by the client and that existing in the ITarget interface can be different. The adapter must be able to handle the name change. In the previous adapter variations, this was true for all Adaptee methods, but the client had to use the names in the ITarget interface. (...)

The pluggable adapter sorts out which object is being plugged in at the time. Once a service has been plugged in and its methods have been assigned to the delegate objects, the association lasts until another set of methods is assigned. What characterizes a pluggable adapter is that it will have constructors for each of the types that it adapts. In each of them, it does the delegate assignments (one, or more than one if there are further methods for rerouting).
Bir başka açıklama şöyle
The pluggable adapter pattern is a technique for creating adapters that doesn't require making a new class for each adaptee interface you need to support.
Örnek
Elimizde şöyle bir kod olsun. Bu örnekte Composition kullanılıyor ancak Target arayüzün Estimate() metodunu kullanmak yerine yeni bir Request metodu tanımlanıyor. Request metodu istenirse Adaptee veya istenirse Target arayüzünü çağırabiliyor.
class Adaptee
{
  public double Precise(double a, double b)
  {
    ...;
  }
}

// New standard for requests
class Target
{
  public string Estimate(int i)
  {
    ...
  }
}    

// Implementing new requests via old
class Adapter : Adaptee
{
    public Func<int, string> Request;    
    // Different constructors for the expected targets/adaptees    
    // Adapter-Adaptee
    public Adapter(Adaptee adaptee)
    {
      // Set the delegate to the new standard
      Request = x => Math.Round(Precise(x, 3));
    }

    // Adapter-Target
    public Adapter(Target target)
    {
      // Set the delegate to the existing standard
      Request = target.Estimate;
    }
}
Kullanmak için şöyle yaparız.
Adapter adapter1 = new Adapter (new Adaptee(  ));
//Here, it will call the Adaptee's abstracted method. 
adapter1.Request(5);

//The only way to call the Target's method is to instantiate a new adapter with the
//target    
Adapter adapter2 = new Adapter (new Target(  ));
Console.WriteLine(adapter2.Request(5));
Örnek
Şöyle yaparız. Burada Adapter Beverage ile ilklendirilirse Beverage gibi davranır. Eğer JuiceMaker ile ilklendirilirse JuiveMaker gibi davranır.
/* Legacy code -------------------------------------------------------------- */
struct Beverage {
  virtual void getBeverage() = 0;
};

struct CoffeeMaker : Beverage {
  void Brew() { cout << "brewing coffee" << endl;}
  void getBeverage() { Brew(); }
};


void make_drink(Beverage &drink){
  drink.getBeverage();                // Interface already shipped & known to client
}

/* --------------------------------------------------------------------------- */
struct JuiceMaker {                     // Introduced later on
  void Squeeze() { cout << "making Juice" << endl; }
};

struct Adapter : Beverage {              // Making things compatible
  function<void()>    m_request;
  Adapter(CoffeeMaker* cm) { m_request = [cm] ( ) { cm->Brew(); }; }
  Adapter(JuiceMaker* jm) { m_request = [jm] ( ) { jm->Squeeze(); }; }
  void getBeverage() { m_request(); }

};

int main() {
  Adapter adp1(new CoffeeMaker());
  make_drink(adp1);
  Adapter adp2(new JuiceMaker());
  make_drink(adp2);
  return EXIT_SUCCESS;
}
2. Class Adapter - Multiple Inheritance
Adapter sınıfı Target ve Adaptee sınıflarından multiple inheritance kullanarak aynı anda kalıtır. C++ gibi diller tarafından kullanılabilen bir yöntem. Java gibi multiple inheritance desteklemeyen diller tarafından bu yöntem biraz değiştirilerek kullanılır.

Örnek
C# kodunda şöyle yaparız.
// Required standard for requests
interface ITarget {
  // Rough estimate required
  string Request (int i);
}


// Existing way requests are implemented
class Adaptee {

  // Provide full precision
  public double SpecificRequest (double a, double b) {
    ...;
  }
}


// Implementing the required standard via Adaptee
class Adapter : Adaptee, ITarget {

   public string Request (int i) {
    return "Rough estimate is " + (int) Math.Round(SpecificRequest (i,3));
  }
}

2.1 . Two Way Adapter
Two Way Adapter yazısına taşıdım.

Adapter'ın Hangi Mesajı Sarmaladığını Nasıl Anlarız
1. Adapter'a bir getAdapteeMessageType() metodu yazılır. Bu metoda bakarak gerçek nesneye cast edilir.


Örnek - Yanlış İsimlendirme
Normalde Adapter örüntüsü için iki tane farklı arayüz gerekir. Bunlar Adaptee ve Target Interface Elimizde Callback şeklinde Client'ı tetikleyen bir kod parçası vardı. Bu callback'lere bir filtre eklenmesi gerekti. Böylece Client her zaman tetiklenmeyecekti. Filtre koduna Adapter ismi verildi.

Filtre kodu EventSource'u ve IFilter nesnesini sarmaladı ve EventSource'a kendisi abone oldu. Gelen event'i süzdü ve gerekiyorsa Client'a verdi. Burada bir arayüzü diğerine çevirme olayı olmamasına rağmen sınıfa XFilterAdapter ismi verilmesi bence yanlıştı

Örnek - Doğru İsimlendirme
Elimizde iki tane mesaj seti vardı (A seti ve B seti) ve bu mesajlar farklı hiyererşilere sahipti. Client normalde A seti ile çalışıyordu ancak daha sonra B setine ne de çevirip farklı bir  sisteme de mesaj gönderme ihtiyacı çıktı. ABAdapter yazılarak A mesajını B mesajına çeviren ve gönderen bir sınıf yazıldı.

Diğer
Adapter,Decorator ve Facade davranış açısından bir başka nesneyi sarmaladıkları için birbirlerine benzerler. Açıklaması şöyle.
A decorator makes it possible to add or alter behavior of an interface at run-time. Alternatively, the adapter can be used when the wrapper must respect a particular interface and must support polymorphic behavior, and the Facade when an easier or simpler interface to an underlying object is desired
Adapter ve Decorator arasındaki fark nedir
Decorator arayüzü değiştirmez, sadece sınıfa yeni davranış ekler.

Facade ve Adapter arasındaki fark nedir?
Facade ise sadece kullanım kolaylığı için vardır. Arayüzler çok önemli değildir