SlideShare ist ein Scribd-Unternehmen logo
1 von 56
Downloaden Sie, um offline zu lesen
Mehmet Korkmaz
reformo.net - efabrika.com
PORTS & ADAPTERS
Separating concerns in your architecture
Selami ile tanışın
@_mehmet_korkmaz
• Hata loglarını bir veritabanında toplayalım.
• Bir CLI uygulaması yazalım.
• Önemli loglarını okuyup MongoDB’ye yazsın.
• Symfony Console
Görev
2019-05-04	09:00:01;LOGIN_ERROR;Failed	log-in	attempt;
{“count”:3,	“username”:”selami@phpkonf.org”}
@_mehmet_korkmaz
$logs = readLogs($logFile);
foreach ($logs as $log) {
if ($log[‘log_type’] === ‘LOGIN_ERROR’) {
$mongoCollection->insert($log);
}
}
Symfony Console Command
@_mehmet_korkmaz
• Bir panel aracılığı ile bu logları listeleyelim.
• Symfony 3
Görev
@_mehmet_korkmaz
$recentLogs = $mongoCollection->getRecent100Logs($log);
$content = $twig->render(‘logs/recent_logs.html.twig’, $recentLogs);
return new Response($content);
Symfony 3 Controller
@_mehmet_korkmaz
• Bu logları analiz edelim.
• Elasticsearch kullanalım.
Görev
@_mehmet_korkmaz
$logs = readLogs($logFile);
foreach ($logs as $log) {
if ($log[‘log_type’] === ‘LOGIN_ERROR’) {
$elasticsearchClient->insert($log);
}
}
@_mehmet_korkmaz
Symfony Console Command
$failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts();
$content = $twig->render(‘logs/recent_logs.html.twig’, $failedAttemptLogs);
return new Response($content);
Symfony 3 Controller
@_mehmet_korkmaz
• Belli tip hataları e-posta ile bildirelim.
• SendGrid kullanalım.
Görev
@_mehmet_korkmaz
$failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts();
foreach ($failedAttemptLogs as $log) {
$sendGridClient->sendEmail($toEmailAddress, $emailTemplate, $log);
}
SendGrid
@_mehmet_korkmaz
• Mobil uygulamamızdaki birtakım hataları da loglayalım.
• Slim 2 ile bir API geliştirelim.
Görev
@_mehmet_korkmaz
$app->post(‘/logs', function () use ($request, $mongoCollection) {
$logData = $request->getParsedBody();
$mongoCollection->insert($log);
});
Slim 2 Route
@_mehmet_korkmaz
• Birtakım log analizleri uzun sürüyor.
• Analiz taleplerini bir kuyruğa atıp analiz edelim.
• RabbitMQ kullanalım.
Görev
@_mehmet_korkmaz
RabbitMQ
$rabbitMQ->publish($queueType, $analysisData);
$rabbitMQ->subscribe($queueType);
@_mehmet_korkmaz
• Kritik hataları SMS ile bildirelim.
Görev
@_mehmet_korkmaz
$failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts();
foreach ($failedAttemptLogs as $log) {
$smsClient->send($phoneNumber, $log);
}
SMS
@_mehmet_korkmaz
• SendGrid maliyetli olmaya başladı.
• Mailgun kullanalım.
Görev
@_mehmet_korkmaz
$failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts();
foreach ($failedAttemptLogs as $log) {
$mailgunClient->sendEmail($toEmailAddress, $emailTemplate, $log);
}
Mailgun
@_mehmet_korkmaz
• Veritabanını PostreSQL’e taşıyalım Selami.
• Symfony 4 çıktı Selami.
• Slim 3 çıktı Selami.
• Apache Kafka mı kullansak Selami?
Görev
@_mehmet_korkmaz
Selami ile bir daha tanışın
@_mehmet_korkmaz
• Uygulamamızın kalbinde duran çalışma mantığı her
yere sızma eğilimindedir. Bu yüzden çalışma
mantığındaki değişiklikleri yönetmek zorlayıcı olabilir.
• Altyapı bağımlılıkları değişiklik gösterebilir.
Problem?
@_mehmet_korkmaz
“Things do change. That's why we design and build with
change in mind”
Ron Jeffries
One of the three founders of the Extreme Programming, 

