Repository Pattern büyük ölçekli projelerde tercih edilen design pattern mimarilerinden biridir.

Repository Pattern büyük ölçekli projelerde tercih edilen design pattern mimarilerinden biridir. Domain Driven Design mimarisinin bir parçası olarak 2004 yılında ilk olarak duyurulmuştur. Veriye erişimi olan objeleri izole ederek (encapsulation) direkt erişime kapatır, bu iletişim repository üzerinden yapılır.

Repository Pattern tasarımının bir dil kısıtlaması yoktur. Her yazılım dilinde uygulanabilmektedir.

Bu soyut kavramı kafamızda biraz daha somutlaştıralım ve örneklendirmeye çalışalım.

Repository Pattern aslında bir veri soyutlama yöntemidir. Bu soyutlama işlemini gerçekleştirirken katmanlardan faydalanılmaktadır.

Projede veritabanı işlemlerini (Data Access Object) bir katmanda, veri erişim isteğinde bulunan kısım (Client) bir katmanda ve son olarak bu iki katman arasındaki iletişimi sağlayacak olan kısımı (Business Logic) bir katmanda düşünelim. Client veriye erişmek istediğinde repository katmanına başvurur. Repository katmanı istenilen veriyi Data Access Object katmanından alır ve tekrar Client katmanına döndürür.

Özetle Repository Pattern yaşam döngüsü (Life Cycle) bu şekilde çalışmaktadır.

Repository katmanını her hangi bir yazılım dilinde sınıf (class) olarak düşünüğümüzde, sıklıkla kullandığımız methodları bu sınıf için de ortak amaçlar için barındırırız. Böylelikle bize özel collection-like sınıfları sağlamaktadır.

Metodlar:

  • create()
  • read()
  • update()
  • delete()

Bu metodlar en çok kullanılanlarıdır. Tabi ki farklılaşabilir fakat kod tekrarına (dublication) sürüklenmemek için dikkat edilmelidir. Çünkü Repository Pattern mimarisinin sağladığı en büyük avantajlardan biri kod tekrarının en aza indirme fırsatı vermesidir.

PHP ile basit bir örnek yaparak prensipleri uygulayalım.

İlk olarak Repository adında bir sınıf oluşturalım.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Repository {
protected $model;
public function __construct($model)
{
$this->model = $model;
}
public function create($data)
{
return $this->model->create($data);
}
public function update($data, $id)
{
return $this->model->update($id, $data);
}
public function delete()
{
return $this->model->delete($id);
}
}

Yukarıda en çok kullanılan bazı metodları sınıfa ekledik. Sonra veritabanı işlemlerini yapacak olan modeli sınıf içine bağımlılık olarak gönderdik.

Not: Model konusu farklı bir başlık konusu olduğundan detayına girilmeyecektir. Sadece veritabanı işlemlerini yapan ve veri nesnelerine erişimi sağlayan katman olarak anılacaktır.

Şimdi de model sınıfımızı oluşturalım.

1
2
3
4
5
6
class ClientModel extends SomeORM {
// bu sınıf belki bir ORM sınıfına yada benzeri ilişkisel veri modelleme sınıflarına genişletilebilir. Belki kendinizin geliştirmiş olduğu bir ORM 'i entegre edebilirsiniz.
// şimdilik sadece create(), update(), delete() methodlarının olduğunu varsayalım.
}

Yukarıdaki basit sınıfları oluşturduktan sonra ClientModel’i repository sınıfına bağımlılık parametresi olarak gönderiyoruz.

1
2
3
4
$model = new ClientModel;
$clientRepository = new Repository($model);

Client Model ile veri erişim işlemlerini yapabileceğimiz bir repository sınıfımız var.

1
2
3
$clientRepository->create($data);
$clientRepository->update($data, $id);

İstersek bunu CategoryModel yapabilirdik. Bu ihtiyaçlarımıza göre çeşitlenecek bir gelişme.

CategoryModel’imiz olduğunu düşünürsek:

1
2
3
$model = new CategoryModel;
$categoryRepository = new Repository($model);

Daha da ileri taşıyacak olursak repository sınıflarınıda genişleterek (extends) daha spesifik kurgular yapabiliriz. Bu tamamen iş mantığı (business logic)’na bağlı bir durum.

Örnek:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ClientRepository extends Repository {
public function __construct($model)
{
parent::__contruct($model);
}
public function mutateAndCreate($data)
{
unset($data['phone']);
return $this->create($data);
}
}
$model = new Client;
$clientRepository = new ClientRepository($model);
$client->mutateAndCreate($data);

Yukarıda Repository sınıfını ClientRepository sınıfına genişlettiğimizi görüyoruz. Sonrasında $model katmanını bu sınıfa bağımlılık sınıfı olarak gönderiyoruz.

Burda yeni oluşturduğumuz ClientRepository sınıfının yapılandırma (construct) metodunda, ana Repository sınıfının yapılandırma (construct) metodunu çağırdığımızı (parent::__construct()) görüyoruz. Çünkü ana Repository sınıfımız $model katmanına bağımlı olduğundan bu işlemi yapmamız gerekmektedir.

Repository pattern mimarisinin avantajlarından bir tanesi sadece tek yönlü bağımlılığı olmasıdır. Bu bize bağımlılık yönetiminde forsatlar sunmaktadır.

Kolay ve hızlıca anlaşılması için yukarıdaki örneği olabildiğince basit anlatmaya çalıştım. Çok daha gelişmiş örnekleri bir kaç arama ile rahatlıkla bulabilirsiniz.