Tag Archives: Software Development

Programa Dilleri ve Çatıları

Son Dakika: HÖSYM İş Görüşmelerinde Çıkan Soruları Çaldırdı

HÖSYM, sonunda bu da oldu dedirtecek cinsten bir olaya daha imza atarak iş görüşmelerinde çıkan soruları da çaldırdı. Konuyla ilgili olarak HÖSYM başkanı Gani Hemir sessiliğini korurken tevekkülden sorumlu kısmi eğitim bakanı Süleyman Çekik “Allahın taktdiri, biz ne yapabiliriz ki ?.” şeklinde açıklamada bulundu. Olayla ilgili savuşturma başlatıldı.

***

İş görüşmelerinde, görüşme yaptığınız teknik insanlar sizi koklayarak tanıyamayacağından mütevellit stres altında neler yapabildiğinizi görebilmek adına çeşitli matematik teorilerini programatik ortamda modellemenizi isteyebilirler. Burada genel olarak ilk bakılan şey yazdığınız kodun neye benzediği, sonrasında ise kullandığınız metodolojidir. Eğer yapmanız gereken iş iteratif bir davranış içinde olacaksa ve siz bunun için iç içe döngüler yazmayı düşünüyorsanız derhal ellerinizi klavyeden kaldırın! Bunu yazmak yerine “Bu böyle yapılabilir ama, daha performanslı bir metod şu an heyecandan aklıma gelmiyor.” gibi bir cümle belki tarihi bir fırsatı kaçırmanızın önüne geçebilir. :)

Bugün sizlerle twitterda bir arkadaşımın gönderisi üzerine aklıma gelen fibonacci, faktöryel ve mükemmel sayılar teorileriyle ilgili olarak bir iki küçük örnek paylaşmak istiyorum.

Mükemmel Sayılar (Perfect Numbers) Nedir ?

Mükemmel sayılar kendisi hariç pozitif tam sayı bölenlerinin toplamına yada tüm pozitif tam sayı bölenlerinin toplamının yarısına eşit olan sayılardır.

Örnek:
6 = 1 + 2 + 3
28 = 1 + 2 + 4 + 7 + 14

Bir Sayının Mükemmel Sayı Olduğunu Nasıl Doğrularız ?

function isPerfectNumber($value)
{
  $total = 0;
  for( $i = 1; $i < $value; $i++ ) {
    if($value % $i == 0) {
      $total += $i;
    }
    echo sprintf('Value: %s, Loop: %s, Total: %s', $value, $i, $total) . PHP_EOL;
  }
  return $value == $total;
}

if( isPerfectNumber(8128) ) {
  echo 'This is a perfect number' https://twitter.com/i/connect. PHP_EOL;
 } else {
  echo 'This is not a perfect number.' . PHP_EOL;
 }

Sonuç:

Value: 8128, Loop: 1, Total: 1
Value: 8128, Loop: 2, Total: 3
Value: 8128, Loop: 3, Total: 3
Value: 8128, Loop: 4, Total: 7
Value: 8128, Loop: 5, Total: 7
...
alue: 8128, Loop: 8123, Total: 8128
Value: 8128, Loop: 8124, Total: 8128
Value: 8128, Loop: 8125, Total: 8128
Value: 8128, Loop: 8126, Total: 8128
Value: 8128, Loop: 8127, Total: 8128
This is a perfect number

real	0m0.629s
user	0m0.124s
sys	0m0.060s

Bu değil, daha farklı birşey olmalı. Bunu herkes yapıyor... Daha az kaynak tüketmeli, cpu/memory mutlu olmalı.

Peki, o zaman gelin bir de tail call optimizasyonu ile recursive olarak yapmayı deneylim.

function isPerfectNumber($value, $divisor = 1, $acumulator = 0)
{
  echo sprintf('Value: %s, Recursion: %s, Acumulator: %s',
              $value, $divisor, $acumulator) . PHP_EOL;

  if( $divisor < ($value -1) &&  $acumulator != $value / 2) {
    $acumulator = ($value % $divisor == 0) ? $acumulator + $divisor : $acumulator;
    return isPerfectNumber($value, $divisor+1, $acumulator);
  } else {
    return $acumulator == $value / 2;
  }
}

