29 Kasım 2018 Perşembe

SOLID - 2000'li Yıllarda Ortaya Çıkan Kodlama Seviyesi Kuralları

SOLID'den Önce
NotNesneye Yönelik Programlama Tarihçesi yazısına bakabilirsiniz

Klasik Nesneye Yönelimli Tasarımda (Object Oriented Design) 3 tane önemli ilke var. Bunlar
Encapsulation, Inheritance, Polymorphism (virtual methods)

Nesneye Yönelik Tasarımın bence en büyük etkisi daha karmaşık problemleri çözmek için soyutlama katmanları getirmesi olmuştur. Yani complexity, abstraction ile çözülmeye başlandı
If you look at the end of the "Lecture 3a: Henderson Escher Example" of SICP, Hal Abelson proposes that complexity is managed not by breaking the task into smaller subtasks, but by creating layers of abstraction. At the highest level, you express the solution to the complicated problem in terms of the the solution to the lower level of abstraction.
Ne Zaman Soyutlama Seviyesi Artırılır
Her şeyi parametre alan ve hiyerarşik sınıflar şeklinde tasarlamak belki mümkün. Ancak bu işe ne zaman kalkışmak lazım. Açıklaması şöyle. Buna The Rule of Three'de deniliyor. Yani aynı şeyi üçüncü kere yapıyorsak veya değiştiriyorsak bu kodu soyutlamak gerekir.
In other words, when a certain algorithm/pattern is being used for a third time, it should be abstracted so that it is reusable (= usable many times).
SOLID Niye Lazım
Çünkü yazılımlar değişmeye devam etmek zorundalar. Lehman Kanunu şöyle söyler
Now, in disciplined development, we use principles such as SOLID to attempt to reduce this problem. However, we are continually fighting Lehman's laws of two summarized general concerns:

1. systems need to continually add new functionality to stay relevant
2. new functionality increases complexity reducing ability to change the system
SOLID
SOLID nesneye yönelik tasarımdan çok sonraları, yani 2000'li yıllarda ortaya çıkan kurallar dizisi. Açıklaması şöyle
The SOLID principles were first conceptualized by Robert C. Martin in his 2000 paper, Design Principles and Design Patterns. These concepts were later built upon by Michael Feathers, who introduced us to the SOLID acronym.
SOLID prensibinde 5 tane kural var.

SOLID karmaşık problemleri çözmek için değildir. Kodlama seviyesindeki kurallardır.

Aslında Robert C. Martin yani Uncle Bob genellikle kodlama seviyesindeki şeylerle ilgili eserler vermiş. Clean Code kitabındaki bazı başlıklar şöyle

Mimari seviyedeki eseri ise şöyle

1. Single Responsibility Principle - Tek Sorumluluk Kuralı
Single Responsibility Principle yazısına taşıdım. Sınıfın Tek Bir Sorumluluk Olmalıdır

2. Open-Closed Kuralı
Open-Closed Kuralı yazısına taşıdım. Mevcut Kod Değiştirilmeden Kalıtım Yapılabilmelidir

3. Liskov Kuralı
Liskov Kuralı yazısına taşıdım. Kalıtım Varsa A ve B Yer Değiştirebilmelidir

4. Interface Segregation Kuralı
Interface Segregation Kuralı yazısına taşıdım. Küçük Arayüzler İyidir

5. Dependency Inversion Kuralı
Dependency Inversion Kuralı yazına taşıdım. Modüller Arasında Soyutlama Katmanı Olmalıdır



Calculus

Giriş
Calculus nedir sorusunun açıklaması şöyle
The three main points are:
  • Limits: How sequences and functions behave when getting closer and closer to a desired point (geometrically, what happens when you "zoom in" near a point)
  • Derivatives: How functions change over a parameter (geometrically, the "slope of a graph at a given point")
  • Integrals: What's the cumulative effect of a function (geometrically, the "area under a graph")
Sayının En Küçük Değeri
X en az 1000 olmalı diye belirtmek için şöyle yaparız.

Türev
Türev eğimi verir. Açıklaması şöyle
The value of the derivative is the slope of the tangent line. If the slope is positive the function is increasing, if negative the function is decreasing.
Türevin Türevi
Türevin türevi eğimi verir. Açıklaması şöyle
Since derivatives measure rates of change, one way to see whether the derivative itself is increasing or decreasing is to find its derivative: the second derivative of the original function. 
Türevin türevi her durumda concavity durumunu doğru bulmasa da  basittir. Açıklaması şöyle
So the real point is that using the 2nd derivative test to verify concavity is very useful:

- It is very simple to use;
- Cases where it does not work are rare (e.g. f(x)=x^4);
- Alternative methods are harder to apply.
L'Hopital Kuralı ve Limit
Pay ve payda aynı anda sonsuz veya sıfıra gidiyorsa bu kural uygulanır. Pay ve paydanın türevi alınarak limit hesaplanır. Açıklaması şöyle
One of the conditions of applying L'Hospital's Rule is that f′(x)/g′(x) must exist.
Basit bir açıklama ise şöyle.
Intuitively, you look at the degree of the numerator and denomiator. If the numerator has higher degree, it will flood out the denominator and tend to ∞. If the denominator has higher degree, the limit will be zero. If they have the same degree, all lower-degree terms will be relatively insignificant and the quotient tends to the ratio of the top-degree coefficients
Örnek
Dolayısıyla (5n^2) / (11n^2) n sonsuza giderken kural uygulanırsa = 5/11 çıkar.

