2. ONLINE KARRIERETAG MÜNCHEN 2016
AGENDA MODERNE WEBENTWICKLUNG
▸ TEIL 1: TESTGETRIEBENE ENTWICKLUNG
▸ CODEBEISPIEL
▸ TEIL 2: SYMFONY ENVIRONMENT
▸ VERSAND EINER NEWSLETTER KAMPAGNE
4. BEISPIELCODE: DATA CLASS
WAS MACHT DIESER CODE?
1 <?php
2
3 class data
4 {
5 private $data;
6
7 public function __construct($data)
8 {
9 $this->data = $data;
10 }
11
12 public function get()
13 {
14 $fp = array();
15 foreach ($this->data as $o) {
16 if ($o->bList == 1) { // What is bList?
17 $fp[] = $o;
18 }
19 }
20
21 return $fp;
22 }
23 }
24
WAS PASSIERT, WENN …
▸ … kein Array von Objekten
übergeben wird?
▸ … die Objekte nicht
public $bList; enthalten?
▸ … du diese Klasse
erweitern sollst?
?
5. WIR LIEBEN AUCH KAFFEE
DANN BRAUCHEN WIR ERST EINMAL EINEN KAFFEE…
6. EXKURS: TESTGETRIEBENE ENTWICKLUNG
RED » GREEN » REFACTOR - ZYKLUS
TEST FEHLGESCHLAGEN
TEST SCHREIBEN
TEST ERFOLGREICH
CODE HINZUFÜGEN
ABLAUF STÄNDIG WIEDERHOLEN
CODE VERBESSERN
REFACTOR
7. ERSTER TEST
PRODUCT LIST TEST
1 <?php
2
3 namespace TestsDemo;
4
5 use DemoProductList;
6
7 class ProductListTest extends PHPUnit_Framework_TestCase
8 {
9 public function testProductList()
10 {
11 $productList = new ProductList();
12 }
13 }
14
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
9. EXKURS: WAS IST EIN INTERFACE
INTERFACE: LISTBARES PRODUKT
1 <?php
2
3 namespace Demo;
4
5 interface ProductListInterface
6 {
7 /**
8 * Checks if the product is listed.
9 *
10 * @return bool
11 */
12 public function isListed();
13 }
14
Mit Hilfe des Interface schließen wir einen „Vertrag“,
dass die Methode „isListed“ vorhanden ist.
10. ERWEITERUNG DES TESTFALLS
ERWEITERUNG PRODUCT LIST TEST
8 class ProductListTest extends PHPUnit_Framework_TestCase
9 {
10 public function testProductList()
11 {
12 $listedProduct = $this->prophesize(ProductListInterface::class);
13 $listedProduct->isListed()->willReturn(true);
14 $notListedProduct = $this->prophesize(ProductListInterface::class);
15 $notListedProduct->isListed()->willReturn(false);
16
17 $productList = new ProductList(
18 [
19 $listedProduct->reveal(),
20 $notListedProduct->reveal(),
21 ]
22 );
23
24 $this->assertCount(1, $productList->getListedProducts());
25 $this->assertContains($listedProduct->reveal(),
26 $productList->getListedProducts());
27 }
28 }
29
GELISTET
NICHT
GELISTET
BEIDE
ÜBERGEBEN
NUR 1 PRODUKT
ERWARTET
11. FEHLERMELDUNG
ERGEBNIS PRODUCT LIST TEST
There was 1 error:
1) TestsDemoProductListTest::testProductList
Error: Call to undefined method DemoProductList::getListedProducts()
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
12. FINALE IMPLEMENTIERUNG DER PRODUCT LIST KLASSE
IMPLEMENTIERUNG PRODUCT LIST
5 class ProductList
6 {
7 private $products = [];
8
9 public function __construct(array $productList)
10 {
11 foreach ($productList as $product) {
12 $this->addProduct($product);
13 }
14 }
15
16 public function addProduct(ProductListInterface $product)
17 {
18 array_push($this->products, $product);
19 }
20
21 public function getListedProducts()
22 {
23 return array_filter(
24 $this->products,
25 function (ProductListInterface $product) {
26 return $product->isListed();
27 }
28 );
29 }
30 }
31
NUR ARRAY
ERLAUBT
INTERFACE
IMPLEMENTIERT
NUR GELISTETE
PRODUKTE
15. WAS IST DIE SYMFONY WELT?
SYMFONY
▸ Komponenten
▸ 36 einzelne Bibliotheken
in PHP
▸ Open Source und in
vielen Projekten oder
Frameworks verwendet
▸ Full-Stack-Framework
basierend auf den
Komponenten bildet
Symfony ein
vollständiges
Framework
17. ÜBERSICHT DES ABLAUFS
BEISPIEL: VERSAND EINER NEWSLETTER E-MAIL
NEWSLETTER
MAILER
instanziiert
Array an Empfängern
jede Instanz sendet eine
E-Mail an einen Empfänger
18. BEISPIEL EINER MÖGLICHEN IMPLEMENTIERUNG
KLASSE: MAILER
1 <?php
2
3 class Mailer
4 {
5 private $fromEmail;
6 private $fromName;
7 private $header;
8
9 public function __construct($fromEmail, $fromName, $header)
10 {
11 $this->fromEmail = $fromEmail;
12 $this->fromName = $fromName;
13 $this->header = "From: $fromName <$fromEmail>n".$header;
14 }
15
16 public function send($to, $subject, $message)
17 {
18 mail($to, $subject, $message, $this->header);
19 }
20 }
21
NICHT TESTBAR!
19. BEISPIEL EINER MÖGLICHEN IMPLEMENTIERUNG
KLASSE: NEWSLETTER
1 <?php
2
3 class Newsletter
4 {
5 private $mailer;
6
7 public function __construct()
8 {
9 $this->mailer = new Mailer('news@demo.de','Demo News','Reply-To: reply@demo.de');
10 }
11
12 public function send($recipients, $subject, $message){
13 foreach ($recipients as $to) {
14 $this->mailer->send($to, $subject, $message);
15 }
16 }
17 }
18
▸ Nicht testbar, erweiterbar und wiederverwendbar
▸ Kein Fehlerhandling & kaum Chancen Fehler zu finden
FAZIT:
DIREKTE
ABHÄNGIGKEIT
20. ENTWICKLUNG IM SYMFONY ENVIRONMENT
„THE SYMFONY WAY“
▸ Dependency Injection löst die Abhängigkeiten auf
▸ Kleine testgetriebene Klassen
▸ Config stellt einfache Konfiguration bereit
▸ Debug hilft beim Testen
▸ Framework integriert die Bibliothek SwiftMailer und stellt
umfangreiche Konfiguration zur Verfügung
21. KONFIGURATION DES SERVICE CONTAINERS MIT HILFE VON YAML
DEPENDENCY INJECTION KONFIGURATION
parameters:
mailer.transport: sendmail
services:
mailer: sendmail
class: Mailer
arguments: ['%mailer.transport%']
newsletter_manager:
class: NewsletterManager
calls:
- [setMailer‚ ['@mailer']]
22. BEISPIEL: UNIT-TEST FÜR NEWSLETTER-MANAGER
NEWSLETTER MANAGER TEST
1 <?php
2
3 namespace TestsDemo;
4
5 use DemoMailerInterface;
6 use DemoMessage;
7 use DemoNewsletterManager;
8
9 class NewsletterManagerTest extends PHPUnit_Framework_TestCase
10 {
11 public function testNewsletterManager()
12 {
13 $message = new Message('Test Betreff', 'Test-Inhalt Newsletter');
14 $mailer = $this->prophesize(MailerInterface::class);
15 $mailer->send('max@mustermann.de', $message)->shouldBeCalled();
16
17 $newsletterManager = new NewsletterManager();
18 $newsletterManager->setMailer($mailer->reveal());
19 $newsletterManager->sendMail(['max@mustermann.de'], $message);
20 }
21 }
22
STUB
24. SYMFONY ENVIRONMENT: DEPENDENCY INJECTION
VERWENDUNG DES NEWSLETTER-MANAGERS
▸ Im Controller oder Command kann nun der
NewsletterManager mit Hilfe der Dependency Injection
verwendet werden:
▸ Symfony liest die Konfiguration aus und erstellt den
NewsletterManager mit allen Abhängigkeiten
$newsletterManager = $this->get('newsletter_manager');
$newsletterManager->send($recipients, $message);
25. SYMFONY ENVIRONMENT: ERWEITERUNG
ZUSÄTZLICHE ANFORDERUNGEN
▸ Im Test- & Entwicklungssystem sollen keine E-Mails
versendet werden
▸ Einfache Konfiguration des Absenders
▸ Möglichkeit, über Gmail E-Mails zu versenden
▸ Bringt Symfony bereits alles mit
27. MODERNE WEBENTWICKLUNG
DANKE FÜR DIE AUFMERKSAMKEIT
▸ Sebastian Blum
sb@sblum.de
▸ Präsentation auf unserer Webseite
lj https://www.sblum.de/treffen
▸ Café an unserem Stand