Categories: Yazılım, Algoritma Soruları
bir sayının 2 üzeri olup olmadığını bulmak
May 16th, 2009Yetki kontrolleri için hazırladığımız kütüphanede ihtiyacımız olduğundan ve birazda enteresan bir problem olduğu için buraya da yazmak istedim.
elinizdeki herhangi bir sayının 2 üssü bir sayı olup olmadığını kontrol edecek bir fonksiyon yazın. hızlı çalışması için optimize edin.
örneğin;
8 (2 ^ 3) için true verecek.
128 (2 ^ 7) için true verecek.
132 için false ferecek.
not : hızlı çalışması gerektiği için logaritma gibi fonksiyonlar en son seçenektir.
Kodlarken yapılan seçimler önemlidir
November 25th, 2008Kod yazdığınız her an farkında olmadan seçimler yaparsınız. Bu seçimleriniz bazen iyi bazen kötü olabilir.
Mesela gündelik olarak yazılabilecek en basit;
Code:
public void List(string[] values) | |
{ | |
foreach(string s in values) | |
Console.WriteLine(s); | |
} |
şeklinde yazdığınız bir kod bir süre sonra;
Code:
public void List(string[] values) | |
{ | |
if ( values != null ) | |
{ | |
foreach(string s in values) | |
Console.WriteLine(s); | |
} | |
} |
şekline dönüşür. Aylar sonra bir türlü anlayamadığınız bir hatanın peşine düşüp saatlerde "neden çalışmıyor bu!?" diye sorular sonrasında aşağıdaki gibi bir seçim yapmış olmayı dilersiniz.
Code:
public void List(string[] values) | |
{ | |
if ( values == null ) | |
throw new ArgumentNullException("values"); | |
| |
foreach(string s in values) | |
Console.WriteLine(s); | |
} |
"parametre null geldiği zaman ses çıkarmamak; bu bir tasarım mıdır yoksa hata mıdır ?" diyerek günü kapatırsınız.
Bu tür hatalarla yeterince uğraştıktan sonra da null değer alabilen parametre yazmak gerektiğini, ArgumentNullException kullanılması gerektiğine karar verirsiniz.
Belkide kod yazarken ilerde bakımını yapacak kişinin ev adresinizi bilen, kana susamış bir piskopat olduğunu varsayarak birden fazla kez düşünmelisiniz.
kod kalitesi üzerine
September 20th, 2008Bir yazılımın kalitesini ölçerken hafıza kullanımı, performans, stabil kalma, hata adedi, yazılımcı "din"i inançlarına uygunluk vs gibi ölçekler kullanırsınız peki karşınızda duran kod dosyası için kaliteyi nasıl ölçersiniz?
Bakalım;
- Satır adedi?
- Hız?
- Okunabilirlik?
- Notlar (Comments)?
- Hata kontrolleri ?
Siz bu listeye istediğiniz kadar aklınıza gelenleri ekleyebilirsiniz ve hepsi pasta'nın bir dilim'ini paylaşır. Bazılarından ödün verip diğerini yükseltebilirsiniz ancak hangi dilimlerin daha çok yer kaplayacağı asıl sorundur.
Satır Adedi
Bazı yazılımcılar (-ki buna kendimi tutamayıp bende dahil oluyorum) ürettikleri yazılımın satır adedi ile övünürler. Aslında satır adedinin yüksek olması her zaman (ama her zaman) kötüdür. Satır adedinin artması yazılımın karmaşıklaşması, bakımının zorlaşması, hatalı/kötü/bilmeden bir "reuse" yada varsa object oriented kullanımının işaretidir.
Aynı işi yapan 2 yazılım için satır adedi daha düşük olan'ın yönetimi her zaman için daha kolaydır. Herhangi bir hata olması durumunda neden'i bulmanız her zaman daha kısa sürecektir. Bu yüzden mümkün olduğu kadar satır adedini az tutmak gerekli.
Satır adedi daha çok projenin boyutu ile ilgili bir ölçektir. Fazlası her zaman kötüdür.
Gerekmediği sürece yeni bir satır eklememek ilerideki saçlarınızın yerinde ve koyu renkte kalmasına yardımcı olur.
Hız
Hızlı çalışan bir yazılım her zaman için tercih edilir ancak bu konuda 2 kez düşünmek gerekli.
Okunabilirliği yüksek ama yavaş çalışan bir kodu, bakınca kimsenin hiç bir şey anlamadığı ama hızlı çalışan bir kod'a çoğu zaman tercih etmeniz gerekir.
Neden?
Eğer tek başına bir yazılım geliştiriyorsanız bu çoğu zaman sizin için bir sorun yaratmaz ama bir ekip ile çalışıyorsanız ekip'deki herkesin sizin becerilerinize sahip olması gibi bir imkanınız olmayacaktır.
Yazılımın içinde bu hızlı çalışan ama dokunulamayan kısımları bıraktığınız her parça dönüp dolaşıp size gelecektir.
Yıllar önce yazdığım (-ki şu an ne iş yaptığını bilsem de nasıl yaptığı konusunda en ufak bir fikrim olmayan) bir kod örneği vereyim;
Code:
void putpixel16(int x,int y,unsigned char * segment) | |
{ | |
register unsigned char * vidmem; | |
register unsigned short int packed; | |
| |
vidmem = (unsigned char * ) (segment + ( y * SCREEN_WIDTH + x ) * SCREEN_BYTEPERPIXEL); | |
| |
_asm { mov eax,vidmem } | |
_asm { mov edi,eax } | |
_asm { mov al,ColR } | |
_asm { and al,0f8h } | |
_asm { mov bl,ColG } | |
_asm { and bl,11100000b } | |
_asm { shr bl,5 } | |
_asm { or al,bl } | |
_asm { stosb } | |
_asm { mov bl,ColG } | |
_asm { and bl,1ch } | |
_asm { shl bl,3 } | |
_asm { mov al,ColB } | |
_asm { shr al,3 } | |
_asm { or al,bl } | |
_asm { stosb } | |
} |
ve aynı kodun daha anlaşılabilir hali;
Code:
void putpixel16(dword x,dword y,unsigned char * segment) | |
{ | |
register unsigned short int *vidmem; | |
register unsigned short int packed; | |
| |
vidmem = (unsigned short int * ) (segment + ( y * SCREEN_WIDTH + x ) * SCREEN_BYTEPERPIXEL ); | |
| |
packed = (ColR << 11) | (ColG << 6) | ColB; | |
| |
* vidmem = packed; | |
} |
Bu örnekle putpixel'i (ölümcül doğası itibariyle) c ile yazın demiyorum, sadece örnektir
Eğer ölümcül değil ise her zaman okunabilir olanı tercih etmek, sabahları işe gittiğinizde yüzlerce sorun yerine internetten haber sitelerini gezmenize yardımcı olacaktır.
Okunabilirlik
Bir kod parçasınının okunabilirliği üzerine yüzlerce şey anlatabilirsiniz ancak en iyisi örnek;
Code:
for (int i = 1; i < num; ++i) { meetsCriteria[i] = true; } | |
for (int i = 2; i < num / 2; ++i) { | |
int j = i + i; | |
while (j <= num) { meetsCriteria[j] = false; j += i; } | |
} | |
for (int i = 0; i < num; ++i) { | |
if (meetsCriteria[i]) { Console.WriteLine(i + " meets criteria"); } | |
} |
Bu örnekde tek bakışta işlemlerin nasıl ilerlerdiğini anlamak zor. İşleyişi çözmek için kod üzerinden fazladan 3-5 sn daha geçirmeniz gerekli, bunun yerine aşağıdaki gibi bir düzen daha iyi olacaktır. Okurken gözlerin kamaştığı bir düzen yerine;
Code:
for (int i = 1; i < num; ++i) | |
{ | |
meetsCriteria[i] = true; | |
} | |
| |
for (int i = 2; i < num / 2; ++i) | |
{ | |
int j = i + i; | |
| |
while (j <= num) | |
{ | |
meetsCriteria[j] = false; | |
| |
j += i; | |
} | |
} | |
| |
for (int i = 0; i < num; ++i) | |
{ | |
if (meetsCriteria[i]) | |
{ | |
Console.WriteLine(i + " meets criteria"); | |
} | |
} |
tercih etmeniz her zaman için başkaları ve bir zaman sonra sizin için sağlıklı olandır.
Buna göre her "statement" olarak geçecek bloğu "{" , "}" arasına alabilirsiniz.
Mantıksal olarak ayrı iş yapılan yerlerde boş bir satır bırakabilirsiniz.
Akışı göstermek için indent verebilirsiniz. Ident'ler için her editör/programcı farklı boşluk seviyesi (2,4,8..) kullandığı için editörü Tab karakteri yerine boşluk koymak üzere ayarlarsanız başka birisi baktığında da aynı düzeni görür.
Notlar
Kod içinde yazılan notlar için kötü örneklerde bazen hiç not olmaz yada yazan kişi her satırın ne olduğuna dair kendince açıklamalar yapar. Bu konuda iyileştirme yapmak istiyorsanız her zaman için yazdığınız kodun ne yaptığı yerinde neden bu şekilde olduğuna dair notlar düşün.
Bu mantıkla baktığınızda her satırda açıklama yapmak yada not yazma zahmetini en aza indirmiş olursunuz.
Hata kontrolleri
Bu konu yeni öğrenen yazılımcılar için belkide en çok hata yapılan konu. Bu yüzden biraz daha detay vermeye çalışıyorum. .Net için konuşuyorsak "hata" olarak konuşulan başlık "exception" olarak geçer. .Net dünyasında kontrolü yapılmamış her exception için Windows'un mavi ekranları olarak algılanabilir ve Windows tabanlı uygulamalar için;