if( isPerfectNumber(8128) ) {
  echo 'This is a perfect number' . PHP_EOL;
 } else {
  echo 'This is not a perfect number.' . PHP_EOL;
 }

Sonuç:

Value: 8128, Recursion: 1, Acumulator: 0
Value: 8128, Recursion: 2, Acumulator: 1
Value: 8128, Recursion: 3, Acumulator: 3
Value: 8128, Recursion: 4, Acumulator: 3
Value: 8128, Recursion: 5, Acumulator: 7
...
alue: 8128, Recursion: 2029, Acumulator: 2032
Value: 8128, Recursion: 2030, Acumulator: 2032
Value: 8128, Recursion: 2031, Acumulator: 2032
Value: 8128, Recursion: 2032, Acumulator: 2032
Value: 8128, Recursion: 2033, Acumulator: 4064
This is a perfect number

real	0m0.229s
user	0m0.044s
sys	0m0.016s

Euclid çalışmış, didinmiş şöyle birşey bulmuş:
2p−1(2p−1).

function isPerfectNumber($value,$power = 2)
{
  echo sprintf('Value: %s, Recursion: %s', $value, $power-1) . PHP_EOL;
  if( pow(2, $power-1) * (pow(2, $power) -1) == $value && $power < $value) {
    return true;
  } else {
    return isPerfectNumber($value, $power + 1);
  }
}

if( isPerfectNumber(8128) ) {
  echo 'This is a perfect number' . PHP_EOL;
 } else {
  echo 'This is not a perfect number.' . PHP_EOL;
 }

Sonuç:

Value: 8128, Recursion: 1
Value: 8128, Recursion: 2
Value: 8128, Recursion: 3
Value: 8128, Recursion: 4
Value: 8128, Recursion: 5
Value: 8128, Recursion: 6
This is a perfect number

real	0m0.062s
user	0m0.048s
sys	0m0.016s

Gördüğünüz üzere ilk denememizde 8127, ikincide 2033 ve son denememizde 6 iterasyonda bu işi tamamldık.

Bir sonraki yazıda fibonacci ve factorial konularını ele alacağız.

Kaynaklar:
http://en.wikipedia.org/wiki/Perfect_number
http://www.bilgisayarkavramlari.com/2008/08/12/kuyruk-ozyinelemesi-tail-recursion-birikimsel-tarz-accumulation-style/
http://c2.com/cgi/wiki?TailRecursion

Yazılım ve Sistem Mühendisliği

Refactoring üstüne

Bu konu üstüne bir giriş yazısı yazmak istedim ama üstad bana söyleyecek söz bırakmamış. Buyrun önce bunu okuyun sonra da spagetti yazılmış örnek bir kod üzerinde birlikte basitce refactoring gerçekleştirelim.

Aslında konunun özü gayet basit:
“Any fool can write code that a computer can understand.Good programmers write code that humans can understand.” (Martin Fowler)

Her apta bilgisayarın anlayabileceği kodu yazabilir. İyi programcılar insanların anlayabileceği kodu yazarlar.

Kodunuz bu standarda uyana kadar refactor etmeye devam edin. :)

