Aylık Arşiv: Ocak 2014

Refactoring 4: Geçici Değişkenlerin Sorguya Dönüştürülmesi (Replace Temp with Query)

Merhabalar.

Bu yazıda “replace temp with query”(geçici değişkenlerin sorguya dönüştürülmesi) yönteminden bahsetmeye çalışacağım.

Nedir?

double basePrice = _quantity * _itemPrice;

if (basePrice > 1000)

     return basePrice * 0.95;

else

     return basePrice * 0.98;

extractmethod

if (basePrice() > 1000)

     return basePrice() * 0.95;

else

     return basePrice() * 0.98;

...
double basePrice() {

     return _quantity * _itemPrice; }

Neden?

  • Global olmayan değişkenler geçici ve lokaldir. Bu zaman zaman kullanımı zorlaştırabilir. Örneğin tanımlandığı blok dışında kullanılamazlar.
  • Bilhassa uzun metodlarda değişkenleri sorgusal metodlara çevirmek faydalı bir yöntemdir.
  • Extract Method yöntemi öncesi, önemli bir adımdır.
  • Bu yöntemi değişkene tek bir değer(global değişkenler, hardcoded değerler vb.) tahsis edildiği durumlarda kullanmak gerekir. Değeri devamlı güncellenen bir değişkene uygulamak mümkün olsa bile uğraştırıcıdır.

Nasıl?

  • Bir kez atama yapılan değişkenlere bakılır. Java’da çalışıyorsanız bir kez atandığını garanti etmek için değişkenleri final yapabilirsiniz.
  • Değişkene atanan kısım alınır ve private bir metod tanımlanıp içine atılır.
  • Değişkenin kullanıldığı yerlerde yeni metod çağırılır ve değişken remove edilir.
  • Derleme ve test.

Örnek

Bir ürünün paket/koli fiyatını getiren bir metodumuz olsun. Paket fiyatına göre de indirimli fiyatı hesaplıyor.

Buradaki _miktar ve _adetFiyati global değişkenler.

double ucretGetir()
 {
      int paketFiyat = _miktar * _adetFiyati;
      double indirimOrani;

      if (paketFiyat > 1000) indirimOrani = 0.95;
      else indirimOrani = 0.98;

      return paketFiyat * indirimOrani;
 }

İlk etapta değişkenlerimizi final yaparak bir kez atama yapıldığını test edelim.

double ucretGetir()
 {
      final int paketFiyat = _miktar * _adetFiyati;
      final double indirimOrani;

      if (paketFiyat > 1000) indirimOrani = 0.95;
      else indirimOrani = 0.98;

      return paketFiyat * indirimOrani;
 }

paketFiyat hesaplamasını yeni bir metoda çıkarıyorum:

private int paketFiyat()
{
     return _miktar * _adetFiyati;
}

Değişkeni artık bu metoda eşitleyebilirim.

double ucretGetir()
 {
      final int paketFiyat = paketFiyat();
      final double indirimOrani;

      if (paketFiyat > 1000) indirimOrani = 0.95;
      else indirimOrani = 0.98;

      return paketFiyat * indirimOrani;
 }

Derleyip, test ediyoruz. Sonra asıl konumuz olan yöntemi uygulamaya başlıyoruz. Değişkeni kullandığım yerde direkt metodu çağırıyorum.

double ucretGetir()
 {
      final int paketFiyat = paketFiyat();
      final double indirimOrani;

      if (paketFiyat() > 1000) indirimOrani = 0.95;
      else indirimOrani = 0.98;

      return paketFiyat * indirimOrani;
 }

Derleyip, test ediyoruz. Daha sonra yerel değişkenimizi tamamen imha ediyoruz:

double ucretGetir()
 {
      final double indirimOrani;

      if (paketFiyat() > 1000) indirimOrani = 0.95;
      else indirimOrani = 0.98;

      return paketFiyat() * indirimOrani;
 }

Derleyip, test ediyoruz. Koda dikkatli baktığımızda indirimOrani için de aynı işlemleri uygulayabiliriz gibi gözüküyor. Bu defa biraz kestirmeden gidelim:

double ucretGetir()
 {
      final double indirimOrani = indirimOrani();

      return paketFiyat * indirimOrani;
 }

