Drupal 8: A story of growing up and getting off the island

Preview:

DESCRIPTION

The Drupal project has traditionally held a strong internal value for doing things "The Drupal Way." As a result, Drupal developers have historically needed to build up reams and reams of tricks and workarounds that were specific to Drupal itself, and Drupal was inaccessible to people with a more traditional programming background. Starting in Drupal 8, however, we've effectively done a ground-up rewrite of the underlying code and in the process made major inroads to getting more inline with the rest of the PHP world. Procedural code is out, OO code is in. "Creative" hacks have been replaced with FIG standards. "Not invented here" is now "Proudly found elsewhere." This story will talk about the journey that Drupal 8 and the Drupal core development team has taken during this transition over the past 3+ years, including some of the pros and cons of this approach and how we dealt (and are dealing) with some of the community management challenges that resulted.

Citation preview

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

Recommended