Agile Founding Father
@_mehmet_korkmaz
• Kullandığımız veritabanları mı?
• Kullandığımız framework’ler mi?
• Kullandığımız ağ servisleri mi?
• Kullandığımız harici servisler mi?
Mimarideki Kritik Kararlar
Nelerdir?
@_mehmet_korkmaz
• Bunların hepsi önemli olmakla beraber herbiri
uygulama detaylarıdır.
• Mimaride esas olan işleyiş mantığındaki (Domain)
ilişkilerdir.
Mimarideki Kritik Kararlar
Nelerdir?
@_mehmet_korkmaz
• Framework’den bağımsız olmalıdır.
• Veritabanından bağımsız olmalıdır.
• Harici servislerden bağımsız olmalıdır.
• Arayüzden bağımsız olmalıdır.
• Test edilebilir olmalıdır.
Nasıl olmalı?
@_mehmet_korkmaz
Çözüm
Separation of Concerns
@_mehmet_korkmaz
• Ports & Adapters
• Hexagonal Architecture
• Use Case Driven Architecture
@_mehmet_korkmaz
a.k.a
Alistair Cockburn
Computer Scientist, Agile Founding Father
“Allow an application to equally be driven by users,
programs, automated test or batch scripts, and to be
developed and tested in isolation from its eventual run-
time devices and databases.”
@_mehmet_korkmaz
@_mehmet_korkmaz
• Application, Domain, ve Infrastructure birbirinden
net bir şekilde ayrılmalıdır.
• Bağımlılıklar Application ve Infrastructure’dan
Domain’e doğru olmalıdır.
• Sınırlar "Portlar ve Adaptörler” aracılığıyla birbirinden
izole edilmelidir.
Prensipler
@_mehmet_korkmaz
• Gerçek dünyada çözmeye çalıştığınız problemin
modelidir.
• Gerçek dünyada karşımıza çıkan kuralların modelidir.
• Gerçek dünyada karşımıza çıkan problemlerin
çözümünde aldığımız kararların modelidir.
Domain Nedir?
@_mehmet_korkmaz
• Uygulama içinde çalışma mantığına dair karar veren
kısımdır.
• Uygulamanın state’ini değiştirmeye dair yetkili tek
kısımdır.
• Uygulamanın içinde problem çözen kısımdır.
• Uygulamanın merkezindeki ilişkileri yöneten kısımdır.
Domain Layer Nedir?
@_mehmet_korkmaz
• Application Layer: Kullanıcı ve/veya diğer harici
uygulamaların uygulamamız ile etkileşime girdiği
katmandır.
• Domain Layer: Uygulamamızın çalışma mantığının yer
aldığı ve diğer katmanlarla nasıl etkileşime girileceğinin
belirlendiği katmandır.
• Infrastructure Layer: Uygulamızın implementasyon
detaylarının olduğu katmandır. Framework, veritabanı,
harici servisler vs.
Application, Domain, ve Infrastructure birbirinden
net bir şekilde ayrılmalıdır.
@_mehmet_korkmaz
@_mehmet_korkmaz
• Domain Application’a bağımlı değildir, Application
Domain’e bağımlıdır.
• Domain Infrastructure’a bağımlı değildir,
Infrastructure Domain’e bağımlıdır.
Bağımlılıklar Application ve Infrastructure’dan
Domain’e doğru olmalıdır.
@_mehmet_korkmaz
@_mehmet_korkmaz
• Application Layer Domain’i bir interface aracılığıyla
kullanır. (Ya da CQRS’deki Command’ları).
• Domain Layer da altyapıyı bir interface aracılığı ile kullanır.
• Bu interface’ler mimaride içeriden dışarıya açık yalıtım
aracı işlevi görür.
Sınırlar “Portlar ve Adaptörler” aracılığıyla
birbirinden izole edilmelidir.
@_mehmet_korkmaz
@_mehmet_korkmaz
Shut Up!
And show me the code!
~Domain Entity ~
@_mehmet_korkmaz
namespace MyApplicationDomainLog;
class Log
{
private $id;
private $logDate;
private $logMessage;
private $logContext;
private $createdAt;
public const LOG_TYPE = ‘LOGIN_ERROR’;
public function __construct(UUID $id, DateTime $logDate, string
$logMessage, array $logContext)
{
$this->createdAt = new Datetime();
//
}
}
~Application Service Interface ~
@_mehmet_korkmaz
namespace MyApplicationDomainLog;
interface LogService
{
public function newLoginErrorLog(NewLoginErrorLogRequest $request) : bool;
}
~Application Service ~
@_mehmet_korkmaz
namespace MyApplicationApplicationLog;
Use MyApplicationDomainLogLogService as DomainLogService;
class LogService implements DomainLogService;
{
private $logRepository;
public function __construct(LogRepository $logRepository)
{
private $this->logRepository = $logRepository;
}
public function newLoginErrorLog(NewLoginErrorLogRequest $request)
{
$log = LogFactory::createFromRequest($request);
$this->logRepository->save($log)
}
}
~Domain Request ~
@_mehmet_korkmaz
namespace MyApplicationDomainLog;
class NewLoginErrorLogRequest
{
private $logId;
private $logDate;
private $logMessage;
private $logContext;
public function __construct(UUID $logId, DateTime $logDate, string
$logMessage, array $logContext)
{
//
}
}
~Domain LogRepository ~
@_mehmet_korkmaz
namespace MyApplicationDomainLog;
interface LogRepository
{
public function byId(UUID $id) : Log;
public function save(Log $log) : bool;
public function update(Log $log) : bool;
public function logList(string $logType, int $limit, int $skip) : LogCollection;
}
~Infrastructure LogRepository ~
@_mehmet_korkmaz
namespace MyApplicationInfrastructurePersistenceLog;
use MyApplicationDomainLogLogRepository as LogRepositoryInterface;
class LogRepository implements LogRepositoryInterface
{
//
public function save(Log $log) : bool
{
$logDBData = [
‘log_date’ => $log->getLogDate()->format(‘Y-m-d H:i:s’),
‘message’ => $log->getMessage(),
‘type’ => $log->getLogType(),
//
];
$mongoCollection->insert($logDBData);
}
}
Use Case Controller
@_mehmet_korkmaz
namespace MyApplicationApplicationLog;
use MyApplicationApplicationLogLogService;
use PsrHttpMessageServerRequestInterface as Request;
use PsrHttpMessageResponseInterface as Response;
use RamseyUuidUuid;
class CreateNewLogController
{
public function __construct((LogService $logService));
public function __invoke(Request $request, Response $response)
{
$logData = $request->getParsedBody();
$logData[‘id’] = Uuid::uuid4();
$newLogRequest = new NewLoginErrorLogRequest(…$logData);
$this->logService->newLoginErrorLog($newLogRequest);
return $response->withAddedHeader(‘Location’, ‘/logs/’ . $logData[‘id’]);
}
}
Bize iş mi çıkarıyorsun?
@_mehmet_korkmaz
“Psychologists have discovered that our minds are ruled
by two different systems—the rational mind and the
emotional mind—that compete for control. The rational
mind wants a great beach body; the emotional mind
wants that Oreo cookie. The rational mind wants to
change something at work; the emotional mind loves
the comfort of the existing routine. This tension can
doom a change effort—but if it is overcome, change
can come quickly.”
Preface from the book Switch: How to Change Things When Change Is Hard
by Chip and Dan Heath
@_mehmet_korkmaz
@_mehmet_korkmaz
@_mehmet_korkmaz
Kimler öneriyor?
@_mehmet_korkmaz
“Eğer doğru kullanırsanız, her araç silah olabilir”
Ani DiFranco
(Şarkıcı, şair, aktivist)
@_mehmet_korkmaz
Son olarak
1. Cockburn, A. - https://web.archive.org/web/20090327032122/http://alistair.cockburn.us/
Hexagonal+architecture
2. Fowler, M. - https://martinfowler.com/bliki/PresentationDomainDataLayering.html
3. http://wiki.c2.com/?HexagonalArchitecture
4. Martin, R. C. https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
5. Alliaume, E. Roccaserra, S. https://blog.octo.com/en/hexagonal-architecture-three-principles-and-an-
implementation-example/
6. Graca, H. https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-
how-i-put-it-all-together/
7. Wynne, M. http://blog.mattwynne.net/2012/05/31/hexagonal-rails-objects-values-and-hexagons/
8. Freeman, S. Pryce, N. Growing Object-Oriented Software, Guided by Tests
9. Vernon, V. Implementing Domain-Driven Design
10. Buenosvinos, C. Soronellas, C. Akbary K. Domain-Driven Design in PHP
References & Credits
@_mehmet_korkmaz
Twitter: @_mehmet_korkmaz
Github: @mkorkmaz

