Bash Script İçerisindeki Arşiv Dosyasını Açmak

Geçen gün elime bash script bir dosyası gelmişti. Yaklaşık ilk 200 satırı klasik bash script dosyasıydı, ancak geri kalanında binary bir şekilde duran bir arşiv (tar.gz gibi) dosyası olduğunu gördüm. Binary şekilde bash script dosyasının içine gömülen bu arşivin açılması gerekliydi.

Şu komutlar ile binary kısımdaki arşiv açıldı:

match=$(grep --text --line-number '^ARCHIVE:$' DOSYA_YOLU | cut -d ':' -f 1)
archive=$((match + 1))
tail -n +$archive DOSYA_YOLU | tar -xzvf - -C .

Not: DOSYA_YOLU yazan yerleri değiştirmeyi unutmayınız.

24 Ağustos 2015

Posted In: Genel, Gezegen

PHP 7 ile Gelen Return Type Declarations

Ekim 2015’te stabil olarak yayınlanması beklenen PHP 7’nin code base’ine return type declarations (geri dönüş bildirimi) merge edildi.

Fonksiyonların yorum satırlarına @return int, @return void yazarak o fonksiyonun hangi tipte veri döndürdüğü belirtilirdi. Ancak bunlar birer yorum satırı olduğu için @return array yazan bir fonksiyondan string dönebiliyordu.

Artık PHP 7 ile doğrudan bir fonksiyonun ne tip veri döndürdüğünü dilin kendisinin de anlayabileceği şekilde belirtebiliyoruz.

Hızlıca bir örnek vermek gerekirse:

function getCity(): string {
    return "Ankara";
}

Örnekte olduğu gibi fonksiyon isminden sonra dönecek olan tipi belirtiyoruz.

Peki bu fonksiyonu şöyle değiştirsek:

function getCity(): string {
    return 06;
}

String döneceğini belirttiğimiz fonksiyon integer bir değer döndürdü.

Sizce bu şekilde çalışacak mı?

İlginç gelebilir ancak çalışacaktır. Çünkü PHP 7 ile artık hayatımıza “weak mode” ve “strict mode” kavramları giriyor.

Tahmin edeceğiniz gibi weak mode bu tarz işlere izin veriyor. Strict mode ise kesinlikle belirtilen kurallara uyulmalı diyor.

Strict mode’u nasıl aktifleştireceğiz?

Kodunuzun <?php satırından hemen sonra

declare(strict_types=1);

yazmanız yeterli. Bu satırı eklemezseniz kodlarınız weak mode’da çalışacaktır.

Şimdi kodu şu şekilde düzenleyip çalıştırmayı deneyelim:

declare(strict_types=1);

function getCity(): string {
    return 06;
}

echo "Merhaba";

Uppss… E yine çalıştı? Yani ekrana Merhaba yazıldı. Ama kodun içinde yerinde bulunan fonksiyon string dönmesi gerekirken integer dönüyor hem de strict mode’dayken!

Neden böyle oldu?

Çünkü getCity() fonksiyonundan dönen değeri henüz bir yerde kullanmadık. Bir başka deyişle getCity() fonksiyonunu henüz çağırmadık.

Yani kodu şöyle düzeltirsek:

declare(strict_types=1);

function getCity(): string {
    return 06;
}

echo "Merhaba";

getCity();

Böyle bir hata alacaksınız:

Fatal error: Return value of getCity() must be of the type string, integer returned in test.php on line 6 in test.php on line 6

Bir Sınıfı Return Type Olarak Belirtmek


declare(strict_types=1);

class Car {
    public $type = "Manual";
}

class Mercedes extends Car {

    public $model = "CLA200";
    public $color = "White";
    public $type = "Automatic";

}

class Property {

    public function getCarDetails(): Car {
        return new Mercedes();
    }

}

$property = new Property();
echo $property->getCarDetails()->type;

