Forum: Projeler turna RSS
HtmlHelper üzerine düşünceler
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4539 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: HtmlHelper üzerine düşünceler
Kadir Can kodun şimdiki durumu hakkında ne düşündüğümü sormuştu. Sözümü sakınmadan yazacağım. Amacım hiçbir zaman olmadığı gibi eleştirmek değil. Kod üzerinde böyle düşünmek yararlıdır ve zevklidir. :)

İşlev isimleri: Bazı işlevlerin işleri isimlerine uymuyor

- saveInFile() dosyaya yazıyor ama aslında "a" modu yüzünden hep dosyanın sonuna ekliyor (bu basit bir hata da olabilir). Ya ismi appendToFile() gibi olmalı ya da "w" kullanılmalı

- createBody() de aynı şekilde: metnin ana bölümünü oluşturmuyor, onun sonuna ekliyor; programda birden fazla çağrıldığında her iki yerde de metnin oluşturulduğunu sanabiliriz; oysa sonra çağrılan, metnin öncekinden sonrasını oluşturuyor

- benzer başka işlevler de var

(Biraz ilgisiz olarak, 'functions' da doğru olmamış. createBody()'nin parametre ismi daha doğru olarak 'pieces' olabilirmiş. Ayrıca createHead()'in amacından emin değilim ve o yüzden onun parametre ismi konusunda iyi bir fikrim yok.)

Üye mi olmalı serbest işlev mi: Kabaca iki tür işlev var: HtmlHelper'ın üyelerini değiştirenler ve createTitle() gibi bir string üretip döndürenler. İkinci tür işlevlerin HtmlHelper'ın üye işlevleri olmaları gerekli mi? Bu konu biraz felsefîdir...

Bu konuda uzmanlar da tam olarak anlaşamazlar. Örneğin Bjarne Stroustrup da çoğu nesne yönelimli programcı gibi "herşey bir sınıftır" der. (Aslında yıllardır yakından izlemiyorum; belki de fikri değişmiştir. (?))

İş arkadaşlarımdan birisinin ortalıkta dolaşan işlevlere karşı alerjisi var: o da "herşey sınıfla başlar" fikrindedir.

Ben ise tam tersi görüşteyim: "herşey işlevle başlar." Sanırım bu "herşey algoritmayla başlar" fikrinde olan Alex Stepanov'la uyuşuyor. Ben öncelikle işlevlere iş yaptırırım veya değer ürettiririm.

Sınıf (veya yapı) kavramının ortaya çıkma nedeni ise belirli bir süre yaşaması gereken veya birbirleriyle yakın ilişkisi bulunan verilerdir. Ancak öyle kavramlarla karşılaşıldığında sınıflar oluşur.

Örneğin ben olsam createTitle()'ı hiçbir sınıfa bağlı olmayan serbest bir işlev olarak yazarım. En yararlısı da odur. Çok basit bir işlev olarak etiketi 'title' olan bir HTML elemanı oluşturur ve işi biter.

Bunun yararları:

- hemen altına unittest bloğu yazılır ve başka işlevlerden bağımsız olarak test edilebilir; test edilebilmesi için nesne gerekmediği test sorunları da azdır; yoksa örneğin bir sınıfın üyesi olsa ve o sınıfın kurucu işlevi bazı özel parametreler gerektirse, işlevin test edilebilmesi için önce öyle bir test ortamı oluşturulması gerekir

- kolay test edilebilmesine benzer şekilde, kolay da kullanılır: tek başına olduğunda bir HtmlHelper nesnesine gerek olmadan kullanılabilir

- başka bir grup işlevin parçası olarak görülmediği için kodun anlaşılması daha kolay olur; örneğin HtmlHelper sınıfı da basitleşecektir

Zararı:

- serbest işlev evrensel alana yazıldığında isim kirliliğine neden olabilir; örneğin başka bir modülde de 'foo()' isminde işlev bulunabilir; oysa sınıflar içinde olsalar isimleri çakışmaz. Bu D'de büyük bir sorun değil çünkü zaten modül ismi nedeniyle ayrı isim alanında bulunurlar.

Öte yandan, tasarımı değiştirdiğimizi ve createTitle() yerine addTitle() gibi bir işlev istediğimizi düşünelim. Bu tasarımda addTitle() bir değer üretmesin, bir HTML elemanları dizisine eleman eklesin:

class HtmlHelper
{
    string[] elemanlar;
 
//...
 