if($_POST['bank_id'] == 1) {
  $mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$curl = curl_init();
	$options = array(
		    CURLOPT_URL             => 'http://vpos.abank.com',
		    CURLOPT_POST            => true,
		    CURLOPT_RETURNTRANSFER  => true,
		    CURLOPT_SSL_VERIFYPEER  => false,
		    CURLOPT_SSL_VERIFYHOST  => true,
		    CURLOPT_HEADER          => false,
		    CURLOPT_POSTFIELDS      => $mBankXml
		);
	curl_setopt_array($curl, $options);
	$rd = curl_exec($curl);
	curl_close($curl);
        $xmlObject = simplexml_load_string($rd);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
} elseif($_POST['bank_id'] == 2) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$curl = curl_init();
	$options = array(
		    CURLOPT_URL             => 'http://vpos.bbbank.com',
		    CURLOPT_POST            => true,
		    CURLOPT_RETURNTRANSFER  => true,
		    CURLOPT_SSL_VERIFYPEER  => false,
		    CURLOPT_SSL_VERIFYHOST  => true,
		    CURLOPT_HEADER          => false,
		    CURLOPT_POSTFIELDS      => $mBankXml
		);
	curl_setopt_array($curl, $options);
	$rd = curl_exec($curl);
	curl_close($curl);
        $xmlObject = simplexml_load_string($rd);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
} elseif($_POST['bank_id'] == 3) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$curl = curl_init();
	$options = array(
		    CURLOPT_URL             => 'http://vpos.cbank.com',
		    CURLOPT_POST            => true,
		    CURLOPT_RETURNTRANSFER  => true,
		    CURLOPT_SSL_VERIFYPEER  => false,
		    CURLOPT_SSL_VERIFYHOST  => true,
		    CURLOPT_HEADER          => false,
		    CURLOPT_POSTFIELDS      => $mBankXml
		);
	curl_setopt_array($curl, $options);
	$rd = curl_exec($curl);
	curl_close($curl);
        $xmlObject = simplexml_load_string($rd);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
} elseif($_POST['bank_id'] == 4) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$curl = curl_init();
	$options = array(
		    CURLOPT_URL             => 'http://vpos.dbank.com',
		    CURLOPT_POST            => true,
		    CURLOPT_RETURNTRANSFER  => true,
		    CURLOPT_SSL_VERIFYPEER  => false,
		    CURLOPT_SSL_VERIFYHOST  => true,
		    CURLOPT_HEADER          => false,
		    CURLOPT_POSTFIELDS      => $mBankXml
		);
	curl_setopt_array($curl, $options);
	$rd = curl_exec($curl);
	curl_close($curl);
        $xmlObject = simplexml_load_string($rd);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
}

Ürkütücü dğeil mi ? Ama reel hayatta malesef bu ve daha da kötüleri de mevcut. Şimdi dilerseniz gelin bu kodları adım adım birlikte refactor edelim.

Öncelikle kodumuzu baştan uca incelediğimizde sayfaya post edilen banka kimliğine göre kodun belirli bir banka api sine veri göndermesi ve sonrasında isteğin sonucu başarılıysa veya başarısızsa veritabanında bir kaydın güncellenmesi gerekiyor.

Her apiye bir http isteği gönderdiğimize göre ilk olarak http isteği yapan bölümü fonksiyon haline getirelim.

/**
  Bu fonksiyon belirli bir url e 
  belirtilen veriyi post eder.

  @param string $url
  @param string $data
  @return string
 */
function sendHttpRequest($url, $data)
{
  $curl = curl_init();
  $options = array(
      CURLOPT_URL             => $url,
      CURLOPT_POST            => true,            
      CURLOPT_RETURNTRANSFER  => true,
      CURLOPT_SSL_VERIFYPEER  => false,   
      CURLOPT_SSL_VERIFYHOST  => true,            
      CURLOPT_HEADER          => false,                   
      CURLOPT_POSTFIELDS      => $data
      );                                                              
  curl_setopt_array($curl, $options);
  $response = curl_exec($curl);
  curl_close($curl);
  return $response
}

Bu değişiklikten sonra kodumuz aşağıdaki hali aldı.

if($_POST['bank_id'] == 1) {
  $mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.abank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
} elseif($_POST['bank_id'] == 2) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.bbank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
} elseif($_POST['bank_id'] == 3) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.cbank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
} elseif($_POST['bank_id'] == 4) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.dbank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		$sql = 'UPDATE pos_transactions SET status=1 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        } else {
		$sql = 'UPDATE pos_transactions SET status=0 WHERE sessionid=' . $_SESSION['id'];
		mysql_query($sql);
        }
}

Farkındayım kod hala bok gibi görünüyor. Şimdi de transaction durumunu güncelleyen veritabanı sorgusu için küçük bir fonksiyon yazalım.

/**
  Bu fonksiyon pos transaction ının 
  durumunu günceller.

  @param integer transactionId
  @param int status
 */
function setTransactionStatus($transactionId, $status)
{
  $transactionId  = (int) $transactionId;
  $status         = (int) $status;
  $sqlText        = "UPDATE pos_transactions SET status={$status} WHERE sessionid={$transactionId}";
  mysql_query($sqlText);
}

