Monday, June 15, 2009

www.bahele.com beta versiyonu yayında

Günlük yazmak gerçekten zor bir iş. Düzenli olarak kaliteli yazılar yazan blog yazarlarını çok kıskanıyorum. Notlarım arasında yazılmayı bekleyen 20-25 tane yazı var. Ne zaman bilgisayarın başına oturup birisini yazayım desem hemen dikkatim dağılıyor. Google Reader içindeki yazılara dalıp gidiyorum. İnternetten bugüne kadar çok şey öğrendim. Hep al hep al olmuyor, biraz da benim internete birşeyler katmam lazım diye düşünüyorum.

Bu günlükteki 41. yazımda (41 kere maşallah :) ) son 4 aydır uğraştığım bir web sitesini tanıtmak istiyorum. Liseden arkadaşlarım Sefa ve Taylan ile beraber hayata geçirdiğimiz bu eğlenceli web sitesinin adresi http://www.bahele.com. Eğlenceli diyorum çünkü biz yaparken çok eğlendik umarım sizler de kullanırken çok eğlenirsiniz.

Bahele.com nedir?

Bahele.com, insanların sevdiklerini ve sevmediklerini tüm internet ile paylaşabilecekleri bir sosyal ortamdır. Sevdiklerinize, onları sevdiğinizi söylemek size de zor geliyorsa bahele.com tam size göre. Bahele.com'u benzer diğer web sitelerinden ayıran en önemli özelliği facebook-connect alt yapısını kullanmasıdır. Facebook-connect sayesinde bahele.com'u mevcut facebook hesaplarınız ile kullanabilirsiz. Bahele.com'da yazdığınız mesajlar isterseniz facebook profilinizde yayınlanır. Bahele.com ile ilgili detaylı bilgiyi yardım sayfalarında bulabilirsiniz.

Ben bu yazıda bahele.com'u yaparken hangi teknolojileri kullandık ondan bahsetmek istiyorum.


  • Siteyi django web framework kullanarak kodladık. Daha önceden java ile web uygulaması geliştirme tecrübelerim olmuştu. Java ne kadar güçlü bir dil olsa da konu kısa sürede çalışır projeler ortaya koymak olunca python'un eline su dökemez.
  • Veritabanı olarak sizin de tahmin edebileceğiniz gibi mysql kullanıyoruz.
  • Veritabanı işlemlerini biraz da olsa rahatlatmak için memcached kullandık. Şimdilik çok fazla trafik gelmiyor ama ileride trafik arttığında veritabanı sorgularını azaltacağı için önbellek çok işimize yarayacak biliyorum.
  • Facebook ile entegrasyonu pyfacebook API ile yaptık.
  • Siteyi webfaction'da barındırıyoruz. İnternette yaptığım araştırmalar sonucunda webfaction'ı seçtim. Şimdiye kadar ki gözlemlerim seçimimde hata yapmadığımı gösteriyor.


Geçen 4 ay içinde akşamları ya da haftasonları vakit buldukça kodladığım bu web sitesi beni çok heyecanlandırıyor. 9 milyonu aşkın Türk abonesi olan bir platform (facebook) ile entegre çalışabilen bahele.com django kullanarak yaptığım ilk web uygulaması. Bakalım bahele.com'un geleceği nasıl olacak? İnternetin karanlık sularında kayıp mı olacak yoksa hatırı sayılır bir ziyaretçi kitlesine mi sahip olacak. Bunları zamanla göreceğiz.

Sunday, January 18, 2009

Java IntegerCache

Şirkette yazdığımız bir kodu Eclipse FindBugs plugini ile incelerken kodun sarı renkli böcekler tarafından istila edildiğini gördük. Integer sınıfını kullandığımız hemen hemen her sınıf içinde FindBugs bize aşağıdaki uyarıyı veriyordu:
Method invokes inefficient Number constructor; use static valueOf instead