Örnek
Şu örnekte L'Hopital kuralı sin fonksiyonu x sonsuza giderken +/-1 arasında dalgalandığı için uygulanamıyor.



Açıklaması şöyle
L'Hospital's Rule isn't working since the derivative of numerator function isn't determinable when x→∞, due to oscillatory behaviour of sinsin and coscos function. Therefore you have to approach traditionally.
Örnek
L'Hopital kuralı iki tane limi işlemi toplamasını birleştirmek için kullanılamaz. Her limit ayrı ayrı hesaplanır ve sonuç toplanır.

23 Kasım 2018 Cuma

Pusula Açısını Trigonometrik Açıya Çevirmek

Giriş
Pusula'nın başlangıç noktası ile trigonometrik başlangıç noktası farklıdır. Pusulada açılar saat yönünde artar, trigonometride ise saatin tersi yönde artar.

Trigonometriden Çevrim
Trigonometrik dereceyi pusulaya çevirmek için aşağıdaki formül kullanılabilir.
azimuth = (450 - angle) % 360
Pusuladan Çevrim
Pusula derecesini trigonometrik dereceye çevirmek için aşağıdaki formül kullanılabilir.
Örnek
Şöyle yaparız
angle = (90 - azimuth + 360) % 360
Örnek
Şöyle yaparız.
angle = (- azimuth + 90)
Burada soruda kuzeyi 0 kabul eden bir soru var



20 Kasım 2018 Salı

Basit Shape Sınıfı - Daire

Giriş
Dairede pisagor teoremi çokça kullanılır. Basit bir daire sınıfı şöyledir.
class Circle {

private:

  double radius;  // Radius of circle

public:

  // Default constructor
  Circle() {
    radius = 0.0;
  }
  // Set the radius of the circle
  void setRadius(double r) {
    radius = r;
  }
  // Get the radius of the circle
  double getRadius() {
    return radius;
  }
  // Calculate the area of the circle using current radius
  double area() {
    return(3.1416 * radius * radius);
  }
};
Açıyı Normalize Etmek
Şöyle yaparız. Burda modulo arithmetic yani mod 360 eksi sonuç verebilir. Bu yüzden + 360 yapılarak düzeltiliyor.
this.orientation += degrees;

this.orientation = this.orientation % 360;

if (this.orientation < 0)
{
    this.orientation += 360;
}
Açı Farkı
[0 - 360] aralığındaki iki açının farkını verir. Şöyle yaparız.
float angleDifference = fmod(angle1 - angle2 + 900f, 360f) - 180f;
Açının İki Açı Arasında Olduğuna Bakmak
Şöyle yaparız.
static bool isABetween(int testAngle, int startAngle, int endAngle) {
  int endAngleDifference = Math.floorMod (endAngle - startAngle, 360);
  int testAngleDifference  = Math.floorMod (testAngle - startAngle, 360);

  return testAngleDifference <= endAngleDifference;

}
Açıyı Artırmak ve Küçültmek
Şöyle yaparız.
class CircularNumber{

  private static final int BOUND = 360;
  private int heading;

  public void add(int amt){
    header = (heading + amt) % BOUND;
  }

  public void deduct(int amt){
    header = (360 + heading - (amt % BOUND)) % BOUND;
  }
}
Açıyı X ve Y'ye Çevirmek
Şöyle yaparız. Açının Cos() sonucu X, Sin() sonucuY değerini verir.

Bir Noktanın Daire İçinde Olduğunu Anlama
Örnek
Şöyle yaparız.
boolean isPointInCircle(int clickX, int clickY) {
  return (clickX - x) * (clickX - x) + (clickY - y) * (clickY - y) <= radius * radius;
}
Örnek
first dairenin merkezi , second ise nokta olsun.
boolean isPointInside(Point second) {
  return (first.Center.Distance(second) <= radius;
}

Bir Dairenin Başka Bir Dairenin İçinde Olduğunu Anlama - overlap
Collision Detection yazısına taşıdım

Daireyi Eşit Olarak Dilimlere Bölme
Şöyle yaparız. r radius'u temsil eder. Burada sağ yatay eksenden yani trigonometrik 0 değerinden başlanıyor ve saatin tersine doğru dönülüyor.
//x0, y0 - center's coordinates
for(i = 1 to n)
{
    angle = i * (360/n);
    point.x = x0 + r * cos(angle);
    point.y = y0 + r * sin(angle);
}
Eğer Trigonometrik 180 yani sol eksenden başlamak isteseydik ve yine saatin tersi yönünde dönmek isteseydik şöyle yaparız.
x0 -=  cos(...)
y0 += sin(...)
Dairenin İçindeki Tüm Noktaları Bulmak
x ve y değerlerini bulmak için şöyle yaparız. x [-r,+r] aralığında olacak şekilde döngü kurarız. x^2 + y^ 2 = r^2 denklemini y'yi çözecek şekilde y = sqrt (r^2 - x^2) haline getiririz. Sonucu tam sayıya çevirmek için floor kullanıırz.
for x in [-floor(r), floor(r)]
    y_max = floor(sqrt(r^2 - x^2))    # Pythagora's theorem
    for y in [-y_max, y_max]
        # (x, y) is good !