Bu fonksiyondan sonra kodumuz aşağıdaki hali alacak.

if($_POST['bank_id'] == 1) {
  $mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.abank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		setTransactionStatus($_SESSION['id'], 1);
        } else {
		setTransactionStatus($_SESSION['id'], 0);
        }
} elseif($_POST['bank_id'] == 2) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.bbank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		setTransactionStatus($_SESSION['id'], 1);
        } else {
		setTransactionStatus($_SESSION['id'], 0);
        }
} elseif($_POST['bank_id'] == 3) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.cbank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		setTransactionStatus($_SESSION['id'], 1);
        } else {
		setTransactionStatus($_SESSION['id'], 0);
        }
} elseif($_POST['bank_id'] == 4) {
	$mBankXml = 'data=
	
	10001
	904567564
	PROVAUT
	' . $_POST['orderid'] . '
        ' . $_POST['amount'] . '
	
	' . $_POST['ccno'] .'
	' . $_POST['expdate'] . '
	' . $_POST['scode'] . '
	
	';
	$apiResponse = sendHttpRequest('http://vpos.dbank.com', $mBankXml);
        $xmlObject = simplexml_load_string($apiResponse);
	if($xmlObject->response == 'approved') {
 		setTransactionStatus($_SESSION['id'], 1);
        } else {
		setTransactionStatus($_SESSION['id'], 0);
        }
}

Evet kod çöplüğümüz ufaktan birşeye benzemeye başlıyor. Şimdi de API lere gönderdiğimiz istekleri fonksiyonlaştıralım.

/**
  ABank icin odeme istegi gonderir.
  @param string $orderId
  @param float $amount
  @param string $cardNo
  @param string $cvc2
  @param string $expDate
  @return boolean
 */
function sendABankPaymentRequest($orderId, $amount, $cardNo, $cvc2, $expDate)
{
  $strXml = 'data=
    
    10001
    904567564
    PROVAUT
    ' . $orderId . '
    ' . $amount . '
    
    ' . $cardNo .'
    ' . $expDate . '
    ' . $cvc2 . '
    
    ';
  $apiResponse  = sendHttpRequest('http://vpos.abank.com', $strXml);
  $xmlObject    = simplexml_load_string($apiResponse);
  return ($xmlObject->response == 'approved') ? true : false;
}

/**
  BBank icin odeme istegi gonderir.
  @param string $orderId
  @param float $amount
  @param string $cardNo
  @param string $cvc2
  @param string $expDate
  @return boolean
 */
function sendBBankPaymentRequest($orderId, $amount, $cardNo, $cvc2, $expDate)
{
  $strXml = 'data=
    
    10001
    904567564
    PROVAUT
    ' . $orderId . '
    ' . $amount . '
    
    ' . $cardNo .'
    ' . $expDate . '
    ' . $cvc2 . '
    
    ';
  $apiResponse  = sendHttpRequest('http://vpos.bbank.com', $strXml);
  $xmlObject    = simplexml_load_string($apiResponse);
  return ($xmlObject->response == 'approved') ? true : false;
}

/**
  CBank icin odeme istegi gonderir.
  @param string $orderId
  @param float $amount
  @param string $cardNo
  @param string $cvc2
  @param string $expDate
  @return boolean
 */
function sendCBankPaymentRequest($orderId, $amount, $cardNo, $cvc2, $expDate)
{
  $strXml = 'data=
    
    10001
    904567564
    PROVAUT
    ' . $orderId . '
    ' . $amount . '
    
    ' . $cardNo .'
    ' . $expDate . '
    ' . $cvc2 . '
    
    ';
  $apiResponse  = sendHttpRequest('http://vpos.bbank.com', $strXml);
  $xmlObject    = simplexml_load_string($apiResponse);
  return ($xmlObject->response == 'approved') ? true : false;
}

/**
  DBank icin odeme istegi gonderir.
  @param string $orderId
  @param float $amount
  @param string $cardNo
  @param string $cvc2
  @param string $expDate
  @return boolean
 */
