ile

Hiç Bilmeyenler İçin Nesne Yönelimli Programlamaya Giriş-10 Sayfa Düzeni

Bu yazı Hiç Bilmeyenler İçin Nesne Yönelimli Programlamaya Giriş-9 Şablonlar yazısının devamıdır. Önce onu okumanızı öneririm.

Medium.com adresinde görüntüleyin

Alexey Brodovitch

Web sayfalarında veya basılı mecralarda, hiçbir zaman veriyi, yazıyı resmi olduğu gibi okuyucuya sunmuyoruz. İnsanların yazıları rahatça okuyabilmeleri için, ya da web sayfamızda kaybolmadan dolaşabilmeleri için sayfamızdaki verileri, belirli bir düzen kullanarak sayfaya yerleştirmemiz ve biçimlendirmemiz gerekiyor. Burada web tasarımı yapmanın ilkelerine girmeyeceğim, ancak merak ediyorsanız bu konuyu araştırabilirsiniz.

Örneğin dümdüz veriyi ekrana bastığımızda, bunlardan bir anlam çıkarmak neredeyse imkansızdır.

Arjantin Enflasyon Verisi

Bu yüzden bu verileri mesela grafikler kullanarak anlamlı hale getirmeye çalışırız.

Arjantin Enflasyon Grafiği

Yani amacımız sadece verilerimizin güzel gözükmesi değil, anlaşılabilir olması, uygulamamızın kolay kullanılabilmesi, okunaklı olması, belli amaçlar için aynı veriyi farklı şekilde görüntüleyebilmemiz (yeniden kullanılabilirlik) de aynı zamanda. Sayfa düzeni, veya herhangi bir şeyi tasarlarken, hatta kod yazarken kullanıcıların kolay kullanımını aklımızda tutmamız çok önemli. Ancak kolaylık, basitlik konusunda aklımızda tutmamız gereken diğer bir ilke ise şu:

Her şey olabildiğince basit olmalıdır, ama olabildiğinden daha basit olmamalıdır. Albert Einstein

Bu alıntıyı yapmamdaki sebep şu, siz işleri gelecekteki kullanıcılar kullanacak diye basitleştirmek ve mükemmelleştirmek için uğraşabilirsiniz. Uygulamanın, tasarımın ya da kodun, şurasını veya burasını iyileştirmek için günlerce aylarca uğraşabilirsiniz, ancak mükemmelleştirmeye çalışırken asıl amacı gözden kaçırabilirsiniz. Albert Einstein burada buna parmak basıyor. Bu hatayı 10 yıllık profesyonel yazılım hayatımda çok yaptım. Bu yüzden bu konuyu sürekli aklınızda tutmanızı, mükemmel değil, ama temiz, düzgün, çalışan ve daha sonra düzeltebileceğiniz incelikli prototipler üretmenizi öneririm.

Şimdi, dönelim tekniğe. Daha önceden Dekoratör tasarım deseninden bahsettik, yani bir veriyi alıp HTML etiketlerine sarmalayıp onu temiz bir web sayfası olarak kullanıcıya sunuyorduk. Bir önceki yazıda bunu yaptık. Şimdi veriyi değil de, bu ürettiğimiz bileşenleri de sarmalayabilecek bir yazılım yazalım. Yani Sayfa bileşeni, yan bilgi, ana bilgi, alt bilgi, form gibi bileşenleri barındırsın ve bunları gerektiğinde LEGO gibi birbirine ekleyip çıkarabilelim. Bu tasarım mantığına bileşen tabanlı geliştirme deniyor. Web Components Standardı, React.js, Vue.js bu ilkeyi uygulamalarımızda kullanmamızı sağlayan teknolojiler. Kitabın sonuna doğru bu teknolojilerden de detaylı olarak bahsedeceğim.

