IPC13 Munich: Planning the Unplannable
-
Upload
robert-lemke -
Category
Technology
-
view
671 -
download
0
description
Transcript of IPC13 Munich: Planning the Unplannable
Planning for the unplannable
project founder of TYPO3 Flow and TYPO3 Neos
co-founder of the TYPO3 Association
software architect at TechDivision
37 years old
lives in Lübeck, Germany
1 wife, 2 daughters, 1 espresso machine
likes drumming
!
Experience
„Architecture”
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.
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
Design Patterns
Reinvent the Wheel!
Planned and Unplanned Extensibility
Configuration
Signal-Slot Pattern
Observer, Dispatcher, Publish-Subsribe, Event-Notifier, …
Define a public API with @api
Code against interfaces
DI + Interfaces
AOP
Dependency Management: Composer, requirejs, …
Unit Tests
Functional Tests
System Tests
Understanding other’s code
Code Ownership
Software Rot
Remove unused code
Write code because it adds value (not because you can)
But maybe we need it (YAGNI)
Be canny with configuration
Reviews
Change your perspective
Be picky!Fix broken windows!
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
The pragmatic programmer Code complete All Martin Fowler Books (PoEAA)
@robertlemke
robertlemke.com