function sendDBankPaymentRequest($orderId, $amount, $cardNo, $cvc2, $expDate)
{
  $strXml = 'data=
    
    10001
    904567564
    PROVAUT
    ' . $orderId . '
    ' . $amount . '
    
    ' . $cardNo .'
    ' . $expDate . '
    ' . $cvc2 . '
    
    ';
  $apiResponse  = sendHttpRequest('http://vpos.bbank.com', $strXml);
  $xmlObject    = simplexml_load_string($apiResponse);
  return ($xmlObject->response == 'approved') ? true : false;
}

Ve… kodumuzun yeni hali…

if($_POST['bank_id'] == 1) {
  $bankResponse = sendABankPaymentRequest($_POST['orderId'], 
                                          $_POST['amount'], 
                                          $_POST['ccno'], 
                                          $_POST['cvc2'], 
                                          $_POST['expdate']);
  if($bankResponse) {
    setTransactionStatus($_SESSION['id'], 1);
  } else {
    setTransactionStatus($_SESSION['id'], 0);
  }
} elseif($_POST['bank_id'] == 2) {
  $bankResponse = sendBBankPaymentRequest($_POST['orderId'], 
                                          $_POST['amount'], 
                                          $_POST['ccno'], 
                                          $_POST['cvc2'], 
                                          $_POST['expdate']);
  if($bankResponse) {
    setTransactionStatus($_SESSION['id'], 1);
  } else {
    setTransactionStatus($_SESSION['id'], 0);
  }
} elseif($_POST['bank_id'] == 3) {
  $bankResponse = sendCBankPaymentRequest($_POST['orderId'], 
                                          $_POST['amount'], 
                                          $_POST['ccno'], 
                                          $_POST['cvc2'], 
                                          $_POST['expdate']);
  if($bankResponse) {
    setTransactionStatus($_SESSION['id'], 1);
  } else {
    setTransactionStatus($_SESSION['id'], 0);
  }
} elseif($_POST['bank_id'] == 4) {
  $bankResponse = sendDBankPaymentRequest($_POST['orderId'], 
                                          $_POST['amount'], 
                                          $_POST['ccno'], 
                                          $_POST['cvc2'], 
                                          $_POST['expdate']);
  if($bankResponse) {
    setTransactionStatus($_SESSION['id'], 1);
  } else {
    setTransactionStatus($_SESSION['id'], 0);
  }
}

Eskiye oranla kodumuz oldukça kısa ve okunaklı oldu. Ancak yine de Aynı işi yapan blokların tekrar etmesi biraz can sıkıcı. Dilerseniz gelin şimdi de bankalara istek gönderen fonksiyonları tekilleştirelim ve sonuca göre bir kerede pos transaction durumumuzu güncelleyelim.

/**
  kimliği belirtilen bankaya ödeme isteği gönderir.

  @param int bankId
  @param string $orderId
  @param float $amount
  @param string $cardNo
  @param string $cvc2
  @param string $expDate
  @return boolean
 */

function sendPaymentRequest($bankId, $orderId, $amount, $cardNo, $cvc2, $expDate)
{
  $functionMap = array(
        1 => 'sendABankPaymentRequest',
        2 => 'sendBBankPaymentRequest',
        3 => 'sendCBankPaymentRequest',
        4 => 'sendDBankPaymentRequest'
      );

  if(!in_array($bankId, $functionMap)) {
    return false;
  }
  
  $function = $functionMap[$bankId];

  return $$function($_POST['orderId'],
      $_POST['amount'],
      $_POST['ccno'],
      $_POST['cvc2'],
      $_POST['expdate']);
}

Bu geliştirmeden sonra kodumuz son olarak aşağıdaki hali alacaktır.

$bankResponse = sendPaymentRequest($_POST['bank_id'],
    $_POST['orderId'], 
    $_POST['amount'], 
    $_POST['ccno'], 
    $_POST['cvc2'], 
    $_POST['expdate']);
if($bankResponse) {
  setTransactionStatus($_SESSION['id'], 1);
} else {
  setTransactionStatus($_SESSION['id'], 0);
}

Berker’in comment’inden sonra gelen edit:

$bankResponse = sendPaymentRequest($_POST['bank_id'],
    $_POST['orderId'], 
    $_POST['amount'], 
    $_POST['ccno'], 
    $_POST['cvc2'], 
    $_POST['expdate']);