private int indirimOrani()
{
      if (paketFiyat() > 1000) return 0.95;
      else return 0.98;
}

..ve son yerel değişkenimizi de ortadan kaldırıyoruz:

double ucretGetir()
{
      return paketFiyat() * indirimOrani();
}

private int indirimOrani()
{
     if (paketFiyat() > 1000) return 0.95;
     else return 0.98;
}

private int paketFiyat()
{
     return paketFiyat * indirimOrani;
}

 

Kendinize çook iyi davranın.

Kaynak: http://sourcemaking.com/refactoring/replace-temp-with-query

 Bu sayfa 1093 kez görüntülendi

It's only fair to share...Share on LinkedInShare on FacebookShare on Google+Tweet about this on TwitterShare on Tumblr

Refactoring 3: Inline Method & Inline Temp

Merhabalar.

Refactoring yaparken, amaçlardan biri koddaki karmaşıklığı gidermek ve okunabilirliği sağlamaktır. Mesela bir önceki yöntemde tekrar eden veya okunurluğu zorlaştıran scriptleri ayrı metod haline getirmiştik.Ama metoda çevirme işinin, hatta değişken oluşturma işinin de abartılmamasında fayda var. Gereksiz yere bunların kullanımı da yine okunurluğu zorlaştırabilir. Buradaki 2 yöntem bu sıkıntıları gidermeye matuftur.

a – Inline Method

Nedir?

int getRating()
 {
      return (moreThanFiveLateDeliveries()) ? 2 : 1;
 }

boolean moreThanFiveLateDeliveries()
 {
      return _numberOfLateDeliveries > 5;
 }

extractmethod

int getRating()
 {
      return (_numberOfLateDeliveries > 5) ? 2 : 1;
 }

 

Neden?

  • Bir önceki yöntemde, kodun anlaşılmasının zor olduğu parçalar yerine; anlaşılır isimde, kısa metodlar yazılması öneriliyordu.
  • Ama herşeyin olduğu gibi metodun da gereksizi ve fazlası zarardır. Bu yüzden değişken kullanılabilecekken ve işi karmaşıklaştırmayacaksa, gereksiz yere metod kullanmak tavsiye edilmez.

Nasıl?

  • Metodun polimorfik olup olmadığı kontrol edilir.
  • Metodun çağrıldığı bütün yerler bulunur.
  • Metodun gövde kısmıyla, metodun çağırıldığı script değiştirilir.
  • Derleme ve test.
  • Metod remove edilir.

 

b – Inline Temp

Nedir?


double basePrice = anOrder.basePrice();
 return (basePrice > 1000);

extractmethod

return (anOrder.basePrice() > 1000);

 

Neden?

  • Inline Method yöntemiyle benzer nedenden ötürü bu yöntem kullanılır.
  • Üstteki örnekteki gibi değişkenin eşitlendiği kısım sabitse(hard coded bir değer, global bir değişken veya bir değer dönen bir metod vb.) ve değişken tek bir yerde kullanılacaksa değişkene gerek olmadığını söyleyebiliriz.

Nasıl?

  • “Değişkene atanan kısım sabit mi” ve “değişken tek yerde mi kullanılıyor” kontrol edilir.
  • Değişkenin kullanıldığı yere değişkenin eşitlendiği değer yazılır
  • Derleme ve test.
  • Değişkenin tanımlanma ve eşitlenme kısımları silinir.

Kendinize çook iyi davranın.

Kaynak:

http://sourcemaking.com/refactoring/inline-method

http://sourcemaking.com/refactoring/inline-temp

 Bu sayfa 1061 kez görüntülendi

It's only fair to share...Share on LinkedInShare on FacebookShare on Google+Tweet about this on TwitterShare on Tumblr

PL/SQL 6: Saklı Yordamlar vs Fonksiyonlar

Merhabalar.

Bu yazıda Saklı Yordamlar(SPler) ile fonksiyonları karşılaştırmaya çalışacağım.

Karşılaştırmaya geçmeden önce örnek olması açısından, oluşturduğum aşağıdaki basit SP ve fonksiyonlara göz atmanızda fayda var.

SP IN olarak öğrencinin numarasını(p_no) ve IN OUT olarak yüzlük sisteme çevirme katsayısını (p_yuzluk_sistem_not) alıyor.