getCarDetails() metotunda Car sınıfından bir şey döneceğini belirttik. Mercedes sınıfı da Car sınıfından extend edildiği için çalıştı. Aynı şekilde bir interface‘i de return type olarak belirtebilirsiniz.

Null Bir Şeyler Return Edebiliyor Muyuz?

function getCity(): string {
    return null;
}

getCity();

Bu kodu çalıştırdığınızda şöyle bir hata alacaksınız:

Fatal error: Return value of getCity() must be of the type string, null returned in test.php on line 6 in test.php on line 6

Dikkat ederseniz bu kod strict mode’da dahi değil.

Yapıcı ve Yıkıcı Metotlarda Return Type

__construct, __destruct ve __clone metotlarında return type belirtilemiyor.

Void Return Type Nerelerde?

Void return type henüz yok. Gelişimini şuradan takip edebilirsiniz: https://wiki.php.net/rfc/void_return_type

Not: Yazının başında da belirttiğim gibi PHP 7’nin Ekim 2015’te stabil olması bekleniyor. O zamana kadar return type işlerinde yeni şeyler olabilir (void type gelmesi gibi). Eğer yeni bir şey olursa eklemeye çalışacağım.

5 Nisan 2015

Posted In: Genel, Gezegen, php, php7, return type

Node.js ile Inotify Event’lerini İşlemek

Geçen gün bir feature (özellik) isteği gelmişti. Bir servis sunucuya bağlanıp bir dosya oluşturacak ve içini dolduracak. Kullanıcıya ise bulunduğu web sayfasında sayfayı yenilemeden bu dosyanın oluştuğundan haberdar edilecek ve tabii sonra bu dosyayı kullanıcı görüntüleyecek.

Direkt 5 saniyede bir AJAX yapıp ilgili dosya oluşmuşsa bir div’e dosyanın oluştuğuna dair mesaj basabilirdim aslında. Ancak olayı biraz daha efektif hâle getirmek istedim. Çünkü AJAX istekleri beraberinde bir dizi overhead getirecekti.

Örneğin; İlgili sayfada 10 kişi olsa, 5 saniyede bir file system‘da yeni dosya var mı diye kontrol yapılması gerekecekti. 10 kişi ayrı ayrı 5 saniyede bir backend’e istek atacaktı. Bu da istediğim bir durum değildi.

Bir diğer problem ise dosyaya yapılan yazma işleminin bittiğinden emin olunması gerek.
Örneğin; AJAX isteği attım. İstekte dosyanın varlığını kontrol ettim. Sonra baktım dosya var mı? Var. Ön tarafa haber saldım “dosya oluştuuuu” diye.
Ama o sırada third-party servis dosyaya veri yazma işlemini bitirmedi. Kullanıcı da “e dosya oluştu madem açayım” derse, sçtık. Çünkü eksik veri görüntüleyecek hatta belki de hata alacak. Sonra ayıkla pirincin taşını.

Bu iş için esas olan “dosyaya yazma işlemim bitti” mesajının gerekliliği. E third-party servis sadece dosya oluşturuyor Gidip bu third-party servisin ekstra bir yerlere mesaj yazmasını da sağlayamam (dosyaya yazdım bitti gibisinden). Hadi yazdırdım diyelim, bir de gidip orayı kontrol etmem gerekecek.

vs. vs. Daha buraya yazmadığım tonla senaryo var bu iş için.

Kısaca bana “dosyayı oluşturdum“, “dosyaya yazdım“, “dosyayı sildim” vs. gibi eventler gerekliydi. Bu bilgileri ise Linux‘ta direkt çekirdekte bulunan Inotify eventleri çok güzel sağlıyor. Yani bilgi sağlam yerden geliyor.

Node.js‘te Inotify eventlerini handle edebilen güzel bir kütüphane var (detaylar, kullanım örneği linkte): node-inotify