setTransactionStatus($_SESSION['id'], (int) $bankResponse);

Göktuğ’nun comment’inden sonra sendPaymentRequest() fonksiyonuna gelen edit:

/**
  kimliği belirtilen bankaya ödeme isteği gönderir.

  @param int bankId
  @param string $orderId
  @param float $amount
  @param string $cardNo
  @param string $cvc2
  @param string $expDate
  @return boolean
 */

function sendPaymentRequest($bankId, $orderId, $amount, $cardNo, $cvc2, $expDate)
{
  $functionMap = array(
        1 => 'sendABankPaymentRequest',
        2 => 'sendBBankPaymentRequest',
        3 => 'sendCBankPaymentRequest',
        4 => 'sendDBankPaymentRequest'
      );

  if(!in_array($bankId, $functionMap)) {
    return false;
  }

  return $functionMap[bankId]($orderId,
      $amount,
      $cardNo,
      $cvc2,
      $expDate);
}
Yazılım ve Sistem Mühendisliği

Geliştirme Metodolojisi Finansal Bir Karardır

Yıllar geçse de, yeni teknolojiler çıksa da PHP gibi serbest yazım stillerine izin veren diller olduğu sürece MVC öcü mü ? oop mi spagetti mi gibi tartışmalar daha uzun yıllar devam edecektir…

***

İşin özü, projenizin programlama stilini belirlemek veya değiştirmek, tamamen finansal bir karardır. Aynen vadeli veya peşin para ile alışveriş yapmak gibi.

Prosedürel programlama kolaydır, fonksiyon kütüphaneleri ve kategorize edilmiş klasör yapılarıyla sizden bekleneni hızlıca üreterek işvereninizi ve yöneticilerinizi kolayca memnun etmenizi sağlar. Bazı durumlarda mvc frameworkler ile geliştirilen projelere göre daha az kaynak tükettiği ve daha hızlı aplikasyonların geliştirilmesine elverişli olduğu konusu gerçektir. Ancak kalabalıklaşan ve projenin geneli hakkında bilgisi olmayan ekiplerin proje üzerinde çalışması ve projenin yaşlanması gibi faktörler kod tekrarına; çok basit ancak projenin geneline etki etmesi beklenen geliştirmeler bazen günler sürerek gereksiz geliştirici kaynağı tüketimine neden olabilir.

MVC frameworkler, umumiyetle nesne yönelimli programlama bilgisi gerektiren yapılardır. Gücü yada hızı kullandığınız framework un dispatch cycle ına göre değişkenlik gösterir. Deneyimli developer lar ve tasarım bilgisi gerektirir. Yapılacak her geliştirme programatik ortamda doğru modellenmeli ve dökümante edilmelidir. Concurrent kullanımın artması gibi durumlarda sunucunuz üzerindeki yükün ciddi manada artacağı konusu bir hakikattir. Kısa vadede bu ve benzeri durumlar gözünüzü korkutsada uzun vadede mvc framework lerin sağlayacağı yararların tartışılmazlığı kesindir.

MVC frameworklerin kullanımıyla ilgili olarak başta bahsettiğim concurrent kullanıcı sayısından doğan yük, doğru ölçeklenmiş, dağıtık bir yapıda rahatlıkla karşılanabilir. Ayrıca mvc hiyararşisi, basit manada tüm business logic in model katmanında, arayüz içeriğinin view katmanında ve bu iki katman arasındaki iletişimi sağlayan yapının controller katmanında olmasını gerektirir. Böylelikle sistemin fonksiyonel bölümünü görsel bölümden izole etmiş olursunuz. Projenin geneline etki etmesi beklenen geliştirmeler, mvc frameworklerin sunduğu plugin gibi yapılarla son derece basit ve kısa sürelerde gerçekleştirilebilir(Zend framework’ün controller plugin leri bu konuya iyi bir örnektir.). DbTable ve ORM gibi, frameworklerle birlikte gelen yada uyumlu çalışabilen veri erişimi sistemleri, injection gibi tehlikeli durumlardan sizi koruyarak güvenli sistemler geliştirmenize olanak sağlar. Son olarak her framework kendi kod standartlarıyla birlikte gelir. Kurallara uygun yazılan, düzgün modellenmiş ve dokümante edilmiş sistemler, minimum kod tekrarıyla temiz ve anlaşılır kod yazmanıza olanak sağlar.