"Yav bırak allah aşkına, alt tarafı bir Integer yaratacaksın" deyip FindBugs uyarısını görmezden gelme varsayılan davranışımdır fakat bugün can sıkıntısının da etkisi ile Java SDK içindeki Integer sınıfının koduna baktım. "new Integer(5)" ile "Integer.valueOf(5)" arasında ne gibi bir fark olabilir çok merak ediyordum. Integer.java sınıfı içerisinde fark yaratan kod aşağıdaki IntegerCache sınıfıymış. JVM sizin için 256 adet tam sayıyı önbelleğe alıyor. -128'den +127'ye kadar olan tam sayılar için Integer.valueOf size hep aynı Integer instance'ını veriyor.

private static class IntegerCache {
private IntegerCache(){}

static final Integer cache[] = new Integer[-(-128) + 127 + 1];

static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}

/**
* Returns a Integer instance representing the specified
* int value.
* If a new Integer instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Integer(int)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param i an int value.
* @return a Integer instance representing i.
* @since 1.5
*/
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}

Küçük bir örnekle konuya nokta koymak istiyorum. Bğyle ufak tefek performans optimizasyonları ile işim olmaz fakat java 1.5'ten beri aktif olan bu özelliği daha yeni öğrendiğim için ilgimi çekti sizinle de paylaşmak istedim.

public class IntegerCacheTest {
public static void main(String[] args) {
Integer int1 = Integer.valueOf(5);
Integer int2 = Integer.valueOf(5);
Integer int3 = new Integer(5);
Integer int4 = 5;
if ( int1 == int2) {
System.out.println("int1 ve int2 ayni instance.");
}
if( int1!= int3) {
System.out.println("Fakat int1 ve int3 farkli instance'lar");
}
if (int1 == int4) {
System.out.println("int1 ve int4 de aynı instance");
}
if (int1.equals(int2) && int2.equals(int3) && int3.equals(int4)) {
System.out.println("ve son olarak hepsinin değeri aynı :)");
}
}
}

Yukarıdaki kod parçasını çalıştırırsanız aşağıdaki gibi bir çıktı alırsınız.
int1 ve int2 ayni instance.
Fakat int1 ve int3 farkli instance'lar
int1 ve int4 de aynı instance
ve son olarak hepsinin değeri aynı :)

Fakat bu sonuç sizi beni şaşırttığı kadar şaşırtmayabilir :)

Friday, January 9, 2009

Akış Diyagramı

http://xkcd.com/518/ adresinden :

Thursday, January 8, 2009

Web uygulamasını deploy ederken python yardımı

Yazdığım bir web uygulamasının dosyalarını web sunucusuna ftp ile göndermeye çalışırken çektiğim eziyet yüzünden aşağıdaki özellikleri içeren bir script yazmaya karar verdim.
    Script;
  1. Benim seçeceğim bir klasör altındaki tüm dosyaları tarayacak.

  2. Benim belirteceğim süre içerisinde güncellenmiş dosyaları bulacak.

  3. Bulduğu dosyalar CVS (.cvs) ya da SVN (.svn) tarafından kullanılan dosyalar olmayacak

  4. Seçilen dosyaları belirteceğim bir sunucunun belirteceğim bir klasörüne secure ftp ile kopyalacak.

Python standart library içerisisinda ftp istemcisi için ftplib modülü bulunuyor. Fakat bu modül güvenli bağlantıyı (SSH2) desteklemiyor. Bu devirde de ssh haricinde bağlantı kabul eden hosting firması yoktur diye tahmin ediyorum. Google'a arama yaparken Paramiko adındaki modülü buldum. Eğer easy_install kurulu ise paramiko'yu kurmak çok kolay. Burada paramiko kurulumundan bahsetmeye gerek yok zaten README dosyasında detaylı bir şekilde anlatmış adam. Bir hayırsever de paramiko modulünü almış ve üzerine basitleştirilmiş, http://media.commandline.org.uk/code/ssh.txt adresinden indirebileceğiniz python kodunu yazmış. Ben de bu kadar hazır yazılmış kodun üzerine asağıdaki satırları yazdım.

import subprocess
import sys
from ssh import Connection

if len(sys.argv)<4:
print 'usage : python ' + sys.argv[0] + ' source_dir destination_dir hour(s)'
sys.exit()

source_dir = sys.argv[1]
destination_dir = sys.argv[2]
minutes = 60 * int(sys.argv[3])