node-inotify kütüphanesini ise socket.io ile birleştirip kullanırsanız tadından yenmez (Ben socket.io kullanmıştım, ama siz başka bir kütüphane elbette tercih edebilirsiniz). Çünkü bu şekilde ön tarafa bir socket açıp dosya değişikliklerini bu socket üzerinden yollayabilirsiniz.

Scala ve Java’da ise bu işleri Non-blocking I/O (java.nio) paketiyle yapabilirsiniz.

14 Mart 2015

Posted In: Genel, Gezegen

Session’ları Memcached’te Saklamak Ne Kadar Doğru?

Özellikle arkasında birden fazla web sunucusunun bulunduğu web projelerinde genellikle non-sticky session bilgilerini saklamak için Memcached kullanılır. Bu şekilde kullanıcıların, farklı web makinelerine düştüklerinde oturum bilgilerine erişilebilmesi amaçlanır.

Ama projenizde her şey yolunda giderken, bir anda kullanıcılardan kendi istekleri dışında “logout olma” şikayetleri gelmeye başladı. Hemen projenizin kodlarını incelediniz ancak anormal bir durum görünmüyor.

Muhtemelen Memcached kullanıcıların session bilgilerini siliyordur.

Peki ama nasıl?

Bu durumu örneklersek: 1. kullanıcı giriş yaptı ve session bilgileri Memcached‘e yazıldı. Ardından yüzlerce kullanıcı da giriş yaptı ve hafızada yer kalmadı. 1. kullanıcının session bilgileri silindi ve böylece logout oldu.

Memcached neden session bilgilerini sildi?

Memcached’e 64 MB (örnek değer) limit verdiniz ve bu 64 MB doldu. Memcached otomatik olarak kendi içerisinde LRU (Least Recently Used) algoritmasını uygulamaya başlayacaktır. Bu algoritma ile “son zamanlarda en az kullanılan” key’i hafızadan silecektir.

Bu senaryoda da bizim silinen key’imiz 1. kullanıcının session key’i oluyor.

Bir diğer durum ise Memcached persistent (kalıcı) bir veri saklamaması. Bundan dolayı sadece LRU algoritması ile değil herhangi bir sebepten dolayı Memcached kapanıp, yeniden açılırsa da (konfigürasyon değişikliği, işletim sisteminin yeniden başlatılması, donanım güncellemesi vs.) session bilgileri silinmiş olur. Doğal olarak kullanıcılar web sitesinden çıkış yapmış olur. Bu da kimi projeler için hoş olmayan sonuçlar doğurabilir.

Session kayıplarını önlemek için, genelde persistent şekilde veri saklayan RDBMS, NoSQL çözümler kullanmanız önerilir.

Bir yazıda hem session hem cache geçiyorsa sonuna şu gif’i koymamak olmaz :) : Patronun cache icin session kullandigini gordugumde ben

26 Ocak 2015

Posted In: Genel, Gezegen

İmzalamadığınız Commit Sizin Değildir

Git kullananlar bilirler, .gitconfig isimli dosyaya isim soyisim ve e-posta adresi yazılarak commit loglarına commit sahibinin bilgileri otomatik eklenir.

Ancak bu durumun bir olumsuz(?) yanı vardır. Başkaları sizin adınıza commit yapabilir.
Kendi .gitconfig dosyanıza Ali yazsanız Ali’nin adına Veli yazsanız Veli’nin adına commit yapabilirsiniz.

Ancak bir commit’in gerçekten o kişinin yaptığına emin olmak için commit’i imzalamakta fayda vardır.

Peki imzalamayı nasıl yapacağız?

Öncelikle sisteminizde imza var mı bakınız:

gpg --list-keys

(Eğer daha önce GPG ile ilgili işlem yapmamışsanız, bu komut gerekli dosyaları da oluşturacaktır.)

Şuna benzer bir sonuç döndürmeli:

pub   2048R/B489436C 2014-12-14
uid                  Adil Ilhan <no-reply@adililhan.com>

Eğer GPG anahtarınız yoksa boş sonuç dönecektir.

gpg --gen-key

