27
MODERNE WEBENTWICKLUNG SEBASTIAN BLUM

Moderne Webentwicklung

Embed Size (px)

Citation preview

MODERNE WEBENTWICKLUNGSEBASTIAN BLUM

ONLINE KARRIERETAG MÜNCHEN 2016

AGENDA MODERNE WEBENTWICKLUNG

▸ TEIL 1: TESTGETRIEBENE ENTWICKLUNG ▸ CODEBEISPIEL

▸ TEIL 2: SYMFONY ENVIRONMENT ▸ VERSAND EINER NEWSLETTER KAMPAGNE

TESTGETRIEBENE ENTWICKLUNGTEIL 1

BEISPIELCODE: DATA CLASS

WAS MACHT DIESER CODE?1<?php23classdata4{5private$data;67publicfunction__construct($data)8{9$this->data=$data;10}1112publicfunctionget()13{14$fp=array();15foreach($this->dataas$o){16if($o->bList==1){//WhatisbList?17$fp[]=$o;18}19}2021return$fp;22}23}24

WAS PASSIERT, WENN …▸ … kein Array von Objekten

übergeben wird?

▸ … die Objekte nicht public $bList; enthalten?

▸ … du diese Klasse erweitern sollst?

?

WIR LIEBEN AUCH KAFFEE

DANN BRAUCHEN WIR ERST EINMAL EINEN KAFFEE…

EXKURS: TESTGETRIEBENE ENTWICKLUNG

RED » GREEN » REFACTOR - ZYKLUS

TEST FEHLGESCHLAGEN

TEST SCHREIBEN

TEST ERFOLGREICH

CODE HINZUFÜGEN

ABLAUF STÄNDIG WIEDERHOLEN

CODE VERBESSERN

REFACTOR

ERSTER TEST

PRODUCT LIST TEST1<?php23namespaceTests\Demo;45useDemo\ProductList;67classProductListTestextends\PHPUnit_Framework_TestCase8{9publicfunctiontestProductList()10{11 $productList=newProductList();12}13}14

FAILURES!Tests:1,Assertions:0,Errors:1.

MINIMALE IMPLEMENTIERUNG

IMPLEMENTIERUNG PRODUCT LIST1<?php23namespaceDemo;45classProductList6{78}9

OK(1test,0assertions)

EXKURS: WAS IST EIN INTERFACE

INTERFACE: LISTBARES PRODUKT1<?php23namespaceDemo;45interfaceProductListInterface6{7/**8*Checksiftheproductislisted.9*10*@returnbool11*/12publicfunctionisListed();13}14

Mit Hilfe des Interface schließen wir einen „Vertrag“, dass die Methode „isListed“ vorhanden ist.

ERWEITERUNG DES TESTFALLS

ERWEITERUNG PRODUCT LIST TEST8classProductListTestextends\PHPUnit_Framework_TestCase9{10publicfunctiontestProductList()11{12$listedProduct=$this->prophesize(ProductListInterface::class);13$listedProduct->isListed()->willReturn(true);14$notListedProduct=$this->prophesize(ProductListInterface::class);15$notListedProduct->isListed()->willReturn(false);1617$productList=newProductList(18[19$listedProduct->reveal(),20$notListedProduct->reveal(),21]22);2324$this->assertCount(1,$productList->getListedProducts());25$this->assertContains($listedProduct->reveal(),26$productList->getListedProducts());27}28}29

GELISTETNICHT

GELISTET

BEIDEÜBERGEBEN

NUR 1 PRODUKT ERWARTET

FEHLERMELDUNG

ERGEBNIS PRODUCT LIST TESTTherewas1error:

1)Tests\Demo\ProductListTest::testProductListError:CalltoundefinedmethodDemo\ProductList::getListedProducts()

FAILURES!Tests:1,Assertions:0,Errors:1.

FINALE IMPLEMENTIERUNG DER PRODUCT LIST KLASSE

IMPLEMENTIERUNG PRODUCT LIST5classProductList6{7private$products=[];89publicfunction__construct(array$productList)10{11foreach($productListas$product){12$this->addProduct($product);13}14}1516publicfunctionaddProduct(ProductListInterface$product)17{18array_push($this->products,$product);19}2021publicfunctiongetListedProducts()22{23returnarray_filter(24$this->products,25function(ProductListInterface$product){26return$product->isListed();27}28);29}30}31

NUR ARRAYERLAUBT

INTERFACE IMPLEMENTIERT

NUR GELISTETEPRODUKTE

3classdata4{5private$data;67publicfunction__construct($data)8{9$this->data=$data;10}1112publicfunctionget()13{14$fp=array();15foreach($this->dataas$o){16if($o->bList==1){17$fp[]=$o;18}19}2021return$fp;22}23}24

5classProductList6{7private$products=[];89publicfunction__construct(array$productList)10{11foreach($productListas$product){12$this->addProduct($product);13}14}1516publicfunctionaddProduct(ProductListInterface$product)17{18array_push($this->products,$product);19}2021publicfunctiongetListedProducts()22{23returnarray_filter(24$this->products,25function(ProductListInterface$product){26return$product->isListed();27}28);29}30}31

GEGENÜBERSTELLUNG

VERGLEICH: VORHER «–» NACHHER

FAZIT: ▸ Einfacherer und sprechender Code▸ Code weniger fehleranfällig▸ Tests stetig wiederholbar

SYMFONY ENVIRONMENTTEIL 2

"

WAS IST DIE SYMFONY WELT?

SYMFONY

▸ Komponenten

▸ 36 einzelne Bibliotheken in PHP

▸ Open Source und in vielen Projekten oder Frameworks verwendet

▸ Full-Stack-Frameworkbasierend auf den Komponenten bildet Symfony ein vollständiges Framework

BEISPIEL: VERSAND EINER NEWSLETTER KAMPAGNE

ÜBERSICHT DES ABLAUFS

BEISPIEL: VERSAND EINER NEWSLETTER E-MAIL

NEWSLETTER

MAILERinstanziiert

Array an Empfängern

jede Instanz sendet eineE-Mail an einen Empfänger

BEISPIEL EINER MÖGLICHEN IMPLEMENTIERUNG

KLASSE: MAILER1<?php23classMailer4{5private$fromEmail;6private$fromName;7private$header;89publicfunction__construct($fromEmail,$fromName,$header)10{11$this->fromEmail=$fromEmail;12$this->fromName=$fromName;13$this->header="From:$fromName<$fromEmail>\n".$header;14}1516publicfunctionsend($to,$subject,$message)17{18mail($to,$subject,$message,$this->header);19}20}21

NICHT TESTBAR!

BEISPIEL EINER MÖGLICHEN IMPLEMENTIERUNG

KLASSE: NEWSLETTER1<?php23classNewsletter4{5private$mailer;67publicfunction__construct()8{9$this->mailer=newMailer('[email protected]','DemoNews','Reply-To:[email protected]');10}1112publicfunctionsend($recipients,$subject,$message){13foreach($recipientsas$to){14$this->mailer->send($to,$subject,$message);15}16}17}18

▸ Nicht testbar, erweiterbar und wiederverwendbar▸ Kein Fehlerhandling & kaum Chancen Fehler zu findenFAZIT:

DIREKTEABHÄNGIGKEIT

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

KONFIGURATION DES SERVICE CONTAINERS MIT HILFE VON YAML

DEPENDENCY INJECTION KONFIGURATIONparameters:mailer.transport:sendmail

services:mailer:sendmailclass:Mailerarguments:['%mailer.transport%']newsletter_manager:class:NewsletterManagercalls:-[setMailer‚['@mailer']]

BEISPIEL: UNIT-TEST FÜR NEWSLETTER-MANAGER

NEWSLETTER MANAGER TEST1<?php23namespaceTests\Demo;45useDemo\MailerInterface;6useDemo\Message;7useDemo\NewsletterManager;89classNewsletterManagerTestextends\PHPUnit_Framework_TestCase10{11publicfunctiontestNewsletterManager()12{13$message=newMessage('TestBetreff','Test-InhaltNewsletter');14$mailer=$this->prophesize(MailerInterface::class);15$mailer->send('[email protected]',$message)->shouldBeCalled();1617$newsletterManager=newNewsletterManager();18$newsletterManager->setMailer($mailer->reveal());19$newsletterManager->sendMail(['[email protected]'],$message);20}21}22

STUB

IMPLEMENTIERUNG DES NEWSLETTER-MANAGERS

NEWSLETTER-MANAGER1<?php23namespaceDemo;45classNewsletterManager6{7private$mailer;89publicfunctionsetMailer(MailerInterface$mailer)10{11$this->mailer=$mailer;12}1314publicfunctionsendMail(array$recipients,Message$message)15{16foreach($recipientsas$recipient){17$this->mailer->send($recipient,$message);18}19}20}21

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);

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

SWIFTMAILER BIBLIOTHEK

KONFIGURATION E-MAIL-VERSAND

▸ Versand deaktivierenswiftmailer:disable_delivery:true

swiftmailer:delivery_address:[email protected]

swiftmailer:transport:'gmail'username:'[email protected]'password'myGmailPassword'

▸ Versand an Test-Empfänger

▸ Versand über Gmail

MODERNE WEBENTWICKLUNG

DANKE FÜR DIE AUFMERKSAMKEIT

▸ Sebastian Blum [email protected]

▸ Präsentation auf unserer Webseite# https://www.sblum.de/treffen

▸ Café an unserem Stand