mkorkmaz.com - reformo.net - efabrika.com
Thank You!

Weitere ähnliche Inhalte

Ähnlich wie Ports and Adapters: Separating concerns in your architecture

Mutant Web Applications
Mutant Web ApplicationsMutant Web Applications
Mutant Web Applicationsguest096801
 
Log yönetimi ve siem projelerindeki en önemli kriter EPS değerleri
Log yönetimi ve siem projelerindeki en önemli kriter EPS değerleriLog yönetimi ve siem projelerindeki en önemli kriter EPS değerleri
Log yönetimi ve siem projelerindeki en önemli kriter EPS değerleriErtugrul Akbas
 
45965 php-source-code-analysis
45965 php-source-code-analysis45965 php-source-code-analysis
45965 php-source-code-analysisAttaporn Ninsuwan
 
Veri̇tabani ve Kullanici Yöneti̇mi̇
Veri̇tabani ve Kullanici Yöneti̇mi̇Veri̇tabani ve Kullanici Yöneti̇mi̇
Veri̇tabani ve Kullanici Yöneti̇mi̇Anar Godjaev
 
Django Introduction
Django IntroductionDjango Introduction
Django IntroductionFatih Erikli
 
Nginx ve Unicorn'la Rack Uygulamalarını Koşturmak
Nginx ve Unicorn'la Rack Uygulamalarını KoşturmakNginx ve Unicorn'la Rack Uygulamalarını Koşturmak
Nginx ve Unicorn'la Rack Uygulamalarını KoşturmakUğur Özyılmazel
 