    void addTitle(const char[] title)
    {
        elemanlar ~= "<title>" ~ to!string(title) ~ "</title>\n";
    }
 
// ...
}

İşte şimdi üye işlev olması gerekir; çünkü addTitle() artık 'elemanlar' gibi bir dizi üzerinde işleyen bir grup işlevin bir parçasıdır. Ama dikkat ederseniz bizi sınıf kavramına iten, tasarımımız olmuştur. Yani addTitle()'ı "bir sınıfın üyesi oluversin" diye değil, o sınıfın bir üyesinde ('elemanlar'da) değişiklik yapıyor diye üye işlev yapmak zorunda kalmışızdır.

İşte benim anlayışım o. Ama dediğim gibi, uzmanların bile uyuştukları bir konu değil. O yüzden bu yalnızca "ben olsam öyle yapardım" gibi bir konu. :)

Kod tekrarı: Kadir Can, ben gördüğüm kod tekrarlarını göstermekle yetineceğim; çözümleri senin üretmenin daha yararlı olacağını düşünüyorum.

Öncelikle kod tekrarı konusunu neden tekrar tekrar gündeme getirdiğimi söyleyeyim. (Böyle bir tekrarın zararı yok galiba! :p)

Uzmanların bazı alışkanlıklarının uzman oldukları için olmadığı fikrindeyim. Tersine; bazı alışkanlıklar, uzmanlığı beraberlerinde getirirler. Kod tekrarını araştıran yapıda olmak ve onu azaltmaya çalışmak, kişiyi uzmanlaştırır: soyutlama ve kavramları sınıflandırma yeteneği artar, hata oranı azalır, kod mantıklı olur.

htmlHelper modülünde rastladığım kod tekrarları şunlar:

- Şu yapıyı tekrarlayan çok sayıda işlev var:

    string bigger(string text)
    {
        return "<big>" ~ text ~ "</big>\n";
    }
 
    string emphasized(string text)
    {
        return "<em>" ~ text ~ "</em>\n";
    }

Onların tek farkı, kullandıkları eleman etiketi: birisinde 'big', diğerinde 'em'. Onun dışındaki herşey aynı.

Eğer o tekrar bir işleve taşınmış olsa herşey çok daha basit bir hale gelecek. Bir yarar: örneğin herhangi bir nedenle elemanların sonundaki '\n' karakterinin bulunmamasını istesek, bunu tek noktada kaldırmak yetecek. Başka bir yararı: Hatalar azalacak; çünkü o metni oluşturan tek işlevin test edilmiş olması yetecek. (Örneğin createHead() içindeki hâlâ gizli olarak bekleyen hata belki de hiç oluşmamış olacak. ;))

- İşlevler arasındaki o kod tekrarlarının benzerleri bidirectional() ve header() işlevlerinin kendi içlerindeki kodlarda da var.

HTML çıktısı mı üye işlevler mi: Bu sınıfın eninde sonunda bir HTML belgesi (çıktısı) oluşturduğunu biliyoruz. Bütün amacı da zaten o. Peki HtmlHelper sınıfı kullanılırken o belge bir yandan sürekli olarak oluşturulmalı mıdır?

Yoksa HtmlBelgesi türünde bir nesne oluşturulmalı da program kullanıldıkça o nesne mi geliştirilmelidir? Bu, yukarıdaki addTitle() konusuna benziyor. addTitle() gibi bir işlev olsa, HTML belgesini temsil eden nesneye bir 'title' elemanı eklemiş olur. Hepsi odur. Bütün HTML çıktısı en sonunda o nesnenin çıktı() işlevi ile edinilebilir.

Kısaca fark şu:

- yola devam ettikçe char[] biçiminde HTML çıktısı mı oluşturulsun?

- HTML sayfasını temsil eden bir nesne mi oluşturulsun, ve sonunda çıktı ondan mı edinilsin?

Bütün bunların felsefî oldukları düşünülebilir; eğer program çalışıyorsa kimsenin fazla bir şey söylemeye hakkı yoktur. Ama kodun sağlığını önemsiyoruz. Her aşamada benzer düşünceler içerisinde ve dikkatle kodlamak gerekiyor. Yukarıda da dediğim gibi, kesin doğru veya yanlış yok. Bunlar üzerinde düşünmek güzel. :)