***

Ve… emin olun sizden alelacele iş bekleyerek, sizi sistemi çöp haline getirmeye zorlayan her işveren veya yönetici, uzayan development süreleri ve büyüyen maliyetlerden bezerek “Framework diye birşey varmış…” diyecek ve konuyu gündemine alacaktır.

Sürüm Yönetimi

Git Çıktılarının Renklendirilmesi

Sabah sabah bilgisayarımın işletim sistemini başlatamaması gibi güzel bir sürprizle güne başladım. Uzun uğraşlar sonucu kurtarmayı başaramayınca mecburen yeniden kurmak zorunda kaldım. Uzun süredir aynı işletim sistemiyle çalışınca insan haliyle başlangıçta neyi nasıl yaptığını unutabiliyor. Dolayısıyla google yardırmaya başlıyorsunuz.

Bundan mütevellit bugün böyle kısa kısa postlar görmeniz muhtemeldir :)

***

Git çıktısını renklendirmek için aşağıdaki komutu çalıştırın:

$ git config --global --add color.ui true
Programa Dilleri ve Çatıları

Kredi Kartı Hareketlerini Sorgulamak İçin Basit Bir Kütüphane

Yakın geçmişte iade konusuyla ilgili başımızdan geçen bir olay nedeniyle iade öncesinde bankayla aramızda mütabakat yapma kararı aldık. Bu işle uğraşırken aşağıdan temin edebileceğiniz PHP kütüphanesini geliştirdim. Umarım birilerinin işine yarar.

Aşağıdaki github deposundan kütüphanenin kaynak kodlarına ulaşabilirsiniz :
https://github.com/ibrahimgunduz34/CcQueryTool

Kütüphane özetle, belirli bir siparişin history datasını banakadan isteyerek dönen veriyi işler ve size bu siparişle ilgili toplam ödenen, iade edilen ve balans verilerini döner.

Kütüphanem Türkiye’deki bankalara sanal pos servisi veren Est, Posnet ve Gvp altyapılarını destekliyor. Sizler de bu kütüphaneyi para iadesi öncesinde mütabakat amacıyla veya banka posunu uygulama katmanında test etmek için kullanabilirsiniz.

Yazılım ve Sistem Mühendisliği

Tasarım Candır

Epeydir teknik konularda sağda solda blog yazıları yazıyorum, iltraf etmeliyim bugüne kadar hiçbir yazım için Bu işin bir pattern i olmalı! kadar olumlu tepki almamıştım, çok şaşırdım.

Mesleki kariyerim için tehlikeli; hislere tercüman olma noktasında başarılı bir yazı oldu sanırım :)

***

Genel geliştirici kafasıdır, önümüze bir iş gelir daha işin ne olduğunu bile doğru dürüst anlamadan bodoslama kod yazmaya girişiz. Daha kodlama aşamasında aklımıza farklı metodolojiler gelir, eski yazdıklarımızı refaktör eder yola devam ederiz, sonra farkederiz ki kazın ayağı öyle değilmiş, yazdığımız kod ne isteneni, ne de ilişkili olduğu başka işlerden doğan ekstra case leri karşılıyor… Tohumuna para mı saydık. Oturur bir daha yazarız… Gider biryerlerden birşeyler okuruz, has… lan bu böyle de yapılabiliyormuş der yine yazarız. Araya başka iş girer, zaman geçer neyi neden yaptığımızı unutur yine başa döneriz….

Tohumuna para mı saydım dediğiniz şey, kısa vadede zaman kaybı, uzun vadede business gözünde “IT ye giden iş gelmiyor”, yöneticinizin gözünde “Mehmetin verimi düşük günlerdir aynı işin üzerinde çalışıyor”, arkadaşlarınızın gözünde “lan bu mehmet de yalanmış” şeklinde oluşan imaj, türlü prestij kaybı ve hatta daha kötüsü işinizden kovularak para kaybı olarak size geri dönecektir.

