patterns, paradigms, and governance 2013-10-03
DESCRIPTION
Scaling PHP How patterns, paradigms, and governance can help you scale PHP performance and enable engineers contributing to your projectTRANSCRIPT
WHAT IS SHAPEWAYS?
2
Shapeways
3
http://www.shapeways.comhttp://developers.shapeways.comhttp://shapejs.shapeways.com
The worlds leading 3D printing marketplace and community
ARCHITECTURE
4
Architecture - System
5
Architecture - Framework
6
Road Runner
Architecture – Performance History
7
PATTERNSPARADIGMS
GOVERNANCE
8
Patterns, Paradigms, and Governance
9
• How do these concepts help us scale PHP ?• Will I see concrete actionable examples ?• Will you show me some hardcore PHP h4x ?
• Patterns – code• Paradigms – knowledge• Governance – process
10
PATTERNS
11
Programatically enforced goodness
Patterns – Traits of Goodness
12
• Accessibility• Repeatability• Clear Rationale
Patterns - Accessibility
13
• An accessible pattern is one that is intuitive, documented, and when invoked, reads like natural language
• Reading code that follows an accessible pattern is easier than reading code that does not follow
Patterns - Repeatability
14
• The repeatability of a pattern will ultimately decide its adoption
• If I can copy and paste, or use a scaffold for a pattern, the pattern is repeatable and will proliferate itself throughout the code
Patterns – Clear Rationale
15
• You need to be able to explain why a pattern was chosen
• All patterns have shortcomings – the *why* behind the pattern’s design and proliferation is critical in maintaining adherence
Pattern Examples: MVC
16
abstract class RoadRunnerController { $model = $this->getModel(); if($this->preHandle($model)) { $this->handleRequest($model); $this->postHandle($model); } $this->finalize($model);}
Pattern Examples: Auto-wiring
17
// Autowire the model managerpublic function preHandle($shapewaysModel, ModelManager $modelManager) { // do something with the ModelManager return parent::preHandle($shapewaysModel);}
I can use any Manager in our domain model by adding it to my function signature.
Pattern Examples: Auto-wiring
18
public function invokeWithManagers($object, $function, $parameters){ $controllerClass = get_class($object); $function = new ReflectionMethod($controllerClass, $function); foreach ($function->getParameters() as $reflectionParameter) { $parameterClass = $reflectionParameter->getClass(); $parameterClassName = $parameterClass->getName(); // substr is much faster than pregmatch! if (substr($parameterClassName, -7) === "Manager") { $parameters[] = $this->instantiateManager($parameterClassName); } } return $function->invokeArgs($object, $parameters);}
PARADIGMS
19
Good things you need to know
20
Paradigms – Traits of Goodness
• Explicit• Consistent• Provide Clear Value
21
Paradigms – Explicit
A paradigm is explicit when the functionality exposed can be understood from the invoking side.
Explicit paradigms show visibly throughout a codebase.
22
Paradigms – Consistent
A paradigm is consistent when it is applied consistently and everywhere applicable in the code.
If your paradigm is only consistent in 60% of your code base, chances are high that folks will copy and proliferate code that violates the paradigm.
23
Paradigms – Provide Clear Value
It is important for the entire team to understand and agree on the value of a paradigm.
Paradigms can easily feel like overhead - it is important to know *why* we choose to adhere to a paradigm.
Paradigm Examples - Constants
$myObj->callFunction( ',', true, false, false);
Vs.
$myObj->callFunction( MyObj::DELIMITER_COMMA, MyObj::MATCH_MULTIPLE, MyObj::LOG_RESULTS, MyObj::SKIP_DUPLICATES);
24
Paradigm Examples – More Constants
$_REQUEST["userId"]
Vs.
const REQUEST_USER_ID = "userId";…$_REQUEST[self::REQUEST_USER_ID];
25
Paradigm Examples - Consistent
• Code Style• Enum/Lookup Tables• Parameter marshaling
26
Paradigm Examples – More Constants
27
Paradigm Examples – One to Many
Making one query vs. two is often faster
SELECT umf.id… , mfma.model_file_material_asset_id… FROM udesign_model_file umf LEFT JOIN model_file_material_asset mfma ON mfma.model_file_id = umf.id
28
Paradigm Examples – One to Many
Generic function for mapping objects
/** * Select an array of objects using the given EntityMapper * * @param $db the database link to use (read-only/read-write/etc) * @param $sql the query * @param $mapper EntityMapper * @return array */public function selectObjects($db, $sql, $mapper){ $db = $this->getDbLink($db); $this->checkDBConnection($db); // Add backtrace information to the SQL as a comment // This helps immensely in slow query identification $sql = $this->prependURL($sql);
if ($resultSet = $this->runQuery($sql, $db)) { while ($row = mysql_fetch_assoc($resultSet)) { $mapper->mapRow($row); } mysql_free_result($resultSet); }
return $mapper->getResults();}
29
Paradigm Examples – One to Many
Mapping results follows a paradigm
public function mapRow($row){ if (!isset($this->rows[$row['id']])) {
$this->rows[$row['id']] = new ModelFileEntity( $row['id'] ); }
$modelFile = $this->rows[$row['id']];
if (isset($row['model_file_material_asset_id'])) { $modelFileMaterialAsset = new ModelFileMaterialAsset( $row['model_file_material_asset_id'] ); $modelFile->addModelFileMaterialAsset($modelFileMaterialAsset); }}
30
Paradigm Examples – Caching
Cache derived data
public function getPrice(){ if ($this->getPrice_cache !== NULL) return $this->getPrice_cache; // if override is set, use that if (($this->getPrice_cache = $this->getPriceOverride()) !== NULL) { return $this->getPrice_cache; } else { return ($this->getPrice_cache = $this->getPriceOriginal()); }}
31
Paradigm Examples – Caching
Give control to the engineers
public function getCurrencyById() { $cacheKey = 'currencyById-' . $currencyId . '-' . date(RoadRunnerDB::DATE_FORMAT_DAY); $currency = null; if(RoadRunnerLocalCache::get($cacheKey, $currency) === FALSE) { if (($currency = $this->memcacheGet($cacheKey, 0)) === FALSE) { $currency = $this->currencyDB->getcurrencyById($currencyId); $this->memcacheSet($cacheKey, $currency, 0); } RoadRunnerLocalCache::set($cacheKey, $currency); } return $currency;}
32
GOVERNANCE
33
For the good of all
Governance
Governance is the most difficult of all the goodness to achieve, and likely it is the most important for performance.
If you can find a problem before it is live, you are 10x more likely to fix it before it impacts your users and your bottom line.
34
Governance Example – DB Query Review
35
Governance Example – DB Query Review
36
Governance Example – DB Query Review
37
Governance Example – Tracking
38
Governance Example – Tracking
watch -n1 "cat rps_uri.sql | mysql tracking"
39
Governance Example – Tracking
40
Governance Example – Quality
41
THANK YOU
42