Drupal 8A Story of Growing Up and Getting Off the Island
Angela "@webchick" Byron php[world]
November 13, 2014
Who the heck are you?
@webchick
What the heck are we talking about?
• A brief intro to Drupal • Then vs. now • Re-writing your code base: a how-to
guide • Lessons learned
Once upon a time…
…in a dorm room far away (Antwerp, Belgium)…
Once upon a time…
…in a dorm room far away (Antwerp, Belgium)…
DRIES BUYTAERT
Once upon a time…
…in a dorm room far away (Antwerp, Belgium)…
IKEA furniture
DRIES BUYTAERT
Once upon a time…
…in a dorm room far away (Antwerp, Belgium)…
Chess board
IKEA furniture
DRIES BUYTAERT
Once upon a time…
…in a dorm room far away (Antwerp, Belgium)…
Chess board
Stamp collection
IKEA furniture
DRIES BUYTAERT
…A domain name registration was mis-typed…
(Fun fact: Dries meant to register 'dorp.org,' which is Dutch for village, and accidentally found that drop.org was available.)
…And a project called "Drupal" was born.
(Fun fact: "Drupal" is an Anglicization of the word "druppel" which is Dutch for "drop.")
What is Drupal?(Some context setting)
A content management system (to get you 80% there)
A content management system (to get you 80% there)
Turn on features ("modules")
A content management system (to get you 80% there)
Turn on features ("modules")
Build content model ("entities" and "fields")
A content management system (to get you 80% there)
Turn on features ("modules")
Build content model ("entities" and "fields")
Create custom listings ("views")
A content management system (to get you 80% there)
Turn on features ("modules")
Build content model ("entities" and "fields")
Create custom listings ("views")
Make it purdy ("themes")
A content management system (to get you 80% there)
Turn on features ("modules")
…zero lines of code.
Build content model ("entities" and "fields")
Create custom listings ("views")
Make it purdy ("themes")
A content management framework (for that last ~20%)
Add/extend functionality, integrate with third-party systems
An awesome community! (1.1M+ users, 35K+ developers, 2,400+ core contributors)
Lots from non-traditional backgrounds, self-taught PHP via Drupal
Powering 2% of the web
Welcome to the Isle of Drupal!
Founded in 2001
Back then, OO PHP support wasn't stellar
So we had to invent creative ways to extend without OOP…
…and many of these workarounds persist to this day.
Hooks... foreach (module_list() as $name) { module_invoke($module_name, 'permission'); }...!
!
function example_permission() { return array('administer examples');}
example.module
user.module
Hooks... foreach (module_list() as $name) { module_invoke($module_name, 'permission'); }...!
!
function example_permission() { return array('administer examples');}
example.module
user.module
Hooks... foreach (module_list() as $name) { module_invoke($module_name, 'permission'); }...!
!
function example_permission() { return array('administer examples');}
example.module
user.module
Magically Named "Mystery Meat" Functions
example.modulefunction example_form() { $form['greeting'] = array( '#type' => 'textfield', '#title' => t('Enter a greeting'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Greet me'), ); return $form;}!function example_form_validate($form, &$form_state) { // Validate logic.}!function example_form_submit($form, &$form_state) { // Submit logic.}
Magically Named "Mystery Meat" Functions
example.modulefunction example_form() { $form['greeting'] = array( '#type' => 'textfield', '#title' => t('Enter a greeting'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Greet me'), ); return $form;}!function example_form_validate($form, &$form_state) { // Validate logic.}!function example_form_submit($form, &$form_state) { // Submit logic.}
Magically Named "Mystery Meat" Functions
example.modulefunction example_form() { $form['greeting'] = array( '#type' => 'textfield', '#title' => t('Enter a greeting'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Greet me'), ); return $form;}!function example_form_validate($form, &$form_state) { // Validate logic.}!function example_form_submit($form, &$form_state) { // Submit logic.}
Build/Alter Patternexample.modulefunction example_menu() { $items['example'] = array( 'title' => 'Example page', 'page callback' => 'example_page', 'access callback' => 'user_access', 'access arguments' => array('administer foo'), ); return $items;}!!function custom_menu_alter(&$items) { $items['example']['access arguments'] = array('view content');}
custom.module
Build/Alter Patternexample.modulefunction example_menu() { $items['example'] = array( 'title' => 'Example page', 'page callback' => 'example_page', 'access callback' => 'user_access', 'access arguments' => array('administer foo'), ); return $items;}!!function custom_menu_alter(&$items) { $items['example']['access arguments'] = array('view content');}
custom.module
Mistrust of third-party code
Mistrust of third-party code
Pain Points• Requires "unlearning"
• ArrayPIs • Drupalisms
• "Not Invented Here" • Talent pool
Enter Drupal 8
Re-joining the rest of the #phpworld!
Composer
Components
YAML
Twig
OOP
PSR-4
Services
"Proudly Invented Elsewhere"
"Hello D8 World"
example.hello: path: '/hello' defaults: _content: '\Drupal\example\ExampleController::hello' requirements: _permission: 'access content'
example.routing.yml
example.info.ymlname: Exampledescription: "Example module"core: 8.xtype: module
"Hello D8 World"src/ExampleController.php<?php namespace Drupal\example; use Drupal\Core\Controller\ControllerBase; /** * Returns responses for Example module routes. */class ExampleController extends ControllerBase { public function hello() { return array('#markup' => $this->t('Hello world.')); }}
"Hello D8 World"src/ExampleController.php<?php namespace Drupal\example; use Drupal\Core\Controller\ControllerBase; /** * Returns responses for Example module routes. */class ExampleController extends ControllerBase { public function hello() { return array('#markup' => $this->t('Hello world.')); }}
How did we get here?And how can lessons learned be applied to other
projects?
There are two sides to any massive migration
Code
There are two sides to any massive migration
Code People
There are two sides to any massive migration
Code Peopleignore this side at your GREAT peril!
0. Set the stagePre-requisites to have in place first
Get your user base onto a modern platform
(Fun fact: The GoPHP5 movement—a coalition of open source projects and hosts to expedite dropping support for PHP4 in 2007—was founded by Drupalistas! :))
Add metric butt-loads of automated test coverage
Including continuous integration, so you can fix failures before commit (Fun fact: Drupal's 50K+ tests stayed 100% passing throughout D8's development)
Introduce a "taste" of the future
db_update('example') ->condition('id', $id) ->fields(array('field2' => 10)) ->execute();
Introduce concepts of OO and external libraries, get people comfortable with basics before going all out.
1. Set ambitious goalsThere's going to be a lot of pain before the pay-off; make
the pay-off worth it.
Drupal 8 initiatives
configurationmanagement Mobile
Multilingual web servicesViews
AUTHORING EXPERIENCE
Refactor as part of achieving those goals
The most successful initiatives had leaders who…
• Communicated "early and often"!
• Documented decision-making
• Built a team around them!
• And genuinely valued that team
• Sought ways to "scale" themselves!
• Delegation
• Re-usable training material
http://hojtsy.hu/blog/2014-oct-17/authority-drupal-andor-open-source-general
2. Major change needs major buy-in
Winning hearts and minds
Get the right people in the right room
Web Services sprint: • Drupal and Symfony
project leads • Initiative leads • Community voices • Detractors
http://buytaert.net/the-future-is-a-restful-drupal
Detractors? Huh?• "Pure" trolls rarely exist!
• But people feeling unheard, frustrated do
• Provide outlet to air legitimate concerns!• Who knows; they might actually be
right! • Build trust; remove defensiveness!
• Ownership in process can turn detractors into advocates
Show your work! (Just like in math class. :))
• Can't just come back with a "decree" and expect people to fall in line.!• Folks need to understand and
trust in your thought process • Transparency++ • "Issue queue or it didn't happen"
3. Git 'er doneIterate, iterate, iterate.
Shameless rip-off time! :)
Thanks, Larry! Go check out the whole thing: http://www.palantir.net/presentations/lsp14-eating-elephpants/
How does one eat an elePHPant?
One bite at a time…
…with friends
…with lots of friends
For new functionality
"Writing code should not be the first response. Finding if shared code exists should be the
first response.
— Beth Tucker-Long, Editor-in-Chief, php[architect]
For existing functionality
• Refactor your app, don't replace it
• Replace your component, don't refactor it
• Especially cryptography!
• Build new code as components, share with yourself
• However! If ain't broke, don't fix it.
Drupal 7
Drupal 8 (early)
Remember: Incremental progress is still progress!
4. Recognize that major change is scary
Empathy is your friend
Fear of losing investment in platform
Particularly if it's your code that's being replaced.
Fear of going back to "square one" and being unable to catch up
Especially pertinent for an aging community; hard to spend nights and weekends learning new things with kids and a mortgage
Fear of the unknown
Not just OO, Symfony, but also entire toolchain; IDE vs. simple text editor/grep
Fear of losing what makes your community "you"
Will hobbyists, non-techies be able to make the transition?
What helps?• Connecting: talking it out, sprints, planning meetings
• Documentation: "conceptual" overviews, detailed API docs, books
• Training: presentations, examples, blog posts
• Tools: inspectors, scaffolding, automated code porting
• DX (Developer Experience): eliminate boilerplate code, consistency/learnability of patterns
• Reinforce that OO practices are used everywhere, may as well learn on a platform they already know!
When "stuff" hits the fan…
5 tips on handling a fork• Resist reacting. Instead, listen. • Dispel FUD, but take the high road • Help existing devs accentuate the
positive • Try and maintain relationship with forkers • If concerns resonate, address them
Example: Semantic Versioning
• Feature releases every 6 months • Backwards compatibility preserved • Both core devs and users working on same code base! • Drupal 9? Not until there's enough to warrant breaking BC
5. Avoid common pitfalls
Learn from our mistakes! Please!
• The perfect is the enemy of the better. • "All you can eat" gives you a tummy-
ache. • Don't be afraid to say "no." • Make decisions early and explicitly
In Summary
1. Set the stage
2. Set ambitious goals
3. Major change needs major buy-in
4. Recognize that major change is scary
5. Avoid common pitfalls
We're not out of the woods yet…
…but we're thrilled to once again re-join the PHP world :)
Thank you!Angela "@webchick" Byron
php[world] November 13, 2014
https://joind.in/11919