Tabi bir de herhangibirşey karalamadan giriştiğiniz bu işin, ön görmediğiniz side effectlerinden doğan reopen ticketler, sizi kovulma level ine birkaç adım daha yaklaştıracaktır.

***

Hazır olun! Mesaj geliyor…
Mimar gibi tasarlayın, müteahhit gibi kodlayın.

Sizden istenen şeye daima bir proje edasıyla yaklaşın. İşi, büyüklüğüne göre mümkün olduğunca kendi başına çalışabilen küçük parçalara ayırın ve herbir parçanın kusursuz çalışacağından emin olun. (Tabi kağıt üstünde mümkün olabilecek kadar). Çok fazla zaman kaybettirmeyecek şekilde mükemmeli yakalayana kadar tekrarlayın. Tıpkı bir gökdeleni incelikle tasarlayan bir mimar gibi.

Daha sonra tasarladığınız bu yapıyı bilgisayarınızın başına oturup kodlayarak hayata geçirin. Kodlama sırasında zamanı para olarak nitelendirin ve paradan kırpmaya çalışan laz müteahhit kafasıyla kodlama yapın. Tasarımınızın doğruluğundan eminseniz yolda aklınıza gelen fikirleri sonraki faza bırakın. Kişisel fikrimi soracak olursanız yolda akla gelen fikirleri doğrudan ignore edin. Müşteriniz ekranda gördüğüyle, yöneticiniz işin ne kadar zamanda ne kadar az hatayla tamamlandığına bakar, program koduna ise yalnızca siz veya belki birkaç takım arkadaşınız.

 

Genel

Kahrolsun Internet Explorer!

Pek isyankar olduğum söylenemez. Çalıştığım şirkette kim ne isterse çok fazla sızlanmadan oturur paşa paşa yazarım. Zaten ne için para alıyoruz ki ? Genellikle verdiğim deadline ı yakalamaya gayret ederim. Ama şu browser sorunları yok mu…

PM insanları gelir der ki “Ey developer! vatandaş checkout a gitsin kart nosunu yazsın, taksit seçsin, taksit seçeneğine göre vade farkı otomatik hesaplanıp sepet güncellensin, girilen kart numarası yapıkrediye aitse ve 6 taksiti seçmişse sayfanın üstünde vadaa hayvanı çıksın kampyadan yararlanmak istiyor musun diye sorsun.”

Siz tüm bunlar için birer if yazmayıp çok generic bir çözüm bulmak adına oturur yazmanız gereken kodun paternini belirlersiniz, kodunuzu yazarsınız ve genellikle kodunuz geliştirme ortamında başarıyla alışır. Haliyle sizde dünyayı kurtaran adam edasıyla IT de kasıla kasıla gezersiniz, arada arkadaşlarınıza yaptığınız iş atla deveymiş gibi yağlandıra ballandıra anlatırsınız “Hacı! bir kod yazdım ben hede hede paterninde, objeleri şöyle tanımlıyorsun, böyle extend ediyorsun, uçuyor, kaçıyor amk!”. Halbu ki ne ki anasını satayım belli şartlar gerçekleşince ekranda vadaa hayvanı çıkıyor:)

Neyse, efendime söyleyeyim sıra test e geldiğinde zalım QA ekibi sizin kodunuzu windows işletim sistemli bilgisayarlarda envai çeşit Internet Explorer sürümüyle test eder, bug bug üstüne gelir, ciğeriniz yanar. Belki bir günde yazdığınız güzelim kodu, üç günde internet explorer da alışır hale getiremez, kudurursunuz. IE7 de çalışan 8 de çalışmaz, 8 de çalışan 9 da çalışmaz… Tabi visual hadiseleri hiç saymıyorum. IE9 da düzgün görünen sayfanın 8 de kıçı başı bir yana kayar.

Sonrası mı, sonrası tekrarlanamayan hatalar, akıl-mantık dışı browser buglarına bulunmaya çalışılan derme çatma çözümler ve haliyle bitmek tükenmek bilmeyen mesai saatleri…

Birileri çıksın ve şu browser yazanlarını bir araya toplayıp ortak bir standart belirlesin. Fakat bu standart internet explorer olmasın. Dinsin bu akan developer kanı artık!