komutu ile GPG anahtarınızı oluşturabilirsiniz. Bu komut size yol gösterecektir.

Ekstra olarak açıklama gereği duyduğum kısım passphrase kısmı. Buraya parola girerseniz oluşturacağınız anahtar bu parola olmadan çalışmayacaktır. Yani anahtarınız çalınsa bile ekstra olarak bir de buraya yazdığınız parolaya ihtiyaç duyulacaktr.

GPG anahtarı artık oluşmuş olmalı. Kontrol için:

gpg --list-keys

Git ortamınıza bu anahtarı tanımlamak gerek:

git config --global user.signingkey B489436C

B489436C bilgisini gpg –list-keys komutunun sonucundan aldım.

Artık commitleri -S parametresi ile imzalayabiliriz:

git commit -m "test" -S

İmzalanmış commitleri görme ve doğruluğunu teyit etme:

git log --show-signature

Bu komut, yerel (local) makinenizdeki GPG bilgisi ile commit log’unda yer alan GPG bilgisini eşleştirir.
Uyuşan loglara gpg: Good signature… yazılır. Uyuşmayan loglara Can’t check signature yazılır.

Örneğin sizin bilgisayarınızdan imzalanarak commitlenen bir commit başka bir bilgisayarda bakıldığında ve o bilgisayarda sizin GPG anahtarınız yoksa log sonuçlarına Can’t check signature bilgisi yazılır.

15 Aralık 2014

Posted In: Genel, Gezegen, git, GPG

Doctrine 2 ile Optimistic Locking

Yoğun editör işlemlerinin olduğu projelerde aynı yazıyı içeriği güncelleme problemleri ile sıkça karşılaşılır.

Örnek senaryo;

  • 1. editör 1. yazıyı güncellemek için açtı.
  • 2. editör 1. yazıyı güncellemek için açtı.
  • 1. editör 1. yazıyı güncelledi.
  • 2. editör 1. yazıyı güncelledi(!).

Son değişikliği 2. editör yaptığı için 1. editörün yaptığı değişiklikler silindi. Bunu önlemek için 2. editöre “Senden önce 1. editör bu yazıyı düzenledi. Önce onun değişikliklerine bakmalısın.” demek gerek.

Peki bu uyarı sistemini ne ile kuracağız?
Optimistic Locking yöntemi ile.

Kısaca bu yöntemi şu şekilde çalışır:

Tablo ismimiz Post olsun. Post tablosuna “version” isminde bir sütun daha ekleyeceğiz. İlk insert işleminde version sütununa 1 yazılır. Her yazı güncellemesinde version sütunundaki sayı 1 arttırılır.

Kullanıcı içeriği güncellediğinde versiyon sayısı güncellemeden önceki sayı ile aynı değilse içerik daha önce birileri tarafından güncellenmiştir.

PHP’de bu işlemleri araya herhangi bir ORM koymadan halledebilirsiniz. Ancak sizin yerinize Doctrine 2 versiyonlama işlemini destekliyor.

Yapmanız gereken Post entity’nize bir @Version annotation’ı eklemeniz.

Örnek olarak hazırladığım Post ismindeki entity’e buraya tıklayarak ulaşabilirsiniz.

Entity sınıfında gerekli versiyonlama için düzenlemeyi yaptık.

Bu Post entity sınıfını kullanarak yazdığım örnek bir Symfony 2 controller’ı da şu şekilde:

namespace Acme\BlogBundle\Controller;