yada ASP.Net için

İyi yazılmış bir .Net uygulaması için asla ama asla bu tip ekranları görmemeniz gereklidir. Bunun anlamı hata kontrolleri yeterince yapılan bir uygulamada exception oluşması gereklidir. Exception'ın Türkçe anlamıda zaten "kural dışı durum" olarak geçer.
.Net dünyasında exceptionlar tepeden baktığınız durumda 2 kategoriye ayrılır. Çalıştırma (Execution) hataları yada bug'dan kaynaklanan hatalar.
Örneğin NullReference, InvalidOperation, ArgumentNull gibi hatalar uygulama genellikle bir bug olduğunu gösterir. Bu tür hataları azaltmak için yapabileceğiniz en iyi çözüm parametre alan methodlarda gerekli kontrolleri yapmaktır. Örneğin;
Code:
void Save(Order order) | |
{ | |
Database.SaveObject(order.Customer); | |
Database.SaveObject(order.Order); | |
} |
Gibi bir method içerisinde parametre olarak gönderilen Order tipi objenin null olup olmadığı kontrolü yapılmıyor. Uygulama içerisindeki bir hata yüzünden null parametre gönderildiğinde size bu NullReference exception olarak gözükecektir. Bunun yerine;
Code:
void Save(Order order) | |
{ | |
if (order == null) | |
throw new ArgumentNullException("order"); | |
| |
Database.SaveObject(order.Customer); | |
Database.SaveObject(order.Order); | |
} |
şeklindeki bir kontrol olası hataları daha erken bulmanızı sağlar.
Execution hatalarına örnek olarakda FileNotFound, SerializationException gibi hatalar olabilir. Bu tür hatalarda genellikle yeterince kontrol yapılmadan işlem yapıldığında ortaya çıkar. Örneğin dosyanın varlığını kontrol etmeden dosyayı açmak gibi. Yapılması gereken dosyanın var olup olmadığını kontrol ederek kullanıcının anlayacağı bir mesaj vermek en doğrusudur.
Execution hatalarında elbetteki olası tüm kontrolleri yapmanız mümkün değil ancak sık olabilecek hataları önceden kontrol etmeniz yeterlidir. Bunun dışındaki hatalar için standart exception dialoglarını kendinize özgü hata ekranları ile değiştirmeniz her zaman için iyi bir fikirdir. Böylece handle etmediğiniz bir hata olduğunda uygulamanın size mail atabilmesi, hata log'larına kayıt gibi fantastik imkanlarınız olabilir.
Standart exception dialoglarını değiştirmek için AppDomain.CurrentDomain.UnhandledException event'ini kullanabilirsiniz. Handle edilmeyen herhangi bir exception oluştuğunda bu event tetiklenir. Örnek olarak buradaki adresde bazı bilgiler bulabilirsiniz.
ÜRÜN GELİŞTİRME UZMANI
May 6th, 2008Standart CV sitelerinden bir ilan;
ÜRÜN GELİŞTİRME UZMANI
İşin Tanımı :
İşe kabul edilecek kişi; Ürün geliştirme proje ekibi içerisinde analiz, tasarım, kodlama çalışmalarını gerçekleştirmek, müşteri ortamında kurulum, entegrasyon ve destek hizmet vermekten sorumlu olacaktır.
Aslında bu ilan Türkiye'de ürün geliştirme ve arge projelerine bakış açısının bir özetidir. Yapılan her tür işe "ürün" sıfatıyla bakılması yüzünden bu noktaya geldik.
Belki Ürün ve Proje ayrımlarını bu saatte yapmak belki geç olacak ama olsun;
Üzerinde belki milyonlarca kitap/yazı yazılmış bir konu olan yazılım ürünleri ile diğer "ürün" adı verebileceğimiz bir emek sarfedilen işler/nesneler arasındaki ayrım; ortaya çıkan "şey"in tüm geliştirilme ve hayat döngüsünü etkileyecek kadar önemlidir.
Niyetim bu blog'u okuyan kişilere ürün geliştirme nedir diye öğretmek değil, sadece kendi bildiğim kadar kısmını aktarmaktır.
Ürün'e ait özellikler;
Belirli bir müşterisi yoktur
Kısa boylu insanlar için pantalon üretebilirsiniz ve bu bir ürün olabilir ancak ismi "Ali" olan birisi için dikilen pantalon ancak bir "Proje" olabilir. Çünkü kısa boylu insanlar'ın farklı talepleri (genişlik, desen, renk) olacaktır ve tüm bu talepleri dikkate alarak üretim yaparsınız. İsmi "Ali" olan birisine ait pantalon üretirken talepler sabittir.
Belirli olmayan talepler için üretim yaparken tüm olası parametreleri düşünerek hareket etmeniz gerekir. Bu ürünün geliştirme süresini arttırır ancak yaygınlığı daha fazladır.
Taleplerin belirli olmadığı bir ortam için öncelikle fzibilite yapılmalıdır. (Türkiye'de bunun yerine önce proje geliştirilir ve sonra kullanabilecek başka kim var diye bakılır. Birileri belki bulunur ancak genellikle talepler farklıdır. Belkide temel hatalardan birisi bu). Fzibilite çalışması yapmadan geliştirme yapmanın belki de tek kuralı "Domain Expert" olmanızdır (-ki gönlüm el vermeden yazıyorum bunu). "Domain Expert" olmadan ürün geliştirmeye çalışmak, taleplerin belirli (belki 1 adet?) müşteri grubundan gelmesi demektir, ki genellikle sonucu facia ile biter.
Taşınabilir olmalıdır
Ürün kullanılırken konfigurasyon denilen değişiklikler dışında başka bir müşteride de kullanılabilir olmalıdır. Taşınabilir olması yaygınlığını arttırmanın en temel kuralıdır. Geliştirdiğiniz yazılım taşınabilir değilse onu geliştirildiği yerde bırakıp eskiye dair bilgilerinizle yeniden geliştirmek her zaman için en kısa yoldur.
Özelleştirilebilir olmalıdır
Farklı taleplerin olduğu yerlerde ihtiyacı karşılamak için ürün üzerinde yine "Taşınabilir" özelleştirmeler yapılabilmelidir. Taşınamayan özelleştirmeler ürün ile proje'nin birbirine girdiği noktadır.
Örneğin yazılım içerisinde "ProjeKodu = 12345" benzeri bir satır var ise bu yazılımın tem taşınamaz, hem de özelleştirilemez olduğunun kanıtıdır. (En çok temel yazılımcılar tarafından yapılır bu hata)
Versiyonları vardır
Ürün'lerin önceden biçilmiş bir hayatları yoktur, talep olduğu sürece hayatlarını (gelişerek) devam ettirirler.
Proje'lerde versiyonlar iş tamamlanana kadar (ki bu zaten işin sonudur) devam eder ve geliştirilmesi durur.
Sistematiği vardır
Ürün geliştirilirken izlenen her yolun bir sistematiği ve disiplini vardır. Bu sistematiğin dışına çıkılan her yolda karanlıklar içinde kaybolup kendiliğinizden başladığınız noktaya geri dönersiniz.
Projeler için talepleri karşılamak ilk hedeftir. Bu yüzden her yol mübahdır, en kısa ve en doğru yol ışığa çıkar.
Ürün ve Proje ekipleri farklıdır
Anlayış farkı nedeniyle, geliştirme ekipleri farklıdır. Bu ekipleri birbiriyle karıştırmak projelerin uzamasına, ürün'ün ürün olmaktan çıkmasına neden olur.
Proje'de çalışan ekipler müşterinin talepleri ile güdülme eğilimindedir ve görüş açıları (detayları nedeniyle) ancak proje kapsamındadır.
Ürün geliştirmede çalışan ekipler kendi geçmiş tecrübe ve yaratıcı fikirleri ile güdülür.
Yukarıdaki ilandaki gibi "destek" kısmını ayırmadığınızda hem proje hem ürün ekibiniz dağılır. Sonuçta (ve kısa zamanda) "never ending story" tipi bir sürü yazılım elinizde kalır.
Özet
Kısaca terzi'lerin çalıştığı bir pantalon fabrikası kuramazsınız. İkiside kutsal işlerdir ancak amaçları farklıdır.
Yazılımcı Araçları
April 15th, 2008Yaptığınız işte daha iyi olmak için neler yapabilirsiniz?
Notepad kullanın
Normalde nerde kod yazıyor olursanız olun, kod dosyalarını çift tıkladığınızda notepad ile açılır hale getirin.
Bu hem dosyalara bakmak istediğinizde size hız sağlar hemde IDE olmadığı durumlarda eliniz ayağınıza dolaşmaz.
Notepad2 kullanın
Windows ile standart gelen notepad temel işlerinizi görecektir ama kod üzerinde hafif düzeltmeler yapmanız gereken durumlarda syntax hilighting gibi cici şeylere ihtiyaç duyabilirsiniz.
Ben notepad'e benzediği için notepad2 kullanıyorum, ultraedit gibi daha gelişmiş olanları var ama editor konusunda minimum ihtiyaçları karşılaması yeterli. Böylece kendi makinanız dışında başka yerde çalışırken tekrar eliniz ayağınız dolaşmaz.
Araç Seti Oluşturun
Sık kullandınız araçları bir dizinde toplayın, böylece bir sorun yaşadığınızda elinizde ne olduğunu unutmazsınız.
Kullandığınız araçlara sadece bir tıklama ile uzak olacak şekilde kısayollar oluşturun. Benim yolum desktop'da bir toolbar açarak tüm kısayolları buraya yerleştirmek. Böylece ekranda daima karşımda olan bir araç seti olur. Unutmadan desktop'unuzdaki kaldırabildiğiniz herşeyi kaldırırsanız tüm pencereleri minimize ettiğinizde rahat bir nefes alabilirsiniz.
Araç olarak kullandıklarım;
- regmon
- Registry'e erişimleri loglayan bir araçtır. Programların registry üzerinde ne işe yaptıklarını izlemek için kullanılır
- filemon
- RegMon gibi ancak dosya sistemi üzerinde yapılan işlemleri izlemeyi sağlar
- CSS Reference
- Herhangi bir CSS Reference sayfasına link. Internet olmadığı durumlarda kullanabilmek için ben kendi diskimde tutuyorum.
- DbgView
- DbgView (DebugView) uygulamaların hataları bulmak için yazdığı logları görmek için kullanabileceğiniz bir uygulama. Çoğu uygulama buraya kayıt atmaz ancak kendi uygulamanız içinde System.Diagnostics.Debug yada Trace classlarını kullanarak buraya çıktı gönderebilirsiniz.
- ProcessXp
- Windows ile standart gelen Task Manager'a alternatif olarak kullanabilirsiniz. Bunun yanında .Net processleri ile ilgili bazı bilgilerde veriyor.
- Internet Information Services
- Normalde Control Panel\Administrative Tools altında bulunan bu kısayol web altında geliştirme yaptığınız durumlarda en çok kullanacağınız araçlardan biridir.
- HexEdit
- HexEdit text dışındaki formatlardaki dosyaların içeriğini görmek için kullanabilirsiniz. Gayet minik ve göstermek için dosyanın tamamını okumadığı için gayet kullanılabilir bir araçtır.
- Reflector
- Reflector hem .net kütüphanelerini gezmek hemde içeride ne yapıldığını görmek için kullanabileceğiniz bir decompiler. Çoğu hatanın asıl nedenini bulmak için yardımcı olacaktır.
- Managed Spy
- .Net uygulamarının içeriğini kurcalayabileceğiniz bir uygulamadır. Uygulamanın penceresi içerisindeki nesnelerin özelliklerini çalışırken değiştirmenize izin verir.
- TcpView
- Network bağlantısı yapmış yada yapan uygulamaları izlemek için kullanabilirsiniz.
Bu araçların dışında kendi yazdığım diğer bir sürü uygulamalarda (XmlFormat, Base64Decoder..) ve yıllardır kullandığım bir Dopus uygulaması varki, windows'un içinde preinstalled gelsin istiyorum.
Firefox Kullanın
Web uyumluğuğu, performans, açık kaynak konularını bir kenara bırakın sadece FireBug için bile bu browser'ı kullanabilirsiniz. Internet Explorer nedense gittikçe daha yavaş daha tuhaf daha bişeyler oldukça bu böyle kalacak.
Firefox ile aşağıdaki addonları mutlaka kullanmanızı tavsiye ederim.
- Firebug
- IE Tab
- Linkification
- PDF Download
Beyond Compare Kullanın
Beyond Compare kod dosyalarını karşılaştırmak için para veripde karşılığını alabileceğiniz az adetteki araçlardan biridir. TortoiseSVN ile birlikte kullanma imkanınızda var.
Source Monitor ile istatistiklerinizi izleyin
Source Monitor kodlar üzerinde statik analiz yapmanızı sağlayan bir araçtır. Bu araçla satır adedi, karmaşıklık gibi detaylı raporları görebilirsiniz.
Fiddler
Web üzerinde uygulama geliştiriyorsanız arkada neler olduğunu görmek için kullanabileceğiniz en iyi ve tek uygulama. Kendisini browser'a proxy olarak tanıtıyor ve http işlemlerini izlemenizi sağlıyor.