3. aşırı yükleme yaşam alanı - dinamik bellek kullanımı
3. aşırı yükleme   yaşam alanı - dinamik bellek kullanımı3. aşırı yükleme   yaşam alanı - dinamik bellek kullanımı
3. aşırı yükleme yaşam alanı - dinamik bellek kullanımıkarmuhtam
 
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit AşamasıBeyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit AşamasıPRISMA CSI
 
Spring uygulamaların exception handling yönetimi
Spring uygulamaların exception handling yönetimiSpring uygulamaların exception handling yönetimi
Spring uygulamaların exception handling yönetimiSistek Yazılım
 
Git - Bildiğiniz Gibi Değil
Git - Bildiğiniz Gibi DeğilGit - Bildiğiniz Gibi Değil
Git - Bildiğiniz Gibi DeğilLemi Orhan Ergin
 
İleri Seviye Programlama 2
İleri Seviye Programlama 2İleri Seviye Programlama 2
İleri Seviye Programlama 2Caner Bovatekin
 
Log Yönetimi ve Saldırı Analizi Eğitimi -1
Log Yönetimi ve Saldırı Analizi Eğitimi -1Log Yönetimi ve Saldırı Analizi Eğitimi -1
Log Yönetimi ve Saldırı Analizi Eğitimi -1BGA Cyber Security
 
C sharp-indir
C sharp-indirC sharp-indir
C sharp-indirsersld30
 
Java Web Uygulama Geliştirme
Java Web Uygulama GeliştirmeJava Web Uygulama Geliştirme
Java Web Uygulama Geliştirmeahmetdemirelli
 