use Acme\BlogBundle\Entity\Post;
use Acme\BlogBundle\Form\PostType;
use Doctrine\DBAL\LockMode;
use Doctrine\ORM\OptimisticLockException;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends Controller
{
    /**
     * @Route("/post/{id}")
     * @Template()
     */
    public function showAction($id)
    {
        $em = $this->get('doctrine')->getManager();
        $entity = $em->find('Acme\BlogBundle\Entity\Post', $id, LockMode::OPTIMISTIC);
        $form = $this->createForm(new PostType(), $entity, ['action' => $this->generateUrl('update_action')]);
        return $this->render('AcmeBlogBundle:Default:show.html.twig', ['form' => $form->createView()]);

    }

    /**
     * @Route("/update", name="update_action")
     * @Method({"POST"})
     */
    public function updateAction(Request $request) {

        $post = new Post();

        $form = $this->createForm(new PostType(), $post);

        $form->handleRequest($request);

        if($form->isValid()) {
            $formData = $form->getData();
            $post->setId($formData->getId());
            $post->setTitle($formData->getTitle());
            $post->setContent($formData->getContent());
            $post->setVersion($formData->getVersion());

            try {
                $em = $this->getDoctrine()->getManager();
                $em->merge($post);
                $em->flush();
            } catch(OptimisticLockException $e) {
                return $this->render('AcmeBlogBundle:Default:locking.html.twig');
            }

            return $this->render('AcmeBlogBundle:Default:success.html.twig');

        }
            return $this->render('AcmeBlogBundle:Default:error.html.twig');

    }
}

22. satırda Optimistic Locking kullanarak find işlemini yapıyoruz. 51. satırda OptimisticLockException ismindeki Exception için bir kural yazılı. Doctrine 2 bizim yerimize version sütununu kontrol ediyor, eğer değer aynı değilse OptimisticLockException isminde bir Exception fırlatıyor.

Örneğin; /post/5 yolunu iki ayrı browser tabında açıp, ikisinde de güncelleme yapılsın. İlk güncelleme çalışacaktır ve 5 numaralı satırın version sütununu 2‘ye yükselecektir. İkinci tabdan güncelleme yapıldığında orada version bilgisi 1 olarak kaldığı için OptimisticLockException‘ı fırlayacaktır.

Bazı kaynaklarda versiyonlama sütunlarını date time veya timestamp olarak da tutulmasından bahsedilebilir. Ancak olası zaman kaymaları için bu yöntem önerilmez.

Ayrıca Bkz.: Dirty read

Not: Symfony 2’de Doctrine 2 varsayılan olarak geldiği için Symfony 2 controller örneği verdim. Doctrine 2’yi başka frameworklerde de kullanabilirsiniz.

14 Kasım 2014

Posted In: Genel, Gezegen

PHP – Identity Map Pattern

$user1 = User::find(1);
$user  = new User();
$user1 = $user->find(1);

Bunlar ve buna benzer kullanımlar PHP içerisinde sıkça görebileceğiniz kullanıcı çekme yöntemleridir. User sınıfındaki find() metotu size bir UserRepository (ismi salladım) nesnesi döndürür oradan işlem yaparsınız.

Örneğin; Runtime’da iki alakasız yerde 1 numaralı kullanıcının veritabanındaki bilgilerine ihtiyacınız var.

Birinci yerde User::find(1) yaptınız ve SELECT sorgusu çalıştırdınız. Kodun farklı bir noktasında tekrar User::find(1) yaptınız ve tekrar SELECT sorgusu işlendi.

Ama daha önce 1 numaralı kullanıcı veritabanından çekilmişti. Tekrar SELECT yapmaya gerek var mı?

veya…

X metotu içinde User::find(1) yaptınız kullanıcıyı çektiniz ve kullanıcı adı Ali.

Sonra Y metotunda tekrar User::find(1) yaptınız. Ama Y metotunun içinde şöyle bir if koşulu var: “Eğer id 1 ise kullanıcı adını Veli yap”.

Y metotundaki kullanıcı adı Veli oldu. Ama geri X metotuna döndüğümde kullanıcı adı hâlen Ali kaldı.

Böyle birçok farklı senaryo düşünülebilir.

Buradaki temel problem her find yapıldığında yeni bir UserRepository objesinin geriye dönmesinden kaynaklanıyor.

Sistem geneli 1 numaralı kullanıcı için hep aynı nesneyi kullansa tekrar SELECT‘e gerek kalmayacak ve bir metotta kullanıcı adı setlendiğinde başka metotta da bu görülebilecek.