findCommand = 'find ' + source_dir + ' -type f -mmin -' + str(minutes)
process1 = subprocess.Popen(findCommand.split(), stdout=subprocess.PIPE)
process2 = subprocess.Popen('grep -v .svn'.split(), stdin=process1.stdout, stdout=subprocess.PIPE)

files = process2.stdout.read().strip().split('\n')
host = 'HOST'
username = 'USER'
password = 'PASSWORD'
print 'connecting to ', host
ftp = Connection(host, username=username, password=password)
print 'connected.'
for file in files:
local = file
remote = destination_dir + file.split(source_dir)[1]
print 'sending file ', local, ' to ', remote
ftp.put(local, remote)
ftp.close()
print 'connection closed.'

Yeni güncellenmiş dosyaları bulup bunlar arasından SVN(subversion) dosyaları ayıklamak için linux find ve grep komutlarından yararlandım. Örneğin:
find . -type f -mmin -60 |grep -v 'svn'

komutu bulunduğun dizindeki dosyalardan (klasörler hariç) son 60 dakika içinde güncellenenleri bulur. (subversion dosyalari hariç)
Python ile sistem komutlarını çalıştırmak için subprocess modülünü kullandım. Subprocess modülü ile
  • Sistem komutları çalıştırılabilir.
  • Bir process'in çıktısı başka bir process'e girdi olarak yönlendirilebilir(pipe)
  • Çalıştırılan process'in çıktısı python script'i içinden okunabilir.

Yukarıdaki script'te find komutu çıktısı subprocess modulu yardımı ile grep komutuna veriliyor ve sonuç grep process'inin stdout alanından okunuyor. Yukarıdaki script'i ftp.py olarak kaydettim. /home/ilkinulas/projects/webapps/test dizini altındaki son 5 saat içinde güncellenmiş dosyaları ftp ile web sunucusundaki /home/ilkinulas/webapps/ dizinine atmak için aşağıdaki komutu yazmak yeterli oluyor.
python ftp.py /home/ilkinulas/projects/webapps/test /home/ilkinulas/webapps 5

Thursday, December 4, 2008

Django uygulamasını deploy etmek


Django uygulamamı deploy ederken karşılaştığım sorunu ve sorunun çözümünü paylaşmak istiyorum. Bilişim Terimleri sitesi deploy teriminin Türkçe karşılığı icin yerleştirme, konuşlandırma terimlerini kullanmış. Fakat bu karşılıklar bana biraz komik geldiği için ("Abi dün gece uygulamayı yerleştirirken problem oldu" gibi), ben "deploy" terimini Türkçeye çevirmeden kullanmaya devam edeceğim.

Bu yazıda bahsettiğim Django (cango diye okunuyor) Tatlı Kaçıklar dizisinde oynayan Mehmet Ali Erbil'in köpeği değil Python ile geliştirilmiş bir Web Framework. Python ile geliştirilmiş onca web framework arasından Django'yu seçmemin nedeni çok iyi bir dokümantasyona sahip olması (gerçekten çok iyi, abartmıyorum) ve web sitesinde yapılan şu Django tanımı oldu :

Web Framework For Perfectionists With Deadlines


Kısaca Django reklamı yaptıktan sonra ana meseleye gelelim. Yazının bundan sonrası Django ile ilgilenmeyenler için sıkıcı olabilir baştan söyleyeyim.
Django, uygulama ayarlarını setting.py dosyasından okur. Genelde development ve test yaparken kullandığınız ayarlar ile production ortamında kullandığınız ayarlar aynı olmaz. En basit örneği database ayarları: url, database adı, kullanıcı adı, şifre gibi.. settings.py dosyasını production sunucusuna upload ettikten sonra her seferinde gidip settings.py'de production ayarlarını yapmak bir süre sonra insanı bayar. Uygulamayı deploy ettikten sonra sağını solunu değiştirmeden çalıştırabilmek için setting.py dosyasına aşağıdaki numarayı çekiyoruz: (Dosyanın sonuna bu satırları yazıyoruz)

try:
from settings_local import *
except ImportError:
pass