Önce daha önce şurada bahsettiğim bileşenleri tek tek listeleyelim.

  1. Head — Her sayfada olacak ama görünmeyecek, css gibi ihtiyaç duyduğumuz dosyaların listesini tutacağımız bileşen. <head> etiketi içinde yeralacak. Sayfanın başlığını belirlediğimiz <title> etiketi burada olacak.
  2. Üst Bilgi — Bütün sayfalarda değişmeyen, logo, üst navigasyon yani yön bulma linklerini, eğer varsa fb veya Twitter’daki gibi üst arama çubuğunu barındıracak, gerekiyorsa kullanıcının çıkış yapıp kendi profilini göreceği açılır menüleri tutacak bileşen. <header> etiketi ile tanımlanıyor.
  3. Yan bilgi — Opsiyonel bir bileşen, genellikle içinde olduğumuz program bileşeninin varsa iç bölümlerinde gezinmemize yarar, yani bu bölümleri link olarak listeler. Bazı programlarda, o an programı kullanan kullanıcı ile bilgileri de listeleyebiliyor.
  4. Ana bilgi — Buna main de deniyor ve <main> etiketi ile tanımlanıyor. Her sayfada bir adet bulunmak zorunda. Eğer bir sayfada önem olarak birbirine eşit farklı bölümler kullanacağım diyorsanız, <section> yani bölüm etiketini kullanacaksınız.
  5. Alt Bilgi — Yine bütün sayfalarda değişmeyecek olan alt bilgi kısmı. Genellikle, sayfaların copyright, telif, gizlilik ve kullanım sözleşmesi gibi sabit kısımları, varsa şirket adresi iletişim gibi bilgiler burada yer almalıdır. <footer> etiketi ile tanımlanır.
  6. Yeniden kullanılabilen bileşenler. Bunlara eleman / element ya da bileşen / component de denebiliyor. Lego gibi programlama amacında olduğumuzdan bu konunun mantığını anlamanız çok önemli. Bunu en kolay şu şekilde anlatabilirim. Örneğin, facebook’ta kendi duvarımızda yeni birşey paylaştığımızda ya da herhangi bir arkadaşımızın duvarında veya bir grupta birşey paylaşmak istediğimizde aynı form bileşeni ortaya çıkıyor ve biz bişiler yazıp gönder tuşuna basıyoruz.

Duvara bişiler yazarken

Gruba bişiler yazarken

İşte bu elemanı (ya da bileşeni) tekrar tekrar yazmamıza gerek yok, belli özelliklerini değiştirip, başka bir sayfada çağırıp kullanabilmemize yeniden kullanılabilirlik deniyor. İşte nesne yönelimli programlamanın bir diğer faydası da bu. Bu konuya da detaylıca sayfa kodunu yazmaya başladığımızda değineceğim.

Yeniden kullanılabilirlik, kod tekrarını önler

DictionaryView ve EntryView isimleriyle yarattığımız dosyaların birbirine benzediğine dikkat edin demiştim. Bir önceki yazıda kod tekrarını önlemekten bahsetmiştim. Şimdi gelin bu iki dosyadan kurtulalım. Program dizinimizin içinde View.php adlı bir dosya oluşturalım ve içeriğini şöyle değiştirelim:

<?php
namespace
MidoriKocak;

class View
{
private $data;

public function __construct()
{
$this->data = [];
}

public function set()
{
$args = func_num_args();
if ($args == 1 && is_array(func_get_arg(0))) {
$this->data = func_get_arg(0);
} elseif ($args == 2 && is_string(func_get_arg(0))) {
$this->data[func_get_arg(0)] = func_get_arg(1);
} else {
throw new InvalidArgumentException('Cannot set variable for View.');
}
}

public function render(string $filename)
{
extract($this->data);

ob_start();
require 'Template/' . $filename . '.php';
return ob_get_clean();
}
}

Her zaman yaptığım gibi kodu tek tek açıklamaya başlayalım. Daha önce her görünüm sınıfı için $this->dictionary veya $this->entry gibi değişkenler kullanarak, görünüm sınıfımıza veri enjekte ediyorduk. İki görünüm sınıfında da render, template ve __construct metodları değişken isimleri hariç aynıydı. Bunun yerine tek bir sınıf kullanıp işimizi halletmek için data adlı bir dizi değişkeni belirledik. __construct metodunda yani new diyerek sınıftan bir nesne yarattığımız anda, php yorumlayıcısı bizim için bu boş diziyi anında oluşturacak.

Asıl hinlik cinlik yaptığımız kısım set yani değişkenleri belirlediğimiz metod. Bu metod Görünüm yani View sınıfına göndermek istediğimiz, template dosyalarımızın kullanacağı değişkenleri enjekte etmemize yarıyor. Yani örneğin bir template yani şema dosyasında $renk adlı değişken tanımlamak ve bu değişkene “pembe” değeri vermek istersem bunu $view->set(‘renk’,’pembe’) diyerek yapabilirim. Peki birden fazla değişkeni aynı anda bir dizi kullanarak göndermek istersem? Bunun için de metoda sadece $view->set($array) ifadesini kullanarak $array ismindeki değişkeni göndereceğim. Peki metodu bu iki farklı parametreyle çağırmamızı sağlayacak olan yöntem ne? Birincisi opsiyonel parametreler kullanmak yani metodu şu şekilde tanımlamak:

public function set($value, $name = null)

Ancak bu şekilde metod ismi ve parametlerin isimlendirmesi anlamsız ve okunaksız oldu. Çünkü ikinci name yani isim parametresini opsiyonel tanımladığımda, $value adlı değişken dizi olmak zorunda. Ancak ben $value değişkenini sadece tek bir değişkenin değerini belirlemek için ifade ediyordum. Bunun yerine PHP de uzun süredir bulunan variadic yani parametlerinin sayısı değişebilen metod kullanmayı tercih ettim.