Peki bu nasıl sağlanacak? Identity Map Pattern ile.

Runtime’da objeleri cacheleyeceğiz.

User::find(1) işlemi için metotu hazırlayalım.

User.php

class User {
    public static function find($id) {
        return (new UserMapper)->init($id);
    }
}

Kullanıcı bilgilerinin bulunduğu UserRepository ile User sınıfının arasındaki bağlantıyı sağlayacak Mapper.

UserMapper.php

class UserMapper {
    
    private static $object;
    
    public function init($id) {
        if( ! isset(self::$object[$id])) {
            self::$object[$id] = (new UserRepository)->fetch($id);
        }

        return self::$object[$id];
        
    }
    
}

Son olarak da kullanıcı bilgilerini barındıran UserRepository sınıfı

UserRepository.php

class UserRepository {

    public $users = [['name' => 'Ali'], ['name' => 'Veli']];

    private $name;

    public function fetch($id) {
        if( ! isset($this->users[$id])) {
            throw new InvalidArgumentException;
        }

        $userRepository = new self; 
        $userRepository->setName($this->users[$id]['name']);

        return $userRepository;
    }

    public function getName() {
        return $this->name;
    }

    public function setName($name) {
        $this->name = $name;
    }
}

Burada bir de DAO işlemleri için ekstra sınıflar gerekiyor. Ancak örnek olması için veritabanı olarak bir basit array kullandım.

Örnek işleme bakalım:

test.php


$user1 = User::find(1);
$user2 = User::find(1);

$user1->setName('Emre');
echo $user2->getName(); // $user2 objesi de Emre oldu

UserMapper sınıfında nesneler cachelenmeseydi ve her defasında return (new UserRepository)->fetch($id); yapılmış olsaydı $user2 nesnesinin getName metotu Veli sonucunu döndürecekti.

Ayrıca cachelendiği için UserRepository sınıfındaki fetch metotu da 1 defa çalıştı. Buradaki isset işlemini SELECT sorgusu olarak düşünebilirsiniz.

Ayrıca Bkz.: Optimistic Offline Lock

9 Kasım 2014

Posted In: Genel, Gezegen

PHP – Redis ile Pub/Sub İşlemi

Redis, kendi içerisinde pub/sub (publish/subscribe) yapılmasına olanak sağlıyor.

Peki pub/sub pattern nedir?

Pub/sub pattern (desen), mesajlaşma pattern’ı olarak geçer. Temelinde; takip edilen bir olayın, takipçilere duyurulması yatar.

Gerçek hayattan örnek verirsek: Öğretmen publish (pub) görevini üstlenir. Öğrenciler ise subscribe (sub) görevini üstlenir. Öğretmen sınav sonuçlarını panoya asar. Öğrenciler de sınav sonucunu bekledikleri için sürekli gözleri panoda bir haber beklerler.

Öncelikle öğretmen görevini yani pub kısmına gözatalım:

pub.php

$teacher = new Predis\Client(array('host' => '127.0.0.1'));

$teacher->publish('Pano', 'Ali, sinavdan AA aldin.');

Gördüğünüz gibi öğretmen Pano’ya Ali isimli öğrencinin sınav bilgisini girdi. Ali de Pano kanalına (channel) aktif olarak abone.

Ali isimli öğrenci Pano kanalını ise şöyle dinleyebiliyor:

sub.php

ini_set("default_socket_timeout", -1); // Ilgili socket surekli dinleniyor

$client = new Predis\Client(array('host' => '127.0.0.1'));

$redis = new Predis\PubSub\DispatcherLoop($client);

$redis->attachCallback('Pano', 'showResult');

$redis->run();

function showResult($data) {
    static $i = 0;
    echo ++$i . '. ogrencinin sonucu aciklandi: ' . $data . PHP_EOL;
}