Balikesir University - Mobile Technologies Presentation
Balikesir University - Mobile Technologies PresentationBalikesir University - Mobile Technologies Presentation
Balikesir University - Mobile Technologies PresentationCan ULUDAG
 

Ähnlich wie Ports and Adapters: Separating concerns in your architecture (20)

Php refactoring
Php refactoringPhp refactoring
Php refactoring
 
Mutant Web Applications
Mutant Web ApplicationsMutant Web Applications
Mutant Web Applications
 
Log yönetimi ve siem projelerindeki en önemli kriter EPS değerleri
Log yönetimi ve siem projelerindeki en önemli kriter EPS değerleriLog yönetimi ve siem projelerindeki en önemli kriter EPS değerleri
Log yönetimi ve siem projelerindeki en önemli kriter EPS değerleri
 
45965 php-source-code-analysis
45965 php-source-code-analysis45965 php-source-code-analysis
45965 php-source-code-analysis
 
Veri̇tabani ve Kullanici Yöneti̇mi̇
Veri̇tabani ve Kullanici Yöneti̇mi̇Veri̇tabani ve Kullanici Yöneti̇mi̇
Veri̇tabani ve Kullanici Yöneti̇mi̇
 
Django Introduction
Django IntroductionDjango Introduction
Django Introduction
 
Nginx ve Unicorn'la Rack Uygulamalarını Koşturmak
Nginx ve Unicorn'la Rack Uygulamalarını KoşturmakNginx ve Unicorn'la Rack Uygulamalarını Koşturmak
Nginx ve Unicorn'la Rack Uygulamalarını Koşturmak
 
3. aşırı yükleme yaşam alanı - dinamik bellek kullanımı
3. aşırı yükleme   yaşam alanı - dinamik bellek kullanımı3. aşırı yükleme   yaşam alanı - dinamik bellek kullanımı
3. aşırı yükleme yaşam alanı - dinamik bellek kullanımı
 
Flex
FlexFlex
Flex
 
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit AşamasıBeyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
 
Spring uygulamaların exception handling yönetimi
Spring uygulamaların exception handling yönetimiSpring uygulamaların exception handling yönetimi
Spring uygulamaların exception handling yönetimi
 
.Net ile yazılım güvenliği
.Net ile yazılım güvenliği.Net ile yazılım güvenliği
.Net ile yazılım güvenliği
 
Git - Bildiğiniz Gibi Değil
Git - Bildiğiniz Gibi DeğilGit - Bildiğiniz Gibi Değil
Git - Bildiğiniz Gibi Değil
 
İleri Seviye Programlama 2
İleri Seviye Programlama 2İleri Seviye Programlama 2
İleri Seviye Programlama 2
 
Log Yönetimi ve Saldırı Analizi Eğitimi -1
Log Yönetimi ve Saldırı Analizi Eğitimi -1Log Yönetimi ve Saldırı Analizi Eğitimi -1
Log Yönetimi ve Saldırı Analizi Eğitimi -1
 
Oracle Weblogic Server
Oracle Weblogic ServerOracle Weblogic Server
Oracle Weblogic Server
 
C sharp-indir
C sharp-indirC sharp-indir
C sharp-indir
 
Java Web Uygulama Geliştirme
Java Web Uygulama GeliştirmeJava Web Uygulama Geliştirme
Java Web Uygulama Geliştirme
 
Ossec - Host Based Saldırı Tespit Sistemi
Ossec - Host Based Saldırı Tespit SistemiOssec - Host Based Saldırı Tespit Sistemi
Ossec - Host Based Saldırı Tespit Sistemi
 
Balikesir University - Mobile Technologies Presentation
Balikesir University - Mobile Technologies PresentationBalikesir University - Mobile Technologies Presentation
Balikesir University - Mobile Technologies Presentation
 