PROCEDURE ogrenci_bilgi(p_no IN NUMBER, p_ad OUT VARCHAR2, p_soyad OUT VARCHAR2, p_yuzluk_sistem_not IN OUT NUMBER)
IS
BEGIN
    SELECT  ad, soyad, not_ortalama * p_yuzluk_sistem_not
      INTO  p_ad, p_soyad, p_yuzluk_sistem_not
      FROM  ogrenci
     WHERE  no = p_no;
END; 

İlk fonksiyon ise öğrencinin numarasını IN olarak alıyor, ad ve soyadı OUT parametre olarak dönüyor ama return değeri olarak notun yüzlük sistemdeki karşılığını dönüyor. 2. fonksiyon ise ogrenci tablosundaki max not ortalamasını dönüyor.:

FUNCTION ogrenci_bilgi_function(p_no IN NUMBER, p_ad OUT VARCHAR2, p_soyad OUT VARCHAR2)
RETURN NUMBER
IS
    p_yuzluk_sistem_not NUMBER:=25;

BEGIN
    SELECT  ad, soyad, not_ortalama * p_yuzluk_sistem_not
      INTO  p_ad, p_soyad, p_yuzluk_sistem_not
      FROM  ogrenci
     WHERE  no = p_no;

RETURN p_yuzluk_sistem_not;
END; 
FUNCTION max_ortalama_getir
RETURN NUMBER
IS
v_max_ortalama NUMBER:=0;

BEGIN
    SELECT  MAX (not_ortalama) INTO v_max_ortalama FROM ogrenci;

    RETURN v_max_ortalama;
END max_ortalama_getir;

Benzerlikler:

  • Her ikisi de IN, OUT ve IN OUT tipinde parametreleri alırlar.
  • Blok yapıları benzerdir. Yerel değişken tanımlamaları aynıdır.
  • SELECT .. INTO deyimiyle tablolardan veriler çekilip, değişkenlere atanabilir.
  • DDL işlemleri içeremezler. (Dinamik SQL kullanımı hariç)

Farklılıklar:

  • Fonksiyonlar RETURN değer dönebilir, SPlerde bu söz konusu değildir.
  • Fonksiyonların (ideal) kullanımı return bir değer elde ederek bu değerin işlenmesi/kullanılmasıdır. SPlerin ise içerisinde belli işlemler(Ör DML işlemleri) yapılmasıdır. Bu yönüyle fonksiyonlar, nesne tabanlı dillerdeki değer dönen metodlara; SPler, void metodlara benzetilebilir.
  • Fonksiyonlarda DML işlemlerinden sadece SELECT deyimi kullanılabilir. SPlerde ise tamamı (SELECT,INSERT,UPDATE,DELETE) kullanılabilir.
  • Fonksiyonlar bir değer ifade ettikleri için sorgu cümlelerinde kullanılabilir, direkt bir değişkene eşitlenebilir veya işlemlerde değişken gibi kullanılabilir. SPler kendileri bu tarz işlemlerde kullanılamaz. Ancak OUT veya IN OUT ile doldurulan değişkenler kullanılabilir.
DECLARE
    v_max_ortalama     NUMBER := 0;
    v_sorgu_ortalama   NUMBER := 0;
BEGIN
    --Fonksiyonları direkt değişkenlere eşitleyebiliyoruz.
    v_max_ortalama := max_ortalama_getir();

    --Sorgu cümlelerinde fonksiyonları "değer" ifade ettiği için kullanabiliyoruz.
    SELECT not_ortalama
      INTO v_sorgu_ortalama
      FROM ogrenci
     WHERE not_ortalama = max_ortalama_getir ();

    dbms_output.put_line ('Fonksiyondan gelen ortalama : ' || max_ortalama_getir ());
    dbms_output.put_line ('Değişkenden gelen ortalama : ' || v_max_ortalama);
    dbms_output.put_line ('Sorgudan gelen ortalama : ' || v_sorgu_ortalama);
END;

Ekran görüntüsü:
sp vs func

Kendinize çook iyi davranın.

Bu sayfa 1473 kez görüntülendi

It's only fair to share...Share on LinkedInShare on FacebookShare on Google+Tweet about this on TwitterShare on Tumblr