Bu sayede Django settings.py'deki ayarları yükledikten sonra settings_local.py dosyamızdaki ayarları yükler. settings_local.py dosyasında development ve test platformunda kullanmak istediğimiz ayarları yazarız. settings_local.py dosyasını production sunucusuna upload etmemize gerek yok, çünkü bu dosyada çalışma ortamımızın production ortamından farkını yazıyoruz. Örnek bir settings_local.py dosyası şu şekildedir:

DEBUG = True

DATABASE_ENGINE = 'mysql'
DATABASE_NAME = 'tututil'
DATABASE_USER = 'nikli'
DATABASE_PASSWORD = 'drowssap
DATABASE_HOST = ''
DATABASE_PORT = ''

MEDIA_ROOT = '/var/www/GOF'
MEDIA_URL = 'http://localhost/gof/'

settings_local.py dosyası settings.py ile aynı klasörde olmalıdır. Dosyalarınızı FTP ile production sunucusuna gönderirken aman dikkat edin settings_local.py dosyasını göndermeyin.

Wednesday, October 29, 2008

Sonunda evlilik telaşı bitti

22 Ekim'de balayı tatilinden dönüp, 23 Ekim'de iş başı yaptım. Daha yeni yeni tatil havasından çıkıyorum. Söz verdiğim gibi yazılara evlilik sonrası daha çok zaman ayıracağım.

Geçenlerde günlüğe yeni bir yazı yazmak için kolları sıvamıştım ki ne göreyim TELEKOMÜNİKASYON İLETİŞİM BAŞKANLIĞI yine yapacağını yapmış; Blogger servisine Türkiye'den erişimi kapatmış. Tünel servisleri aracılığı ile erişim açık olmasına rağmen içimdeki yazma hevesini kırdığı için tatil sonrası ilk yazım bugüne kadar sarktı.

Balayı tatilimiz için Nurten'le Maldivler'e gittik. Yüzlerce adadan oluşan bu ülkede kendi bütçemize göre bir ada seçtik ve çantamızı sırtlanıp Maldivler'in yolunu tuttuk. Katar aktarmalı 10 saatlik bir uçak yolculuğundan sonra Maldivler'in başkenti Male'ye ulaştık. Male'den tatilimizi geçireceğimiz Sun Island adasına transferimiz de deniz uçağı ile oldu. Yeryüzündeki cennete benzetilen Maldivler'de 6 gün geçirdikten sonra gözümüz arkada kalarak dönüş yolculuğuna başladık.

http://picasaweb.google.com/ilkinulas/MaldivesEkim2008 adresinde tatilde çektiğimiz fotoğraflara göz atabilirsiniz.

Aşağıda fotoğraf makinası ile çektiğim ve benim ilginç olduğunu düşündüğüm videolar var. İlk video Sting ray denilen balığın (bu balığın türkçe ismini bilmiyorum. Bilen varsa söylesin lütfen) kendini insanlara nasıl sevdirdiğini, insanların elinden nasıl yemek yediğini görebilirsiniz.



İkinci videoda ise su altı kamerasına alternatif olarak su üstü kamerası ile yaptığım çekimleri izleyebilirsiniz :)



Maldivler bizim için unutulmaz bir deneyim oldu. İlk başta Maldivler'de bir hafta tatil için harcayacığımız para ile Türkiye'de bir ay tatil yaparız diye düşünüyordum. Fakat beyaz kumlar üzerinde güneşlenip,ılık okyanus suyunda mercanlar ve rengarenk balıklar arasında yüzdükten sonra balayımız için Maldivler'i seçmenin ne kadar iyi bir tercih olduğunu anladım.

Friday, September 26, 2008

Evleniyorum...


Selam dostlar, uzun zamandır yazamadım. Bu suskunluğumu güzel bir haberle bozayım dedim. 11 Ekim 2008'de memleketim Denizli'de evleniyorum. 8 Ekim 2008 Çarşamba günü İstanbul, Salon Palmina'da bir düğünümüz var, hemen sonrasında 11 Ekim Cumartesi Denizli'de nikah törenimiz var. Tüm dostlarım davetlidir.

Evlilik telaşı biter bitmez yazılarıma devam edeceğim.