Bunu da metod çağırıldığında parametrelerin sayısını veren func_num_args() metodu ve sırasına göre metoda gönderilmiş parametrenin değerine değişken ismi kullanmadan erişmemizi sağlayan func_get_arg() yöntemlerini kullanarak sağladım. Bu tarz metodların, C ve C++ dilinde komut satırı uygulamaları yazılırken kullanıldığını görmüşsünüzdür. Çünkü tek bir program komut satırından çağırılırken, kaç parametrenin kaç değer alacağı önceden bilinmiyor. Örneğin diyelim ki composer adlı programı şu şekilde çağırabiliriz.

$> composer help --format=xml list

Burada help, programa verdiğimiz birinci parametre, format=xml ikinci parametre ve list de üçüncü parametre oluyor. Linux ortamına alışkın değilseniz, ya da Windows üzerinde cmd.exe kullanmadıysanız buraları anlamamanız gayet doğal. Sorun değil, öğrenmesi de zor değil. Tavsiye ederim.

Render metodu daha önceki görünüm sınıflarıyla aynı. Tek fark extract metodunu kullanmamız. buradaki extract($this->data) ifadesiyle, örneğin, data dizisi içinde ‘renk’=>’pembe’ değerinde bir eleman tanımlandıysa, buradaki değişkeni doğrudan echo $renk; diyerek kullanabiliyoruz mesela. Dikkat etmemiz gereken en önemli nokta, kullanıcıdan gelen hiçbir veriyi buraya temizlemeden sokuşturmamamız. Yani bu metoda parametre olarak girecek her tür kullanıcının form üzerinden girdiği veriye htmlspecialchars() metodunu kullanarak müdahele etmemiz gerekiyor yoksa 14–15 yaşındaki veletler sistemimizi hem çok pis hacklerler, hem de bizimle dalga geçerler. Bu konudan da güvenlik bölümüne vardığımızda detaylıca bahsedeceğim.

Şimdi app.php dosyasını açalım ve şu şekilde değiştirelim:

<?php

require_once 'DictionaryInterface.php'
;
require_once 'Dictionary.php';
require_once 'EntryInterface.php';
require_once 'Entry.php';
require_once 'View.php';

try {
$dictionary = new MidoriKocakDictionary("Nesne Yönelimli Programlama Sözlüğü");

$nesne = new MidoriKocakEntry('nesne', 'aklımızın dışındaki herşey');

$nesne->addValue('harika bişi');
$nesne->addValue('ingilizce object');

$şey = new MidoriKocakEntry('şey', 'ismi olmayan nesne');

$dictionary->addEntry($nesne);
$dictionary->addEntry($şey);

$entriesArray = $dictionary->getEntriesAsArray();

$entries = $dictionary->getEntries();

$dictionaryView = new MidoriKocakView();

$dictionaryView->set('dictionary', $dictionary);

echo $dictionaryView->render('dictionary');

} catch (Exception | Error $e) {
echo 'Error on line ' . $e->getLine() . ' in ' . $e->getFile()
. ': <b>' . $e->getMessage();
}

Dikkat ettiyseniz artık DictionaryView ve EntryView Dosyalarına ihtiyacımız kalmadı. Bunun yerine sadece tek bir sınıf kullandık.

App.php’yi web sunucumuzu kullanıp açtığımızda, tek bir görünüm sınıfının işleri başarıyla yerine getirdiğiniz göreceğiz.



Bu yazıda son olarak dikkat etmenizi istediğim bir satır da şu:

} catch (Exception | Error $e) {

Burada Error ifadesini de catch bloğuna ekledik ki, sadece exception tipinde değil, error tipinde de hataları yakalayalım. Eğer bunu yapmasaydık ve diyelim ki app.php içinde $dictionaryView->set(‘dictionary’, $dictionary); yazmayı unutsaydık, yani template dosyasında olmayan değişkenlere erişmeye çalışsaydık PHP yorumlayıcısı şu şekilde isyan bayrağını çekecekti.


Bunun yerine Error $e diyerek istisnaların yanında hataları da aynı şekilde yakalamak istediğimizi belirttik ve kullanıcının doğru düzgün bir hata mesajı görmesini sağladık:


Bu sayede hatanın nerde olduğunu kolayca bulup onu böcek gibi ezebiliriz. Şimdilik bu kadar. Bir sonraki yazıda bileşenleri birleştirip bir sayfa oluşturacağız (nihayet).

Bir sonraki yazıya şuradan ulaşabilirsiniz:

Medium.com adresinde görüntüleyin


Projelerle PHP 7

Ben Mutlu Koçak, Bilgisayar Mühendisiyim, ZCPE Sertifikasına sahibim ve “Hiç Bilmeyenler İçin İnternet Programlamaya Giriş — PHP 7” adlı kitabın yazarıyım. Kitabım: https://www.seckin.com.tr/kitap/911934237
Özgeçmişim:
http://represent.io/midorikocak.pdf 
Websitem:
http://mtkocak.net

Yorumla

Yorum