Planning for the Unplannable (IPC14 SE)
-
Upload
robert-lemke -
Category
Technology
-
view
891 -
download
0
description
Transcript of Planning for the Unplannable (IPC14 SE)
Planning for the Unplannable Framework-Grade Architecture
Robert Lemke - TechDivision GmbH
TEXT HERE
Robert Lemke !
38 years old developer for 27 years lives in Lübeck, Germany software architect at TechDivision TYPO3 Association co-founder TYPO3 Flow & TYPO3 Neos project founder1 wife, 2 daughters, 1 espresso machine
Framework-Grade?
Architecture?
Image © Arquivo Nacional Brasil
Image © 2014 Landsat / © 2014 GoogleImage © 2014 SIO, NOAA, U.S. Navy, NGA, GEBCO, Landsat, Google, Inav/Geosistemas SRL, Mapcity
TEXT HERE
„this experiment was not successful”
Oscar Niemeyer 2001
Photo © Marcelo Coelho
TEXT HERE
If you know that you can’t planfor something, just
plan for the unplannable.
Flexibility and quality are key
Experience
Design Patterns
Loose Coupling
High Cohesion
Law of Demeter
- each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
- each unit should only talk to its friends;don't talk to strangers.
- only talk to your immediate friends.
Code against interfaces
Dependency Injection
<?php!class IsbnLookupService { protected static $instance; public function getInstance() { if (self::$instance === NULL) { self::$instance = new self; } return self::$instance; }}!!class BookSearchController { public function action() { $service = IsbnLookupService::getInstance(); … } }!
class ServiceLocator { protected static $services = array(); public function getInstance($name) { return self::$service[$name]; }!}!!class BookSearchService { public function action() { $service = ServiceLocater::getInstance("IsbnLookupService"); … } }
class BookSearchController extends ActionController {! /** * @var IsbnLookupService */ protected $isbnLookupService; /** * @param IsbnLookupService $isbnLookupService */ public function __construct(IsbnLookupService $service) { $this->isbnLookupService = $service; } }
class BookSearchController extends ActionController {! /** * @var IsbnLookupService */ protected $isbnLookupService; /** * @param IsbnLookupService $isbnLookupService */ public function injectLookupService(IsbnLookupService $service) { $this->isbnLookupService = $service; } }
class BookSearchController extends ActionController {! /** * @Flow\Inject * @var IsbnLookupService */ protected $isbnLookupService;!}
class BookSearchController extends ActionController {! /** * @Flow\Inject * @var IsbnLookupServiceInterface */ protected $isbnLookupService;!}
Acme\Controller\BookSearchController: properties: isbnLookupService: className: Amazon\Service\IsbnLookupService
Planned and Unplanned Extensibility
Configuration
Signal-Slot Pattern
Observer, Dispatcher, Publish-Subscribe, Event-Notifier,
Event Sourcing …
Define a public API with @api
Aspect-Oriented Programming
Dependency Management: Composer, requirejs, …
Reinvent the Wheel!
Unit Tests
Functional Tests
System / Behavior Tests
Understanding other people’s code
Code Ownership
Software Rot
Be picky!Fix broken windows!
Remove unused code
Write code because it adds value(not only because you can)
But maybe we need it (YAGNI)
Be canny with configuration
Reviews
Change your perspective
Readable Code
TYPO3 Flow Coding Guidelines on one page
<?phpnamespace Acme\TestPackage;
/* * * This script belongs to the TYPO3 Flow package "Acme.TestPackage". * * * * It is free software; you can redistribute it and/or modify it under * * the terms of the GNU General Public License, either version 3 of the * * License, or (at your option) any later version. * * * * The TYPO3 project - inspiring people to share! * * */
use Acme\TestPackage\Service\FooGenerator;use TYPO3\Flow\Annotations as Flow;
/** * Here goes the description of the class. It should explain what the main * purpose of this class is... * * @Flow\Scope(”singleton”) */class UniverseAnalyzer extends BaseClass implements SomeInterface {
/** * Some injected dependency * * @Flow\Inject * @var FooGenerator */protected $someDependency = NULL;
/** * Shows if you are addicted to TYPO3 Flow * * @var boolean */static protected $addictedToFlow = TRUE;
/** * Shows if you are a fan of TYPO3 Flow * * @var boolean */protected $fanOfFlow;
/** * A great method which shows how to indent control structures. * * @param MyClass $object An instance of MyClass * @param array $someArray Some array * @return void * @throws \Exception */public function analyzeUniverse(MyClass $object, array $someArray = array()) {
$subObjects = $object->getSubObjects();foreach ($subObjects as $subObject){
/** @var $subObject MySubClass */$subObject->doSomethingCool();
}if (isset($someArray['question'])
&& $this->answerToEverything === 42|| count($someArray) > 3) {
$this->fanOfTYPO3Flow = TRUE;} else {
throw new \Exception('We cannot tolerate that.', 1223391710);}
}
/** * This is a setter for the fanOfFlow property. * * @param boolean $isFan Pass TRUE to mark a fan, FALSE for a Zend follower * @return mixed */public function setFanOfFlow($isFan) {
$this->fanOfFlow = $isFan;}
/** * As simple as it gets – a boolean getter. * * @return boolean Whether a foo was detected (TRUE) or not (FALSE) * @api */static public function isAddictedToFlow() {
return self::$addictedToFlow;}
}?>
Also check out the latest documentation: http://docs.typo3.org/flow/TYPO3FlowDocumentation/TheDefinitiveGuide/PartV/CodingGuideLines/Index.html
Description of the class. Make it as long as needed, feel free to explain how to use it.
Namespace starts with vendor name followed by package key (name) and subparts as needed
UpperCamelCase class name. Class names should be nouns.In other packages, import \Acme\TestPackage\UniverseAnalyzer and refer to it as UniverseAnalyer.
Opening brace on same line with opening token. One space before.
Use @var tag. Optional description goes in the first comment line followed by a blank comment line.
Indent with tabs.
Multiline conditions:Indent them and add a extra indent to following code. Put the boolean operators at beginning of line.
Write what went wrong, give helpful details and give a hint for a possible solution.
UNIX timestamp at time of writing the throw clause.
Description of the method. Make it as long as needed.
Use type hinting
Methods returning boolean values should start with “has” or “is”. Other getters should start with “get“.
Setter methods should start with “set”.
Method names should be verbs.
@return tag with type, even if it is “void”. Only __construct() has no return tag.
static and abstract keywords before the visibility modifier
@api tag defines public API
One use statement per line.One use statement per namespace.Order statements alphabetically.Don't import namespaces unless you use them.
No empty line between DocComment and class, member var or method.
Prefer relative namespaces, unless Fully Qualified Namespace is more readable
Param tag: type, name, description.
Only use inline @var annotations when type can't be derived (like in an array of objects) to increase readability and trigger IDE auto-completion.
List @Flow\* before other tags: @var, @param, @return, @throws, @api, @since, @deprecated
Capture the joy of coding as you create excellent web solutions.Enjoy coding. Enjoy Flow.
http://rlmk.me/flowcgl
Naming
$path $pathAndFilename $filename $directory $directoryName $class $className
© „davic” (Flickr)
© „¡Carlitos” (Flickr)
borrowed a lot from:
The pragmatic programmer Code complete
All Martin Fowler Books (PoEAA)
TEXT HERE
@robertlemke !
robertlemke.com flow.typo3.org neos.typo3.org techdivision.com