Deneme yapabilmek için öncelikle sub.php dosyasını ardından pub.php dosyasını çalıştırın. Böylece ilk önce kullanıcıyı Pano isimli kanala abone ediyorsunuz ve artık Pano’dan gelecek mesaajı ekrana basmaya hazır oluyor. Daha sonra pub.php ile Pano‘ya veri giriyorsunuz.

pub.php dosyasını biraz genişletelim. Öğretmen daha çok sınav sonucu açıklasın.

$teacher = new Predis\Client(array('host' => '127.0.0.1'));

$students = array('Ali', 'Ayse', 'Veli', 'Hasan', 'Fatma', 'Oguz');
$results = array('AA', 'BA', 'DC', 'CC', 'AA', 'BA');

for($i = 0; $i < 6; $i++) {
    $teacher->publish('Pano', $students[$i] . ', sinavdan ' . $results[$i] . ' aldin.');
    sleep(1);
}

Yeni pub.php dosyası ile öğretmen, iki dizideki verileri eşleştirerek birer saniye aralıklarla Pano’ya sınav sonuçlarını koyuyor.

Ayrıca bkz.: Observer Design Pattern

5 Aralık 2013

Posted In: Genel, Gezegen, php, pub/sub, redis

PHP – Symfony Component’i ile Dependency Injection

Nesne yönelimli programlamada bazı nesneler birbiri ile bağlantılı olmak durumunda kalabiliyor. Ancak bu “bağlama” işlemleri için eğer doğru bir yazılım tasarımı yapılmazsa, kodun “maintain” (sürdürmek) edilebilmesi oldukça zorlaşır. Özellikle kodun maintain edilebilmesi için nesnelerin birbirlerine tightly coupled (sıkı bağlama) değil de loosely coupled (gevşek bağlama) olarak bağlanması gereklidir.

Birbiri ile bağlantılı nesnelerin yine birbirlerine “enjekte” edilebilmesi için arada bir framework olmalı (framework olmadan alternatif çözüm üretmek de mümkün). Aslında dependency injection kavramı tam bu kapıya çıkıyor. Nesnelerin bir framework aracılığıyla diğer nesnelere enjekte edilmesidir dependency injection.

PHP’de ise dependency injection için birçok framework var. Ancak bunların da birçoğu outdated (zaman aşımına uğramış).

Bu işler için Symfony‘nin kendi içinde bir dependency injection component’i bulunuyor.

Yazının devamında bulunan kodda, Symfony’nin dependency injection component’i ile yazdığım bir örneği görebilirsiniz.

Money sınıfı iCurrency interface’ine loosely coupled olarak bağlı. Böylece iCurrency‘den türetilen herhangi bir sınıfı kendi içerisinde çalıştırabilecek.
Ancak arada bir interface olmamış olsaydı, doğrudan Dollar sınıfına bağlansaydı, ileri de Euro para birimi kullanılacağı zaman bir de ekstra olarak Money sınıfının bağımlılığı düzenlenecekti.

İlgili kodu görmek için buraya tıklayın.

İlgili kodun PHPUnit ile yazdığım Unit Test’lerine buradan ulaşabilirsiniz.

1 Ağustos 2013

Posted In: Genel, Gezegen

Bir yazılım stajı nasıl olmalı?

Güzel memleketimin dört bir köşesinde, her yıl binlerce genç, yazılım üzerine staj yapıyor. Ben de bir yazılım stajının nasıl olması gerektiği konusunda aklımda olan düşünceleri paylaşayım dedim.

Doğrusu yanlışı, eksiği fazlası benim düşüncemdir.

Başlayalım…

Staj, iş değildir!

Staj yaparken, iş nasıl yapılır onu öğrenirsiniz. Bunun için staj süresince çok iyi bir gözlemci olmalısınız. Kim nasıl çalışıyor iyi irdelemelisiniz. Bu, ‘kim yatıyor kim çalışıyor’ onu bulun demek değil.

İpuçları almaya çalışın