Ports and Adapters: Separating concerns in your architecture

  • 1. Mehmet Korkmaz reformo.net - efabrika.com PORTS & ADAPTERS Separating concerns in your architecture
  • 3. • Hata loglarını bir veritabanında toplayalım. • Bir CLI uygulaması yazalım. • Önemli loglarını okuyup MongoDB’ye yazsın. • Symfony Console Görev 2019-05-04 09:00:01;LOGIN_ERROR;Failed log-in attempt; {“count”:3, “username”:”selami@phpkonf.org”} @_mehmet_korkmaz
  • 4. $logs = readLogs($logFile); foreach ($logs as $log) { if ($log[‘log_type’] === ‘LOGIN_ERROR’) { $mongoCollection->insert($log); } } Symfony Console Command @_mehmet_korkmaz
  • 5. • Bir panel aracılığı ile bu logları listeleyelim. • Symfony 3 Görev @_mehmet_korkmaz
  • 6. $recentLogs = $mongoCollection->getRecent100Logs($log); $content = $twig->render(‘logs/recent_logs.html.twig’, $recentLogs); return new Response($content); Symfony 3 Controller @_mehmet_korkmaz
  • 7. • Bu logları analiz edelim. • Elasticsearch kullanalım. Görev @_mehmet_korkmaz
  • 8. $logs = readLogs($logFile); foreach ($logs as $log) { if ($log[‘log_type’] === ‘LOGIN_ERROR’) { $elasticsearchClient->insert($log); } } @_mehmet_korkmaz Symfony Console Command
  • 9. $failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts(); $content = $twig->render(‘logs/recent_logs.html.twig’, $failedAttemptLogs); return new Response($content); Symfony 3 Controller @_mehmet_korkmaz
  • 10. • Belli tip hataları e-posta ile bildirelim. • SendGrid kullanalım. Görev @_mehmet_korkmaz
  • 11. $failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts(); foreach ($failedAttemptLogs as $log) { $sendGridClient->sendEmail($toEmailAddress, $emailTemplate, $log); } SendGrid @_mehmet_korkmaz
  • 12. • Mobil uygulamamızdaki birtakım hataları da loglayalım. • Slim 2 ile bir API geliştirelim. Görev @_mehmet_korkmaz
  • 13. $app->post(‘/logs', function () use ($request, $mongoCollection) { $logData = $request->getParsedBody(); $mongoCollection->insert($log); }); Slim 2 Route @_mehmet_korkmaz
  • 14. • Birtakım log analizleri uzun sürüyor. • Analiz taleplerini bir kuyruğa atıp analiz edelim. • RabbitMQ kullanalım. Görev @_mehmet_korkmaz
  • 16. • Kritik hataları SMS ile bildirelim. Görev @_mehmet_korkmaz
  • 17. $failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts(); foreach ($failedAttemptLogs as $log) { $smsClient->send($phoneNumber, $log); } SMS @_mehmet_korkmaz
  • 18. • SendGrid maliyetli olmaya başladı. • Mailgun kullanalım. Görev @_mehmet_korkmaz
  • 19. $failedAttemptLogs = $elasticsearchIndex->findMoreThan10FailedLoginAttempts(); foreach ($failedAttemptLogs as $log) { $mailgunClient->sendEmail($toEmailAddress, $emailTemplate, $log); } Mailgun @_mehmet_korkmaz
  • 20. • Veritabanını PostreSQL’e taşıyalım Selami. • Symfony 4 çıktı Selami. • Slim 3 çıktı Selami. • Apache Kafka mı kullansak Selami? Görev @_mehmet_korkmaz
  • 21. Selami ile bir daha tanışın @_mehmet_korkmaz
  • 22. • Uygulamamızın kalbinde duran çalışma mantığı her yere sızma eğilimindedir. Bu yüzden çalışma mantığındaki değişiklikleri yönetmek zorlayıcı olabilir. • Altyapı bağımlılıkları değişiklik gösterebilir. Problem? @_mehmet_korkmaz
  • 23. “Things do change. That's why we design and build with change in mind” Ron Jeffries One of the three founders of the Extreme Programming, 
 Agile Founding Father @_mehmet_korkmaz
  • 24. • Kullandığımız veritabanları mı? • Kullandığımız framework’ler mi? • Kullandığımız ağ servisleri mi? • Kullandığımız harici servisler mi? Mimarideki Kritik Kararlar Nelerdir? @_mehmet_korkmaz
  • 25. • Bunların hepsi önemli olmakla beraber herbiri uygulama detaylarıdır. • Mimaride esas olan işleyiş mantığındaki (Domain) ilişkilerdir. Mimarideki Kritik Kararlar Nelerdir? @_mehmet_korkmaz
  • 26. • Framework’den bağımsız olmalıdır. • Veritabanından bağımsız olmalıdır. • Harici servislerden bağımsız olmalıdır. • Arayüzden bağımsız olmalıdır. • Test edilebilir olmalıdır. Nasıl olmalı? @_mehmet_korkmaz
  • 29. • Ports & Adapters • Hexagonal Architecture • Use Case Driven Architecture @_mehmet_korkmaz a.k.a
  • 30. Alistair Cockburn Computer Scientist, Agile Founding Father “Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run- time devices and databases.” @_mehmet_korkmaz
  • 32. • Application, Domain, ve Infrastructure birbirinden net bir şekilde ayrılmalıdır. • Bağımlılıklar Application ve Infrastructure’dan Domain’e doğru olmalıdır. • Sınırlar "Portlar ve Adaptörler” aracılığıyla birbirinden izole edilmelidir. Prensipler @_mehmet_korkmaz
  • 33. • Gerçek dünyada çözmeye çalıştığınız problemin modelidir. • Gerçek dünyada karşımıza çıkan kuralların modelidir. • Gerçek dünyada karşımıza çıkan problemlerin çözümünde aldığımız kararların modelidir. Domain Nedir? @_mehmet_korkmaz
  • 34. • Uygulama içinde çalışma mantığına dair karar veren kısımdır. • Uygulamanın state’ini değiştirmeye dair yetkili tek kısımdır. • Uygulamanın içinde problem çözen kısımdır. • Uygulamanın merkezindeki ilişkileri yöneten kısımdır. Domain Layer Nedir? @_mehmet_korkmaz
  • 35. • Application Layer: Kullanıcı ve/veya diğer harici uygulamaların uygulamamız ile etkileşime girdiği katmandır. • Domain Layer: Uygulamamızın çalışma mantığının yer aldığı ve diğer katmanlarla nasıl etkileşime girileceğinin belirlendiği katmandır. • Infrastructure Layer: Uygulamızın implementasyon detaylarının olduğu katmandır. Framework, veritabanı, harici servisler vs. Application, Domain, ve Infrastructure birbirinden net bir şekilde ayrılmalıdır. @_mehmet_korkmaz
  • 37. • Domain Application’a bağımlı değildir, Application Domain’e bağımlıdır. • Domain Infrastructure’a bağımlı değildir, Infrastructure Domain’e bağımlıdır. Bağımlılıklar Application ve Infrastructure’dan Domain’e doğru olmalıdır. @_mehmet_korkmaz
  • 39. • Application Layer Domain’i bir interface aracılığıyla kullanır. (Ya da CQRS’deki Command’ları). • Domain Layer da altyapıyı bir interface aracılığı ile kullanır. • Bu interface’ler mimaride içeriden dışarıya açık yalıtım aracı işlevi görür. Sınırlar “Portlar ve Adaptörler” aracılığıyla birbirinden izole edilmelidir. @_mehmet_korkmaz
  • 41. Shut Up! And show me the code!
  • 42. ~Domain Entity ~ @_mehmet_korkmaz namespace MyApplicationDomainLog; class Log { private $id; private $logDate; private $logMessage; private $logContext; private $createdAt; public const LOG_TYPE = ‘LOGIN_ERROR’; public function __construct(UUID $id, DateTime $logDate, string $logMessage, array $logContext) { $this->createdAt = new Datetime(); // } }
  • 43. ~Application Service Interface ~ @_mehmet_korkmaz namespace MyApplicationDomainLog; interface LogService { public function newLoginErrorLog(NewLoginErrorLogRequest $request) : bool; }
  • 44. ~Application Service ~ @_mehmet_korkmaz namespace MyApplicationApplicationLog; Use MyApplicationDomainLogLogService as DomainLogService; class LogService implements DomainLogService; { private $logRepository; public function __construct(LogRepository $logRepository) { private $this->logRepository = $logRepository; } public function newLoginErrorLog(NewLoginErrorLogRequest $request) { $log = LogFactory::createFromRequest($request); $this->logRepository->save($log) } }
  • 45. ~Domain Request ~ @_mehmet_korkmaz namespace MyApplicationDomainLog; class NewLoginErrorLogRequest { private $logId; private $logDate; private $logMessage; private $logContext; public function __construct(UUID $logId, DateTime $logDate, string $logMessage, array $logContext) { // } }
  • 46. ~Domain LogRepository ~ @_mehmet_korkmaz namespace MyApplicationDomainLog; interface LogRepository { public function byId(UUID $id) : Log; public function save(Log $log) : bool; public function update(Log $log) : bool; public function logList(string $logType, int $limit, int $skip) : LogCollection; }
  • 47. ~Infrastructure LogRepository ~ @_mehmet_korkmaz namespace MyApplicationInfrastructurePersistenceLog; use MyApplicationDomainLogLogRepository as LogRepositoryInterface; class LogRepository implements LogRepositoryInterface { // public function save(Log $log) : bool { $logDBData = [ ‘log_date’ => $log->getLogDate()->format(‘Y-m-d H:i:s’), ‘message’ => $log->getMessage(), ‘type’ => $log->getLogType(), // ]; $mongoCollection->insert($logDBData); } }
  • 48. Use Case Controller @_mehmet_korkmaz namespace MyApplicationApplicationLog; use MyApplicationApplicationLogLogService; use PsrHttpMessageServerRequestInterface as Request; use PsrHttpMessageResponseInterface as Response; use RamseyUuidUuid; class CreateNewLogController { public function __construct((LogService $logService)); public function __invoke(Request $request, Response $response) { $logData = $request->getParsedBody(); $logData[‘id’] = Uuid::uuid4(); $newLogRequest = new NewLoginErrorLogRequest(…$logData); $this->logService->newLoginErrorLog($newLogRequest); return $response->withAddedHeader(‘Location’, ‘/logs/’ . $logData[‘id’]); } }
  • 49. Bize iş mi çıkarıyorsun? @_mehmet_korkmaz
  • 50. “Psychologists have discovered that our minds are ruled by two different systems—the rational mind and the emotional mind—that compete for control. The rational mind wants a great beach body; the emotional mind wants that Oreo cookie. The rational mind wants to change something at work; the emotional mind loves the comfort of the existing routine. This tension can doom a change effort—but if it is overcome, change can come quickly.” Preface from the book Switch: How to Change Things When Change Is Hard by Chip and Dan Heath @_mehmet_korkmaz
  • 54. “Eğer doğru kullanırsanız, her araç silah olabilir” Ani DiFranco (Şarkıcı, şair, aktivist) @_mehmet_korkmaz Son olarak
  • 55. 1. Cockburn, A. - https://web.archive.org/web/20090327032122/http://alistair.cockburn.us/ Hexagonal+architecture 2. Fowler, M. - https://martinfowler.com/bliki/PresentationDomainDataLayering.html 3. http://wiki.c2.com/?HexagonalArchitecture 4. Martin, R. C. https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html 5. Alliaume, E. Roccaserra, S. https://blog.octo.com/en/hexagonal-architecture-three-principles-and-an- implementation-example/ 6. Graca, H. https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs- how-i-put-it-all-together/ 7. Wynne, M. http://blog.mattwynne.net/2012/05/31/hexagonal-rails-objects-values-and-hexagons/ 8. Freeman, S. Pryce, N. Growing Object-Oriented Software, Guided by Tests 9. Vernon, V. Implementing Domain-Driven Design 10. Buenosvinos, C. Soronellas, C. Akbary K. Domain-Driven Design in PHP References & Credits @_mehmet_korkmaz
  • 56. Twitter: @_mehmet_korkmaz Github: @mkorkmaz
 mkorkmaz.com - reformo.net - efabrika.com Thank You!