Ali
Kadir Can #2
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bunlar oldukça iyi.Hatta verdiğiniz yararlı bilgiler de oldukça iyi.Ayrıca sözünüz de çok güzel:
"Uzmanların bazı alışkanlıklarının uzman oldukları için olmadığı fikrindeyim. Tersine; bazı alışkanlıklar, uzmanlığı beraberlerinde getirirler."
Artık kod yazarken daha dikkatli olacağım.

Hepsini de yapacağımdan şüpheniz olmasın.
Kadir Can #3
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bir kaç değişiklik yaptım.Pull request atıyorum.Yeni haline de bakar mısınız?
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4539 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Teşekkür. Ben bir kaç yorum yaptım.

Soru: Her satıra yaptığım yorum sana nasıl geldi? Ayrı e-mail'ler olarak mı? Hepsini birden yollama seçeneği göremedim. (?)

Öneri: Eğer pull request gönderdiğini yalnızca bana söylüyorsan yorulmana değmez; zaten e-mail geliyor. :)

Teşekkür,
Ali
Kadir Can #5
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
5 ayrı notification şeklinde geldi.Onları da düzeltirim.

Kod standartları dışında kodun genel durumu nasıl?

Not:Şimdi kapatıyorum.Dediklerinizi yarın yapacağım.
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4539 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Kodlama standardı dışında benim hoşuma gitti. :)

createComment'te istenmeyen bir durum olacağını farkettim ama yine de XML standardına uygun oluyor galiba:

<!-->açıklama</!-->

Ama alıştığımız gibi değil:

<!-- açıklama -->

İstersen onu da downLine() gibi özel olarak bırakırsın.

Ali
Kadir Can #7
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Doğru.Bir an aklımdan çıkmış.Birden çok parametre ile çalışan işlevleri bırakalım mı,yoksa onlara da bir işlev yazalım mı?Bu hususta ne dersiniz?
Kadir Can #8
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yalnız bir sorunum var.Pull request atamıyorum.Açık pull request var diyor.Ne yapacağız?
Avatar
Salih Dinçer #9
Üye Ock 2012 tarihinden beri · 1913 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Önceki projelere bakıyordum ve bu sene bunların canlanmasını temenni ederek sözlerime devam ediyorum...:)

Ali hocamın burada yer verdiği yorumları değerli. Hatta projenin dışına çıkıp programlama teknikleri hakkında güzel ifadelerde bulunmuş. O yüzden biraz olsun öne çıkarmak istiyorum.

Ayrıca bu modülün sınıf haline dönüşüp son hali şu iletide bitirilmiş olduğunu belirtmeliyim:
http://ddili.org/forum/post/6284

Web çatısı hakkındaki düşücelerimi de ilerleyen günlerde, ilgili başlık altında dile getirmeye çalışacağım...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
zekeriyadurmus #10
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Salih hocam web çatısı içerisine bir CGI sınıfı oluştursak nasıl olur? RhS yi apache, nginx gibi sunucularda çalıştırmak için bir sınıf veya başka bir şey yapmayı düşünüyorum. Bunu turna için yapıp RhS içerisinde turnayı kullanabiliriz. Ne dersiniz?

Zekeriya
Bilgi meraktan gelir...
Avatar
Salih Dinçer #11
Üye Ock 2012 tarihinden beri · 1913 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Evet, projelerin birbirleri ile uyumlu olması ve birlikte geliştirilmeleri çok hoş sonuçlar doğurabilir...:)

Düşünsenize; dünya nüfusuna göre azınlık kalan yüz binlerce insan kod geliştiriyor. Ne için? Bilgisayar ve/veya teknolojik aygıt kullanabilen diğer milyonlarca (belki milyarlarca) insan için. Temelde benzer şeyler yapıyoruz ve işimize geliyorsa bunları kütüphaneler halinde kullanıyoruz. Bazen hız ve güvenlik gerekçeleri ile tekerleği (bilgiyi) baştan icat etmesek de en azından saf/güvenilir taş parçasını alıp alışık olduğumuz kurallar çerçevesinde yontuyor ve yuvarlıyoruz...

Offf çok uzatttım yine...

Bakınız şurada Java mimarisini kullanarak adamlar nasıl bir çatı yapmış:
[Resim: https://vaadin.com/image/image_gallery?uuid=453a301a-798c-4daf-aea7-3fd115c0d88a&groupId=10187&t=1349442259604]
https://vaadin.com/learn

Bana biraz yavaş geldi ama HTML5'i de destekleyip enteresan örnekler sunabilmesi hoş...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Forum: Projeler turna RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-12-18, 01:00:56 (UTC -08:00)