Olabildiğince yazılım geliştirme konusunda ipuçları almaya çalışın. Mümkün olduğunca yazılım geliştirme teknikleri konusunda çalışanlardan bilgi almaya çalışın. Öğreneceğiniz her bilgi ileride çok işinize yarayabilir. Mesela “hangi işletim sistemini kullanmalısınız” bilgisi oldukça önemli bir ipucu olabilir size (Linux forever!).

Kimlerle çalışacaksınız gitmeden önce öğrenin

Başvuru yapacağınız şirketin sayfasında eğer çalışanlar sayfası varsa iyice bir inceleyin orayı. Şirkette kim varmış kim yokmuş öğrenin. Eğer çalışanlar sayfası yoksa LinkedIn bu konuda size yardımcı olabilir.

Ayrıca çalışanların LinkedIn profillerini ve varsa bloglarını bulmaya çalışın. Bu şekilde çalışacağınız kişilerin hangi konularda bilgili olduklarını tespit edin.

Böylece kabul edilirseniz, staj süresince “aa bu adam bu konuyu biliyordu, dur gidip bir sorayım” diyebilirsiniz.

Şirket değil yazılımcı seçin!

Şirketten öte, şirkette çalışan yazılımcıları iyi araştırın. CV’nize yazacağınız şirketin mutlaka bir şekilde etkisi olacaktır. Ancak staj süresince edineceğiniz bilgi bundan daha önemlidir, bunu unutmayın.

Çok büyük bir X firmasına staj yapmak için girdiniz. Yaptığınız işler ufak tefek sayılamayacak kadar önemsiz olabilir. Doğal olarak o şirketten herhangi bir şey öğrenmeden ayrılmış olacaksınız.

Ama X firmasına göre daha ufak bir Y firmasında iyi bir yazılımcıyla stajınızı yaparsanız ve stajı gerçekten kaliteli işler üreterek tamamlarsanız bu sizin açınızdan daha faydalı olacaktır.

Mutlaka en az bir tane sistemci

Çalışacağınız yerde en az bir tane sistem yöneticisi olmasına dikkat edin. Hem yazılım üretip hem de sistemle ilgilenen kişilerden bahsetmiyorum. Mesleki sıfatı sistem yöneticisi olan ve sadece sistem yönetimiyle ilgilenen kişi veya kişilerin olmasından bahsediyorum.

Çünkü staj yapana kadar öğrenciler sistem tarafından pek haberdar olmuyor maalesef. Ara ara “yahu bu adam napıyor ki burada” deyip konuşmaya, fikir almaya çalışın. Çünkü gerçekten tüm sistem o adamın elinden geçiyor.

Aynı yerde birden fazla staj yapmayın

Staj sizin için sektörü tanımak için en uygun zamandır. Eğer birden fazla staj yapacaksanız ikisini de farklı farklı yerlerde yapmaya özen gösterin. Örneğin; bir yerde X diliyle çalışırsanız, diğer yerde Y dili ile çalışabilirsiniz.

Bunun en önemli yanı ufkunuzun açılmasıdır. Farklı “tatlar” denemeniz sizin avantajınızadır…

Naçizane benim aklıma gelenler bunlar, sürç-i lisan ettiysem affola.

Dip not: “E bunca fikri nasıl edindin be adam?” sorusu aklınıza gelebilir diye şöyle bir açıklama yapayım: 2 kez staj yaptım. Birkaç stajyer ile çalıştım. Ama farklı şirketlerde, farklı görevler üstlenen ve sayısını aklımda tutamadığım kadar çok, staj yapmış kişi ile çeşitli sebeplerle yaptıkları staj(lar) üzerinde diyalogum oldu. Bunca fikir staj yapmış kişilerle yaşadığım diyaloglar sayesinde ortaya çıktı.

11 Nisan 2013

Posted In: Genel, Gezegen, staj, stajyer, yazılım stajı

WP Twitter Auto Publish Powered By : XYZScripts.com