PHP hat mittlerweile über 20 Jahre auf dem Buckel und die Entwicklung hat in den letzten Jahren gerade mit PHP 7 und den vielen nützlichen Frameworks einen weiteren Schub bekommen. Da ist es nicht verwunderlich, dass viele langjährig gewachsene PHP Anwendungen mittlerweile ein wenig in die Jahre gekommen sind. In dieser Session erhalten Sie 9 Tipps, mit denen Sie Ihre PHP Anwendung Schritt für Schritt modernisieren können, und erfahren auch, warum ein Reworking mit stetigem Refactoring besser als ein Rewrite mit einmaligem Relaunch ist.
4. Ralf EggertRalf Eggert 44 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Legacy ApplicationLegacy Application
5. »Der Begriff Altsystem (englisch
legacy system) bezeichnet in der
Informatik eine etablierte,
historisch gewachsene
Anwendung im Bereich
Unternehmenssoftware.
Legacy ist hierbei das englische
Wort für Vermächtnis,
Hinterlassenschaft, Erbschaft, auch
Altlast.«
Wikipedia Deutschland
6. »The app was written some time
ago, its original authors moved on
taking knowledge with them (lost
knowledge).
Subsequent authors changed the
application based on insufficient /
lost knowledge, introducing bugs
and de-stabilizing it.
The app is now brittle, and
people are reluctant to change it for
fear of breaking it.«
Phil Murphy
Forrester Research, Inc.
7. »The main thing that distinguishes
legacy code from non-legacy code is
tests, or rather a lack of tests.«
Michael Feathers
Autor von
»Working Effectively with Legacy Code«
8. »Legacy Applications sind
historisch gewachsen und
niemand traut sich mehr,
Änderungen im Großen oder
Kleinen vorzunehmen.
Neue Features werden nur
langsam oder gar nicht
implementiert.
Sollten Tests vorhanden sein, geben
diese auch keine Sicherheit.«
Ralf Eggert
Travello GmbH
10. Ralf EggertRalf Eggert 1010 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 1: Rewrite vs. RefactoringTipp 1: Rewrite vs. Refactoring
11. Ralf EggertRalf Eggert 1111 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
RewriteRewrite
12. Ralf EggertRalf Eggert 1212 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
RefactoringRefactoring
14. »Netscape made the single worst
strategic mistake that any software
company can make:
They decided to rewrite the code
from scratch.
This one decision cost Netscape
3 years.«
Joel Spolsky
Stack Overflow / Trello
15. »Mit seiner langen Entwicklungszeit
von 14 Jahren und immer wieder
verschobenen
Veröffentlichungsterminen war es
lange eines der bekanntesten
Vaporware-Produkte.«
Wikipedia Deutschland
16. »Für ein eigenes Projekt haben in
der Vergangenheit zwei mal einen
Rewrite gestartet. Zweimal wurde
der Rewrite abgebrochen.
Jetzt machen wir ein
schrittweises Refactoring.«
Ralf Eggert
Travello GmbH
17. Ralf EggertRalf Eggert 1717 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Vergleich Rewrite und Refactoring
Rewrite Refactoring
Ressourcen aufteilen oder verdoppeln ✔ -
Entwicklerwissen in Teams splitten ✔ -
Verlust von Marktanteilen möglich ✔ -
Ausfallzeiten bei Relaunch möglich ✔ -
Features doppelt implementieren ✔ -
Bessere Architektur nicht garantiert ✔ -
Neue Technologien einführen ✔ ( )✔
18. Ralf EggertRalf Eggert 1818 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 2: Schrittweises RefactoringTipp 2: Schrittweises Refactoring
19. Ralf EggertRalf Eggert 1919 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
SelbstdisziplinSelbstdisziplin
20. Ralf EggertRalf Eggert 2020 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
ChaosChaos
21. Ralf EggertRalf Eggert 2121 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Schritt 1: Composer einführen
Schritt 2: Dependency Injection einführen
Schritt 3: Controller konsolidieren
Schritt 4: SQL Abfragen abstrahieren
usw.
Schritte nacheinander ausführen
22. Ralf EggertRalf Eggert 2222 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 3: TestsTipp 3: Tests
23. Ralf EggertRalf Eggert 2323 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Das Untestbare testen?Das Untestbare testen?
24. Ralf EggertRalf Eggert 2424 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Unit Tests
Testpyramide nach Mike Cohn
Mike Cohn
Service Tests
UI
Tests
25. Ralf EggertRalf Eggert 2525 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Testpyramide Variante
Unit Tests
Integration Tests
End-to-End
Tests
26. Ralf EggertRalf Eggert 2626 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Testpyramide Legacy Applications
Unit Tests
Integration Tests
End-to-End
Tests
Ralf Eggert
Travello GmbH
27. Ralf EggertRalf Eggert 2727 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
End-to-End Tests
namespace EndToEndTest;
use PHPUnitFrameworkTestCase;
class RegistrationTest extends TestCase
{
/**
* @backupGlobals
*/
public function testRegister()
{
$_POST = [
'user_name' => 'Ralf Eggert',
'user_email' => 'ralf@travello.com',
'submit_user_registration' => 'submit_user_registration',
];
require __DIR__ . '/../public/index.php';
$newUser = Legacy_Application_UsersModel::getUserByEmail('ralf@travello.com');
$this->assertEquals($_POST['user_name'], $newUser['name']);
$this->assertEquals($_POST['user_email'], $newUser['email']);
}
}
28. Ralf EggertRalf Eggert 2828 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 4: ComposerTipp 4: Composer
29. Ralf EggertRalf Eggert 2929 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Composer? Ernsthaft?Composer? Ernsthaft?
31. Composer einführen
Immer alle Abhängigkeiten abbilden
(keine Ausnahmen).
Zuerst bisherige Versionen
verwenden und Autoloading für
komplette Anwendung nutzen.
Wenn Anwendung läuft, die
neuesten Versionen der
Abhängigkeiten verwenden.
https://getcomposer.org
32. Kein Composer Paket vorhanden?
Gepatchte Libraries?
Anderen Quatsch gemacht?
SATIS
33. Ralf EggertRalf Eggert 3333 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Kein Composer? Es ist 2017!Kein Composer? Es ist 2017!
34. Ralf EggertRalf Eggert 3434 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 5: Tech-Stack aktualisierenTipp 5: Tech-Stack aktualisieren
37. Ralf EggertRalf Eggert 3737 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 6: Legacy WeicheTipp 6: Legacy Weiche
39. »Es ist unvermeidlich, dass manche
Bereiche bei parallelen
Anwendungen doppelt gepflegt
werden müssen.
Dies könnten zugrundeliegende
Layouts sein, aber vor allem
Konfigurationen für Legacy und die
moderne Anwendung.
Halten Sie diese doppelten Bereiche
aber so gering wie möglich.«
Ralf Eggert
Travello GmbH
40. Ralf EggertRalf Eggert 4040 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Apache 2 .htaccess Weiche
RewriteEngine On
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
// new features for modern application
RewriteRule ^new_user modern.php [NC,L]
RewriteRule ^new_feature modern.php [NC,L]
RewriteRule ^index.php modern.php [NC,L]
// no new stuff? let the legacy application handle it
RewriteRule ^.*$ legacy.php [NC,L]
41. Ralf EggertRalf Eggert 4141 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
ZendExpressive Middleware I
namespace LegacyMiddleware;
use InteropHttpServerMiddlewareDelegateInterface;
use InteropHttpServerMiddlewareMiddlewareInterface;
use PsrHttpMessageServerRequestInterface as Request;
use ZendExpressiveRouterRouteResult;
class LegacyApplicationMiddleware implements MiddlewareInterface
{
public function process(
Request $request, DelegateInterface $delegate
) {
$result = $request->getAttribute(RouteResult::class, false);
if ($result instanceof RouteResult) {
return $delegate->process($request);
}
return $this->handleLegacy();
}
/* ... */
}
42. Ralf EggertRalf Eggert 4242 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
ZendExpressive Middleware II
namespace LegacyMiddleware;
use ZendDiactorosResponseHtmlResponse;
use Zend_Application;
class LegacyApplicationMiddleware implements MiddlewareInterface
{
public function handleLegacy()
{
ob_start();
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);
$application->bootstrap();
$application->run();
$output = ob_get_contents();
ob_end_clean();
return new HtmlResponse($output);
}
}
45. Ralf EggertRalf Eggert 4545 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 7: Dependency InjectionTipp 7: Dependency Injection
46. Ralf EggertRalf Eggert 4646 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Dependency Injection Pattern
Class
PostService
instanziiert
Class
PostItem
Class
PostService
wird injiziert
Class
PostItem
Harte Abhängigkeit Injizierte Abhängigkeit
Interface
ItemInterfaceimplementiert implementiert
47. Ralf EggertRalf Eggert 4747 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
DI Codebeispiel
// harte Abhängigkeit
class PostService
{
public __construct()
{
$this->item = new PostItem();
}
}
// Dependency Injection per Setter
class PostService
{
public setItem(PostItem $item)
{
$this->item = $item;
}
}
// Dependency Injection per Konstruktor
class PostService
{
public __construct(
PostItem $item
) {
$this->item = $item;
}
}
// Dependency Injection mit Interface
class PostService
{
public __construct(
ItemInterface $item
) {
$this->item = $item;
}
}
51. Ralf EggertRalf Eggert 5151 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 8: CodestrukturTipp 8: Codestruktur
55. Ralf EggertRalf Eggert 5555 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Tipp 9: Last Boy Scout RegelTipp 9: Last Boy Scout Regel
56. Ralf EggertRalf Eggert 5656 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Nein, nicht Bruce!Nein, nicht Bruce!
57. The Boy Scouts have a rule: »Always
leave the campground cleaner than
you found it.«
What if we followed a similar rule in
our code: »Always check a module
in cleaner than when you checked
it out.«
Robert C. Martin
(Uncle Bob)
58. Opportunistic Refactoring
(last boy-scout rule)
»What this means is that at any time
someone sees some code that isn't
as clear as it should be, they should
take the opportunity to fix it right
there and then - or at least within a
few minutes.«
Martin Fowler
59. »Wenn du an einer Methode oder
Klasse arbeitest, investiere maximal
15 Minuten, um den Code zu
verbessern.«
Ralf Eggert
Travello GmbH
64. Ralf EggertRalf Eggert 6464 vonvon 6464
9 Tipps für die Modernisierung von PHP-Anwendungen9 Tipps für die Modernisierung von PHP-Anwendungen
Bildnachweis
Ralf Steinberger
Abandoned factory building
in Northern Italy.
(CC BY 2.0)
Chris Potter
3D Home Inspection Checklist
(CC BY 2.0)
Swaroop C H
Green fields
(CC BY-SA 2.0)
Aapo Haapanen
Renovation
(CC BY 2.0)
Sunjo
Feuerwerk
(CC BY-SA 2.0)
Frederik Magle Music
Conductor - Frederik Magle
conducting a symphony orchestra 9
(CC BY 2.0)
Rebecca Siegel
Stack
(CC BY-SA 2.0)
Kecko
St. Margrethen - Switzerland
(CC BY 2.0)
slgckgc
September 2012 Court of Honor
(CC BY 2.0)
Daisuke tashiro
Long long stairs
(CC BY-SA 2.0)
Tomas Sobek
Walking down to Rock Burn Valley
(CC BY 2.0)
Mike Mozart
Mess
(CC BY 2.0)
Adrian Sampson
Cable closet
(CC BY 2.0)
Thomas Claveirole
Gears
(CC BY-SA 2.0)
Eduard Anton
Structure
(CC BY 2.0)
Rohit Chhiber
Snotty doubt
(CC BY 2.0)