SlideShare a Scribd company logo
DrupalCon Amsterdam 2019
Multilingualism makes
better programmers
A look beyond PHP and JavaScript
Photo by Émile Perron on Unsplash
describe(‘Alexander Varwijk’)
• Programming for 15+ years
• 7 years of Drupal
• Developer for Open Social
• Love for sports, beer and pretty code
• A look outside of our comfort zone
• Not every example works in PHP/JS
• Concepts/Thought process is still useful
• Examples from Ruby, Java, Rust, Javascript, Perl
About this talk
What’s in a 

(programming) language?
Syntax
The arrangement of words and phrases
to create well-formed sentences in a language
The structure of statements in a computer
language
“ How do I express what I want to do? ”
(Standard) Library
A standard library in computer programming
Is the library made available across
Implementations of a programming language.
“ What can I use without installing something else? ”
Ecosystem
A collection of software projects, which are developed
and co-evolve in the same environment.
Can be organizational (a company), social (an open-
source community), or technical (the Ruby
ecosystem)
“ What has already been built that I can use? ”
“Ruby, Ruby, Ruby, Ruby”


— Kaiser Chiefs
The Ruby Styleguide
• A community driven effort to create standards.
• Applicable beyond Ruby
rubocop-hq/ruby-style-guide
Keep functions short
Avoid methods longer than 10 LOC (lines of code).
Ideally, most methods will be shorter than 5 LOC.
Empty lines do not contribute to the relevant LOC.
Keep functions short
• Give functions a single purpose
• Reduces mental load
• Makes it easier to put the code in presentations ;-)
• Find the right balance
function social_post_form_post_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Show the users picture for new posts.
if ($form_state->getFormObject()->getEntity()->isNew()) {
// Load current user.
$account = User::load(Drupal::currentUser()->id());
// Load compact notification view mode of the attached profile.
if ($account) {
$storage = Drupal::entityTypeManager()->getStorage('profile');
$user_profile = $storage->loadByUser($account, 'profile');
if ($user_profile) {
$content = Drupal::entityTypeManager()->getViewBuilder('profile')
->view($user_profile, 'compact_notification');
// Add to a new field, so twig can render it.
$form['current_user_image'] = $content;
}
}
}
// [Snip]
}
function social_post_form_post_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Show the users picture for new posts.
if ($form_state->getFormObject()->getEntity()->isNew()) {
$user_image = social_post_get_current_user_image();
if ($user_image) {
// Add to a new field, so twig can render it.
$form['current_user_image'] = $user_image;
}
}
// [Snip]
}
if as modifier
Prefer modifier if / unless usage when you have a
single-line body.
Another good alternative is the usage of control
flow && / ||.
# good (doesn't work in PHP/JS)
do_something if some_condition
# another good option
some_condition && do_something
function p(x) { process.stdout.write(x); }
function ret_true() {
p("true ");
return true;
}
function ret_false() {
p("false ");
return false;
}
ret_true() && p("&& print");
ret_true() || p("|| print");
ret_false() && p("&& print");
ret_false() || p("|| print");
true && print
true
false
false || print
function p($x) { echo $x; }
function ret_true() {
echo "true ";
return true;
}
function ret_false() {
echo "false ";
return false;
}
ret_true() && p("&& print");
ret_true() || p("|| print");
ret_false() && p("&& print");
ret_false() || p("|| print");
PHP Javascript Output
No method_missing
Avoid using method_missing for metaprogramming
because backtraces become messy, the behavior is not
listed in #methods, and misspelled method calls might
silently work, e.g. nukes.luanch_state = false
Some of PHPs Magic Methods
• __get, __set, __call
• Used extensively by Drupal
• Can make behaviour less predictable
/** Implements the magic method for getting object properties. */
public function &__get($name) {
// If this is an entity field, handle it accordingly. We first check whether
// a field object has been already created. If not, we create one.
if (isset($this->fields[$name][$this->activeLangcode])) {
return $this->fields[$name][$this->activeLangcode];
}
// Inline getFieldDefinition() to speed things up.
if (!isset($this->fieldDefinitions)) { $this->getFieldDefinitions(); }
if (isset($this->fieldDefinitions[$name])) {
$return = $this->getTranslatedField($name, $this->activeLangcode);
return $return;
}
// Else directly read/write plain values. That way, non-field entity
// properties can always be accessed directly.
if (!isset($this->values[$name])) { $this->values[$name] = NULL; }
return $this->values[$name];
}
Javascript Proxy
• Emulates PHP’s magic methods
• MDN Documentation
• Could be a talk on its own
• Doesn’t work in Internet Explorer
Java
Annotations
In the Java computer programming language, an
annotation is a form of syntactic metadata that can
be added to Java source code.
— Wikipedia, Java_annotation
package com.example.examplemod;
import net.minecraft.init.Blocks;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
public class ExampleMod {
public static final String MODID = "examplemod";
public static final String VERSION = "1.0";
public void init(FMLInitializationEvent event) {
// some example code
System.out.println("DIRT BLOCK >> "+Blocks.dirt.getUnlocalizedName());
}
}
package com.example.examplemod;
import net.minecraft.init.Blocks;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
@Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION)
public class ExampleMod {
public static final String MODID = "examplemod";
public static final String VERSION = "1.0";
public void init(FMLInitializationEvent event) {
// some example code
System.out.println("DIRT BLOCK >> "+Blocks.dirt.getUnlocalizedName());
}
}
package com.example.examplemod;
import net.minecraft.init.Blocks;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
@Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION)
public class ExampleMod {
public static final String MODID = "examplemod";
public static final String VERSION = "1.0";
@EventHandler
public void init(FMLInitializationEvent event) {
// some example code
System.out.println("DIRT BLOCK >> "+Blocks.dirt.getUnlocalizedName());
}
}
namespace DrupalimagePluginFieldFieldWidget;
/**
* Plugin implementation of the 'image_image' widget.
*
* @FieldWidget(
* id = "image_image",
* label = @Translation("Image"),
* field_types = {
* "image"
* }
* )
*/
class ImageWidget extends FileWidget {
// Body omitted
}
PHP Annotations
• Not built into the language
• Uses the doctrine/annotations package
• Uses PHP Reflection to read object/method/property comments
• Proposal to move annotations into the PHP runtime (out of
comments). See https://wiki.php.net/rfc/annotations_v2
Javascript Annotations Decorators
• Are used to modify the behaviour of a class or its properties
• Are currently a stage 2 proposal
• https://github.com/tc39/proposal-decorators
• Implementation details changed a lot in March 2019
• Babel allows using these already, 

as well as the legacy stage 1 syntax.
class CounterWidget extends HTMLElement {
}
// Source: https://github.com/tc39/proposal-decorators
import { @defineElement } from "./defineElement.mjs";
@defineElement('counter-widget')
class CounterWidget extends HTMLElement {
}
// Source: https://github.com/tc39/proposal-decorators
import { @tracked } from "./tracked.mjs";
import { @defineElement } from "./defineElement.mjs";
@defineElement('counter-widget')
class CounterWidget extends HTMLElement {
@tracked x = 0;
connectedCallback() { this.render(); }
render() { this.textContent = this.x.toString(); }
}
// Source: https://github.com/tc39/proposal-decorators
import { @tracked } from "./tracked.mjs";
import { @bound } from "./bound.mjs";
import { @defineElement } from "./defineElement.mjs";
@defineElement('counter-widget')
class CounterWidget extends HTMLElement {
@tracked x = 0;
@bound clicked() { this.x++; }
connectedCallback() { this.render(); }
render() { this.textContent = this.x.toString(); }
}
// Source: https://github.com/tc39/proposal-decorators
import { @set } from "./set.mjs";
import { @tracked } from "./tracked.mjs";
import { @bound } from "./bound.mjs";
import { @defineElement } from "./defineElement.mjs";
@defineElement('counter-widget')
class CounterWidget extends HTMLElement {
@tracked x = 0;
@set onclick = this.clicked;
@bound clicked() { this.x++; }
connectedCallback() { this.render(); }
render() { this.textContent = this.x.toString(); }
}
// Source: https://github.com/tc39/proposal-decorators
Rust
Strongly Typed
In a strongly typed language each data area will
have a distinct type and each process will state its
communication requirements in terms of these
types.
— Jackson, K. (1977).
Design and Implementation of
Programming Languages.
Strongly Typed PHP
5.0
5.1
5.4
7.0
7.1
7.4
- Parameter type hints for Interface and Class names
- Parameter type hints for arrays
- Parameter type hints for callables
- Parameter type hints for all primitive types, return type hints
- Nullable types
- Type hints for class properties
/* An example of PHP 7.4's type hints. */
class TypeHintsExample {
protected string $chant = 'PHP is improving!';
public function setChant(string $newChant) {
$this->chant = $newChant;
}
public function chant() {
echo $this->chant . PHP_EOL;
}
public function isAwesome() : bool {
return true;
}
}
/* An example of PHP 7.4's type hints. */
class TypeHintsExample {
protected string $chant = 'PHP is improving!';
public function setChant(string $newChant) {
$this->chant = $newChant;
}
public function chant() {
echo $this->chant . PHP_EOL;
}
public function isAwesome() : bool {
return true;
}
}
$fan = new TypeHintsExample();
$fan->setChant('PHP is improving!');
// Outputs: "PHP is improving!n"
$fan->chant();
$fan->setChant(9001);
// Outputs: "9001n"
$fan->chant();
// Required to actually trigger type errors.
declare(strict_types = 1);
/* An example of PHP 7.4's type hints. */
class TypeHintsExample {
protected string $chant = 'PHP is improving!';
public function setChant(string $newChant) {
$this->chant = $newChant;
}
public function chant() {
echo $this->chant . PHP_EOL;
}
public function isAwesome() : bool {
return true;
}
}
$fan = new TypeHintsExample();
$fan->setChant('PHP is improving!');
// Outputs: "PHP is improving!n"
$fan->chant();
// Throws a TypeError
$fan->setChant(9001);
$fan->chant();
Strongly Typed Drupal
• Parameter type hints in coding standards: Issue #1158720
• Standardising array type hints (11 years and counting): Issue #318016
• Discussion about implementing types in existing code: Issue
#3050720
• Highlights some backwards compatibility issues, 

some solved in PHP 7.2
• Discussion on coding standard for new code: Issue #3060914
Strongly Typed Javascript
• 😅
• There’s Typescript
Pattern Matching
Patterns are a special syntax in Rust for matching
against the structure of types, both complex and
simple.
let x = 1;
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("anything"),
}
// Source: https://doc.rust-lang.org/1.5.0/book/patterns.html
// PHP
switch ($x) {
case 1:
echo "one";
break;
case 2:
echo "two";
break;
case 3:
echo "three";
break;
default:
echo "anything";
}
// Javascript
switch (x) {
case 1:
console.log("one");
break;
case 2:
console.log("two");
break;
case 3:
console.log("three");
break;
default:
console.log("anything");
}
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
i => println!("{} was not in our range", i),
}
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
i => println!("{} was not in our range", i),
}
enum OptionalInt {
Value(i32),
Missing,
}
let x = OptionalInt::Value(5);
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
OptionalInt::Value(..) => println!("Got an int!"),
OptionalInt::Missing => println!("No such luck."),
}
// Source: https://doc.rust-lang.org/1.5.0/book/patterns.html
Enum
The enum keyword allows the creation of a type
which may be one of a few different variants.
namespace DrupalCoreLanguage;
/**
* Defines a language.
*/
interface LanguageInterface {
// [Snip]
/**
* Language written left to right.
* Possible value of $language->direction.
*/
const DIRECTION_LTR = 'ltr';
/**
* Language written right to left.
* Possible value of $language->direction.
*/
const DIRECTION_RTL = 'rtl';
/**
* Gets the text direction (left-to-right or
* right-to-left).
*
* @return string
* Either self::DIRECTION_LTR
* or self::DIRECTION_RTL.
*/
public function getDirection();
// [Snip]
}
/**
* Defines a language.
*/
interface LanguageInterface {
// [Snip]
/**
* Gets the text direction
* (left-to-right or right-to-left).
*
* @return string
* Either self::DIRECTION_LTR
* or self::DIRECTION_RTL.
*/
public function getDirection();
}
class Gibberish implements LanguageInterface {
// Required methods omitted for brevity.
public function getDirection() {
return 'outside-in';
}
}
/**
* Defines a language.
*/
interface LanguageInterface {
// [Snip]
/**
* Gets the text direction
* (left-to-right or right-to-left).
*
* @return string
* Either self::DIRECTION_LTR
* or self::DIRECTION_RTL.
*/
public function getDirection();
}
enum LanguageDirection {
LTR,
RTL,
}
trait LanguageInterface {
fn get_direction() -> LanguageDirection;
}
struct Gibberish {}
impl LanguageInterface for Gibberish {
fn get_direction() -> LanguageDirection {
"outside-in"
}
}
// Create an `enum` to classify a web event. Note how both
// names and type information together specify the variant:
// `PageLoad != PageUnload` and `KeyPress(char) != Paste(String)`.
// Each is different and independent.
enum WebEvent {
// An `enum` may either be `unit-like`,
PageLoad,
PageUnload,
// like tuple structs,
KeyPress(char),
Paste(String),
// or like structures.
Click { x: i64, y: i64 },
}
// Source https://doc.rust-lang.org/stable/rust-by-example/custom_types/enum.html
PHP
• No support out of the box
• SPL (Standard PHP Library) Types extension exists
• Careful: it's experimental
• Check your return values manually
Javascript
• 😅
• Handle the case where functions misbehave
• Typescript does support enums
NULL does not exist
Error: Call to a member function someFunction() on null
/**
* Loads an entity.
*
* @param mixed $id
* The id of the entity to load.
*
* @return static
* The entity object or NULL if there is no entity with the given ID.
*/
// Given we have < 9000 nodes.
// Throws: Error: Call to a member function label() on null
Node::load(9002)->label();
use std::fs::File;
use std::io::prelude::*;
fn main() {
let file = File::open("foo.txt");
let mut contents = String::new();
file.read_to_string(&mut contents);
println!("The contents of the file: {}", contents);
}
Error handling with the Result type
Result<T, E> is the type used for returning and
propagating errors.
It is an enum with the variants, Ok(T), representing
success and containing a value, and Err(E),
representing error and containing an error value.
enum Result<T, E> {
Ok(T),
Err(E),
}
// Source: https://doc.rust-lang.org/std/result/
use std::fs::File;
use std::io::prelude::*;
fn main() {
let file = File::open("foo.txt");
match file {
Ok(mut f) => {
let mut contents = String::new();
f.read_to_string(&mut contents).expect("Reading failed");
}
}
}
Javascript
Closures
A closure is the combination of a function and the lexical
environment within which that function was declared.
Closures
• Mozilla’s Developer Network (MDN) Web docs are awesome
• Let us borrow some examples
function init() {
var name = 'Mozilla'; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
console.log(name); // use variable declared in the parent function
}
displayName();
}
// Outputs: Mozilla
init();
// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
function makeFunc() {
var name = 'Mozilla';
function displayName() {
console.log(name);
}
return displayName;
}
var myFunc = makeFunc();
// Outputs: Mozilla
myFunc();
// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
function addFunction (x) {
return x + 5;
}
const addArrowFn = x => x + 5;
console.log(addFunction(2)); // 7
console.log(addArrowFn(2)); // 7
function makeAdder(x) {
return y => x + y;
}
const add6 = makeAdder(6);
const add9 = makeAdder(9);
console.log(add6(9)); // 14
console.log(add9(9)); // 18
Functional Programming
In computer science, functional programming is a 
programming paradigm that treats computation as
the evaluation of mathematical functions and avoids
changing-state and mutable data.
— Wikipedia, Functional_programming
const usdToEur = usd => usd * 0.88; // 27-06-2019.
const cart = [
{ label: 'Socks', currency: 'usd', price: 3.99 } ,
{ label: 'Shirt', currency: 'usd', price: 9.99 } ,
{ label: 'Shoes', currency: 'usd', price: 49.99 },
];
for (let i=0; i<cart.length; i++) {
cart[i].price = usdToEur(cart[i].price);
}
// Outputs:
// [ { label: 'Socks', currency: 'eur', price: 3.5112 },
// { label: 'Shirt', currency: 'eur', price: 8.7912 },
// { label: 'Shoes', currency: 'eur', price: 43.9912 } ]
console.dir(cart);
const usdToEur = usd => usd * 0.88; // 27-06-2019.
const cart = [
{ label: 'Socks', currency: 'usd', price: 3.99 } ,
{ label: 'Shirt', currency: 'usd', price: 9.99 } ,
{ label: 'Shoes', currency: 'usd', price: 49.99 },
];
const cartInEur = cart.map(item => ({
label: item.label,
currency: 'eur',
price: usdToEur(item.price),
}));
// Outputs:
// [ { label: 'Socks', currency: 'eur', price: 3.5112 },
// { label: 'Shirt', currency: 'eur', price: 8.7912 },
// { label: 'Shoes', currency: 'eur', price: 43.9912 } ]
console.dir(cartInEur);
function createCartExchanger(currency, rate) {
return item => ({
label: item.label,
currency: currency,
price: item.price * rate,
});
}
// Exchange rates on 27-06-2019.
const cartToEuro = createCartExchanger('eur', 0.88);
const cartToYen = createCartExchanger('yen', 107.87);
const cartInEur = cart.map(cartToEuro);
const cartInYen = cart.map(cartToYen);
// Outputs:
// [ { label: 'Socks', currency: 'yen', price: 430.40130000000005 },
// { label: 'Shirt', currency: 'yen', price: 1077.6213 },
// { label: 'Shoes', currency: 'yen', price: 5392.421300000001 } ]
console.dir(cartInYen);
function createCartExchanger(string $currency, float $rate) {
return function (array $item) use ($currency, $rate) {
return [
'label' => $item['label'],
'currency' => $currency,
'price' => $item['price'] * $rate,
];
};
}
$cartToEuro = createCartExchanger('eur', 0.88);
$cartInEur = array_map($cartToEuro, $cart);
// As of PHP 7.4.
function createCartExchanger(string $currency, float $rate) {
return fn($item) => [
'label' => $item['label'],
'currency' => $currency,
'price' => $item['price'] * $rate,
];
}
$cartToEuro = createCartExchanger('eur', 0.88);
$cartInEur = array_map($cartToEuro, $cart);
Perl
Schwartzian Transform
In computer programming, the Schwartzian
transform is a technique used to improve the
efficiency of sorting a list of items.
Schwartzian Transform
• Sorting based on a certain property
• Calculating that property is expensive
• e.g. sort orders based on total value
• Can work without intermediate variables
• It’s possible in PHP but horrible.
• A Javascript example is simpler
const unsorted = [2, 0, 5, 3, 1, 4];
let seen = [0, 0, 0, 0, 0, 0];
// Copy the array and sort it. Count the
// number of times each item is compared.
const sorted = unsorted.slice().sort(
(a, b) => {
seen[a]++;
seen[b]++;
return a - b;
}
);
console.log("NumbertTimes seen");
seen.forEach((times, number) => {
console.log(`${number}t${times}`);
});
Number
0
1
2
3
4
5
Times seen
3
3
5
4
3
4
// slowTransform: wait 1s and return x * 2.
const unsorted = [2, 0, 5, 3, 1, 4];
// Copy the array and sort it.
const sorted = unsorted.slice().sort(
(a, b) => {
// Access network, disk, calculate prime number or fibonacci.
return slowTransform(a) - slowTransform(b);
}
);
// [ 0, 1, 2, 3, 4, 5 ]
console.log(sorted);
// Takes about 22 seconds.
// slowTransform: wait 1s and return x * 2.
const unsorted = [2, 0, 5, 3, 1, 4];
// Copy the array, transform, then sort.
const sorted = unsorted.slice()
.map(slowTransform)
.sort(
(a, b) => {
return a - b;
}
);
// [ 0, 2, 4, 6, 8, 10 ]
console.log(sorted);
// Takes about 6 seconds.
// slowTransform: wait 1s and return x * 2.
const unsorted = [2, 0, 5, 3, 1, 4];
// Slice copies the array.
const sorted = unsorted.slice()
.map(x => [x, slowTransform(x)])
.sort(
(a, b) => {
return a[1] - b[1];
}
)
.map(x => x[0]);
// [ 0, 1, 2, 3, 4, 5 ]
console.log(sorted);
// Takes about 6 seconds.
Ruby Styleguide Wisdom
Be consistent and use common sense
Thank you! Questions?
Slides: tiny.cc/dc2019slides
Snippets: tiny.cc/dc2019code
Locate this session at the DrupalCon Amsterdam website:
https://drupal.kuoni-congress.info/2019/program/
Take the Survey!

https://www.surveymonkey.com/r/DrupalConAmsterdam
Join us for
contribution opportunities
Thursday, October 31, 2019
9:00-18:00
Room: Europe Foyer 2
Mentored
Contribution
First Time
Contributor Workshop
General
Contribution
#DrupalContributions
9:00-14:00
Room: Diamond Lounge
9:00-18:00
Room: Europe Foyer 2

More Related Content

What's hot

PHP MVC
PHP MVCPHP MVC
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
Leonardo Proietti
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 
Overlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh MyOverlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh My
Steve McMahon
 
Dependency Injection Smells
Dependency Injection SmellsDependency Injection Smells
Dependency Injection Smells
Matthias Noback
 
Javascript in Plone
Javascript in PloneJavascript in Plone
Javascript in Plone
Steve McMahon
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
Jonathan Wage
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Extending Twig
Extending TwigExtending Twig
Extending Twig
Gerry Vandermaesen
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
Rebecca Murphey
 
Drupal 8: Entities
Drupal 8: EntitiesDrupal 8: Entities
Drupal 8: Entities
drubb
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
Samuel ROZE
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
Bastian Feder
 
Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?
Yevhen Kotelnytskyi
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
Leonardo Proietti
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
Rebecca Murphey
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
Siarhei Barysiuk
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
Łukasz Chruściel
 
Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0
Yevhen Kotelnytskyi
 

What's hot (20)

PHP MVC
PHP MVCPHP MVC
PHP MVC
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 
Overlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh MyOverlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh My
 
Dependency Injection Smells
Dependency Injection SmellsDependency Injection Smells
Dependency Injection Smells
 
Javascript in Plone
Javascript in PloneJavascript in Plone
Javascript in Plone
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Extending Twig
Extending TwigExtending Twig
Extending Twig
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
 
Drupal 8: Entities
Drupal 8: EntitiesDrupal 8: Entities
Drupal 8: Entities
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Using Objects to Organize your jQuery Code
Using Objects to Organize your jQuery CodeUsing Objects to Organize your jQuery Code
Using Objects to Organize your jQuery Code
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
 
Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0
 

Similar to Multilingualism makes better programmers

Drupaljam xl 2019 presentation multilingualism makes better programmers
Drupaljam xl 2019 presentation   multilingualism makes better programmersDrupaljam xl 2019 presentation   multilingualism makes better programmers
Drupaljam xl 2019 presentation multilingualism makes better programmers
Alexander Varwijk
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
Hugo Hamon
 
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
James Titcumb
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
Joaquim Rocha
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
SWIFTotter Solutions
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
Divante
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
James Titcumb
 
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
James Titcumb
 
Hexagonal architecture in PHP
Hexagonal architecture in PHPHexagonal architecture in PHP
Hexagonal architecture in PHP
Paulo Victor Gomes
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
Doctrine and NoSQL
Doctrine and NoSQLDoctrine and NoSQL
Doctrine and NoSQL
Benjamin Eberlei
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
David Padbury
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
Richard Leland
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
Alive Kuo
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
Jose Manuel Pereira Garcia
 

Similar to Multilingualism makes better programmers (20)

Drupaljam xl 2019 presentation multilingualism makes better programmers
Drupaljam xl 2019 presentation   multilingualism makes better programmersDrupaljam xl 2019 presentation   multilingualism makes better programmers
Drupaljam xl 2019 presentation multilingualism makes better programmers
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
 
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
Kicking off with Zend Expressive and Doctrine ORM (Sunshine PHP 2017)
 
Hexagonal architecture in PHP
Hexagonal architecture in PHPHexagonal architecture in PHP
Hexagonal architecture in PHP
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
Doctrine and NoSQL
Doctrine and NoSQLDoctrine and NoSQL
Doctrine and NoSQL
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
Django at the Disco
Django at the DiscoDjango at the Disco
Django at the Disco
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 

Recently uploaded

Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
Tier1 app
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
NaapbooksPrivateLimi
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
KrzysztofKkol1
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 

Recently uploaded (20)

Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Visitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.appVisitor Management System in India- Vizman.app
Visitor Management System in India- Vizman.app
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
SOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBrokerSOCRadar Research Team: Latest Activities of IntelBroker
SOCRadar Research Team: Latest Activities of IntelBroker
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Designing for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web ServicesDesigning for Privacy in Amazon Web Services
Designing for Privacy in Amazon Web Services
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 

Multilingualism makes better programmers

  • 1. DrupalCon Amsterdam 2019 Multilingualism makes better programmers A look beyond PHP and JavaScript Photo by Émile Perron on Unsplash
  • 2. describe(‘Alexander Varwijk’) • Programming for 15+ years • 7 years of Drupal • Developer for Open Social • Love for sports, beer and pretty code
  • 3. • A look outside of our comfort zone • Not every example works in PHP/JS • Concepts/Thought process is still useful • Examples from Ruby, Java, Rust, Javascript, Perl About this talk
  • 4. What’s in a 
 (programming) language?
  • 5. Syntax The arrangement of words and phrases to create well-formed sentences in a language The structure of statements in a computer language “ How do I express what I want to do? ”
  • 6. (Standard) Library A standard library in computer programming Is the library made available across Implementations of a programming language. “ What can I use without installing something else? ”
  • 7. Ecosystem A collection of software projects, which are developed and co-evolve in the same environment. Can be organizational (a company), social (an open- source community), or technical (the Ruby ecosystem) “ What has already been built that I can use? ”
  • 8. “Ruby, Ruby, Ruby, Ruby” 
 — Kaiser Chiefs
  • 9. The Ruby Styleguide • A community driven effort to create standards. • Applicable beyond Ruby rubocop-hq/ruby-style-guide
  • 10. Keep functions short Avoid methods longer than 10 LOC (lines of code). Ideally, most methods will be shorter than 5 LOC. Empty lines do not contribute to the relevant LOC.
  • 11. Keep functions short • Give functions a single purpose • Reduces mental load • Makes it easier to put the code in presentations ;-) • Find the right balance
  • 12. function social_post_form_post_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Show the users picture for new posts. if ($form_state->getFormObject()->getEntity()->isNew()) { // Load current user. $account = User::load(Drupal::currentUser()->id()); // Load compact notification view mode of the attached profile. if ($account) { $storage = Drupal::entityTypeManager()->getStorage('profile'); $user_profile = $storage->loadByUser($account, 'profile'); if ($user_profile) { $content = Drupal::entityTypeManager()->getViewBuilder('profile') ->view($user_profile, 'compact_notification'); // Add to a new field, so twig can render it. $form['current_user_image'] = $content; } } } // [Snip] }
  • 13. function social_post_form_post_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Show the users picture for new posts. if ($form_state->getFormObject()->getEntity()->isNew()) { $user_image = social_post_get_current_user_image(); if ($user_image) { // Add to a new field, so twig can render it. $form['current_user_image'] = $user_image; } } // [Snip] }
  • 14. if as modifier Prefer modifier if / unless usage when you have a single-line body. Another good alternative is the usage of control flow && / ||.
  • 15. # good (doesn't work in PHP/JS) do_something if some_condition # another good option some_condition && do_something
  • 16. function p(x) { process.stdout.write(x); } function ret_true() { p("true "); return true; } function ret_false() { p("false "); return false; } ret_true() && p("&& print"); ret_true() || p("|| print"); ret_false() && p("&& print"); ret_false() || p("|| print"); true && print true false false || print function p($x) { echo $x; } function ret_true() { echo "true "; return true; } function ret_false() { echo "false "; return false; } ret_true() && p("&& print"); ret_true() || p("|| print"); ret_false() && p("&& print"); ret_false() || p("|| print"); PHP Javascript Output
  • 17. No method_missing Avoid using method_missing for metaprogramming because backtraces become messy, the behavior is not listed in #methods, and misspelled method calls might silently work, e.g. nukes.luanch_state = false
  • 18. Some of PHPs Magic Methods • __get, __set, __call • Used extensively by Drupal • Can make behaviour less predictable
  • 19. /** Implements the magic method for getting object properties. */ public function &__get($name) { // If this is an entity field, handle it accordingly. We first check whether // a field object has been already created. If not, we create one. if (isset($this->fields[$name][$this->activeLangcode])) { return $this->fields[$name][$this->activeLangcode]; } // Inline getFieldDefinition() to speed things up. if (!isset($this->fieldDefinitions)) { $this->getFieldDefinitions(); } if (isset($this->fieldDefinitions[$name])) { $return = $this->getTranslatedField($name, $this->activeLangcode); return $return; } // Else directly read/write plain values. That way, non-field entity // properties can always be accessed directly. if (!isset($this->values[$name])) { $this->values[$name] = NULL; } return $this->values[$name]; }
  • 20. Javascript Proxy • Emulates PHP’s magic methods • MDN Documentation • Could be a talk on its own • Doesn’t work in Internet Explorer
  • 21. Java
  • 22. Annotations In the Java computer programming language, an annotation is a form of syntactic metadata that can be added to Java source code. — Wikipedia, Java_annotation
  • 23. package com.example.examplemod; import net.minecraft.init.Blocks; import net.minecraftforge.fml.common.event.FMLInitializationEvent; public class ExampleMod { public static final String MODID = "examplemod"; public static final String VERSION = "1.0"; public void init(FMLInitializationEvent event) { // some example code System.out.println("DIRT BLOCK >> "+Blocks.dirt.getUnlocalizedName()); } }
  • 24. package com.example.examplemod; import net.minecraft.init.Blocks; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.FMLInitializationEvent; @Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION) public class ExampleMod { public static final String MODID = "examplemod"; public static final String VERSION = "1.0"; public void init(FMLInitializationEvent event) { // some example code System.out.println("DIRT BLOCK >> "+Blocks.dirt.getUnlocalizedName()); } }
  • 25. package com.example.examplemod; import net.minecraft.init.Blocks; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; @Mod(modid = ExampleMod.MODID, version = ExampleMod.VERSION) public class ExampleMod { public static final String MODID = "examplemod"; public static final String VERSION = "1.0"; @EventHandler public void init(FMLInitializationEvent event) { // some example code System.out.println("DIRT BLOCK >> "+Blocks.dirt.getUnlocalizedName()); } }
  • 26. namespace DrupalimagePluginFieldFieldWidget; /** * Plugin implementation of the 'image_image' widget. * * @FieldWidget( * id = "image_image", * label = @Translation("Image"), * field_types = { * "image" * } * ) */ class ImageWidget extends FileWidget { // Body omitted }
  • 27. PHP Annotations • Not built into the language • Uses the doctrine/annotations package • Uses PHP Reflection to read object/method/property comments • Proposal to move annotations into the PHP runtime (out of comments). See https://wiki.php.net/rfc/annotations_v2
  • 28. Javascript Annotations Decorators • Are used to modify the behaviour of a class or its properties • Are currently a stage 2 proposal • https://github.com/tc39/proposal-decorators • Implementation details changed a lot in March 2019 • Babel allows using these already, 
 as well as the legacy stage 1 syntax.
  • 29. class CounterWidget extends HTMLElement { } // Source: https://github.com/tc39/proposal-decorators
  • 30. import { @defineElement } from "./defineElement.mjs"; @defineElement('counter-widget') class CounterWidget extends HTMLElement { } // Source: https://github.com/tc39/proposal-decorators
  • 31. import { @tracked } from "./tracked.mjs"; import { @defineElement } from "./defineElement.mjs"; @defineElement('counter-widget') class CounterWidget extends HTMLElement { @tracked x = 0; connectedCallback() { this.render(); } render() { this.textContent = this.x.toString(); } } // Source: https://github.com/tc39/proposal-decorators
  • 32. import { @tracked } from "./tracked.mjs"; import { @bound } from "./bound.mjs"; import { @defineElement } from "./defineElement.mjs"; @defineElement('counter-widget') class CounterWidget extends HTMLElement { @tracked x = 0; @bound clicked() { this.x++; } connectedCallback() { this.render(); } render() { this.textContent = this.x.toString(); } } // Source: https://github.com/tc39/proposal-decorators
  • 33. import { @set } from "./set.mjs"; import { @tracked } from "./tracked.mjs"; import { @bound } from "./bound.mjs"; import { @defineElement } from "./defineElement.mjs"; @defineElement('counter-widget') class CounterWidget extends HTMLElement { @tracked x = 0; @set onclick = this.clicked; @bound clicked() { this.x++; } connectedCallback() { this.render(); } render() { this.textContent = this.x.toString(); } } // Source: https://github.com/tc39/proposal-decorators
  • 34. Rust
  • 35. Strongly Typed In a strongly typed language each data area will have a distinct type and each process will state its communication requirements in terms of these types. — Jackson, K. (1977). Design and Implementation of Programming Languages.
  • 36. Strongly Typed PHP 5.0 5.1 5.4 7.0 7.1 7.4 - Parameter type hints for Interface and Class names - Parameter type hints for arrays - Parameter type hints for callables - Parameter type hints for all primitive types, return type hints - Nullable types - Type hints for class properties
  • 37. /* An example of PHP 7.4's type hints. */ class TypeHintsExample { protected string $chant = 'PHP is improving!'; public function setChant(string $newChant) { $this->chant = $newChant; } public function chant() { echo $this->chant . PHP_EOL; } public function isAwesome() : bool { return true; } }
  • 38. /* An example of PHP 7.4's type hints. */ class TypeHintsExample { protected string $chant = 'PHP is improving!'; public function setChant(string $newChant) { $this->chant = $newChant; } public function chant() { echo $this->chant . PHP_EOL; } public function isAwesome() : bool { return true; } } $fan = new TypeHintsExample(); $fan->setChant('PHP is improving!'); // Outputs: "PHP is improving!n" $fan->chant(); $fan->setChant(9001); // Outputs: "9001n" $fan->chant();
  • 39. // Required to actually trigger type errors. declare(strict_types = 1); /* An example of PHP 7.4's type hints. */ class TypeHintsExample { protected string $chant = 'PHP is improving!'; public function setChant(string $newChant) { $this->chant = $newChant; } public function chant() { echo $this->chant . PHP_EOL; } public function isAwesome() : bool { return true; } } $fan = new TypeHintsExample(); $fan->setChant('PHP is improving!'); // Outputs: "PHP is improving!n" $fan->chant(); // Throws a TypeError $fan->setChant(9001); $fan->chant();
  • 40. Strongly Typed Drupal • Parameter type hints in coding standards: Issue #1158720 • Standardising array type hints (11 years and counting): Issue #318016 • Discussion about implementing types in existing code: Issue #3050720 • Highlights some backwards compatibility issues, 
 some solved in PHP 7.2 • Discussion on coding standard for new code: Issue #3060914
  • 41. Strongly Typed Javascript • 😅 • There’s Typescript
  • 42. Pattern Matching Patterns are a special syntax in Rust for matching against the structure of types, both complex and simple.
  • 43. let x = 1; match x { 1 => println!("one"), 2 => println!("two"), 3 => println!("three"), _ => println!("anything"), } // Source: https://doc.rust-lang.org/1.5.0/book/patterns.html
  • 44. // PHP switch ($x) { case 1: echo "one"; break; case 2: echo "two"; break; case 3: echo "three"; break; default: echo "anything"; } // Javascript switch (x) { case 1: console.log("one"); break; case 2: console.log("two"); break; case 3: console.log("three"); break; default: console.log("anything"); }
  • 45. match x { e @ 1 ... 5 => println!("got a range element {}", e), i => println!("{} was not in our range", i), }
  • 46. match x { e @ 1 ... 5 => println!("got a range element {}", e), i => println!("{} was not in our range", i), } enum OptionalInt { Value(i32), Missing, } let x = OptionalInt::Value(5); match x { OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"), OptionalInt::Value(..) => println!("Got an int!"), OptionalInt::Missing => println!("No such luck."), } // Source: https://doc.rust-lang.org/1.5.0/book/patterns.html
  • 47. Enum The enum keyword allows the creation of a type which may be one of a few different variants.
  • 48. namespace DrupalCoreLanguage; /** * Defines a language. */ interface LanguageInterface { // [Snip] /** * Language written left to right. * Possible value of $language->direction. */ const DIRECTION_LTR = 'ltr'; /** * Language written right to left. * Possible value of $language->direction. */ const DIRECTION_RTL = 'rtl'; /** * Gets the text direction (left-to-right or * right-to-left). * * @return string * Either self::DIRECTION_LTR * or self::DIRECTION_RTL. */ public function getDirection(); // [Snip] }
  • 49. /** * Defines a language. */ interface LanguageInterface { // [Snip] /** * Gets the text direction * (left-to-right or right-to-left). * * @return string * Either self::DIRECTION_LTR * or self::DIRECTION_RTL. */ public function getDirection(); }
  • 50. class Gibberish implements LanguageInterface { // Required methods omitted for brevity. public function getDirection() { return 'outside-in'; } } /** * Defines a language. */ interface LanguageInterface { // [Snip] /** * Gets the text direction * (left-to-right or right-to-left). * * @return string * Either self::DIRECTION_LTR * or self::DIRECTION_RTL. */ public function getDirection(); }
  • 51. enum LanguageDirection { LTR, RTL, } trait LanguageInterface { fn get_direction() -> LanguageDirection; } struct Gibberish {} impl LanguageInterface for Gibberish { fn get_direction() -> LanguageDirection { "outside-in" } }
  • 52.
  • 53. // Create an `enum` to classify a web event. Note how both // names and type information together specify the variant: // `PageLoad != PageUnload` and `KeyPress(char) != Paste(String)`. // Each is different and independent. enum WebEvent { // An `enum` may either be `unit-like`, PageLoad, PageUnload, // like tuple structs, KeyPress(char), Paste(String), // or like structures. Click { x: i64, y: i64 }, } // Source https://doc.rust-lang.org/stable/rust-by-example/custom_types/enum.html
  • 54. PHP • No support out of the box • SPL (Standard PHP Library) Types extension exists • Careful: it's experimental • Check your return values manually
  • 55. Javascript • 😅 • Handle the case where functions misbehave • Typescript does support enums
  • 56. NULL does not exist Error: Call to a member function someFunction() on null
  • 57. /** * Loads an entity. * * @param mixed $id * The id of the entity to load. * * @return static * The entity object or NULL if there is no entity with the given ID. */ // Given we have < 9000 nodes. // Throws: Error: Call to a member function label() on null Node::load(9002)->label();
  • 58. use std::fs::File; use std::io::prelude::*; fn main() { let file = File::open("foo.txt"); let mut contents = String::new(); file.read_to_string(&mut contents); println!("The contents of the file: {}", contents); }
  • 59.
  • 60. Error handling with the Result type Result<T, E> is the type used for returning and propagating errors. It is an enum with the variants, Ok(T), representing success and containing a value, and Err(E), representing error and containing an error value.
  • 61. enum Result<T, E> { Ok(T), Err(E), } // Source: https://doc.rust-lang.org/std/result/
  • 62. use std::fs::File; use std::io::prelude::*; fn main() { let file = File::open("foo.txt"); match file { Ok(mut f) => { let mut contents = String::new(); f.read_to_string(&mut contents).expect("Reading failed"); } } }
  • 63.
  • 65. Closures A closure is the combination of a function and the lexical environment within which that function was declared.
  • 66. Closures • Mozilla’s Developer Network (MDN) Web docs are awesome • Let us borrow some examples
  • 67. function init() { var name = 'Mozilla'; // name is a local variable created by init function displayName() { // displayName() is the inner function, a closure console.log(name); // use variable declared in the parent function } displayName(); } // Outputs: Mozilla init(); // Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
  • 68. function makeFunc() { var name = 'Mozilla'; function displayName() { console.log(name); } return displayName; } var myFunc = makeFunc(); // Outputs: Mozilla myFunc(); // Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
  • 69. function addFunction (x) { return x + 5; } const addArrowFn = x => x + 5; console.log(addFunction(2)); // 7 console.log(addArrowFn(2)); // 7
  • 70. function makeAdder(x) { return y => x + y; } const add6 = makeAdder(6); const add9 = makeAdder(9); console.log(add6(9)); // 14 console.log(add9(9)); // 18
  • 71. Functional Programming In computer science, functional programming is a  programming paradigm that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. — Wikipedia, Functional_programming
  • 72. const usdToEur = usd => usd * 0.88; // 27-06-2019. const cart = [ { label: 'Socks', currency: 'usd', price: 3.99 } , { label: 'Shirt', currency: 'usd', price: 9.99 } , { label: 'Shoes', currency: 'usd', price: 49.99 }, ]; for (let i=0; i<cart.length; i++) { cart[i].price = usdToEur(cart[i].price); } // Outputs: // [ { label: 'Socks', currency: 'eur', price: 3.5112 }, // { label: 'Shirt', currency: 'eur', price: 8.7912 }, // { label: 'Shoes', currency: 'eur', price: 43.9912 } ] console.dir(cart);
  • 73. const usdToEur = usd => usd * 0.88; // 27-06-2019. const cart = [ { label: 'Socks', currency: 'usd', price: 3.99 } , { label: 'Shirt', currency: 'usd', price: 9.99 } , { label: 'Shoes', currency: 'usd', price: 49.99 }, ]; const cartInEur = cart.map(item => ({ label: item.label, currency: 'eur', price: usdToEur(item.price), })); // Outputs: // [ { label: 'Socks', currency: 'eur', price: 3.5112 }, // { label: 'Shirt', currency: 'eur', price: 8.7912 }, // { label: 'Shoes', currency: 'eur', price: 43.9912 } ] console.dir(cartInEur);
  • 74. function createCartExchanger(currency, rate) { return item => ({ label: item.label, currency: currency, price: item.price * rate, }); } // Exchange rates on 27-06-2019. const cartToEuro = createCartExchanger('eur', 0.88); const cartToYen = createCartExchanger('yen', 107.87); const cartInEur = cart.map(cartToEuro); const cartInYen = cart.map(cartToYen); // Outputs: // [ { label: 'Socks', currency: 'yen', price: 430.40130000000005 }, // { label: 'Shirt', currency: 'yen', price: 1077.6213 }, // { label: 'Shoes', currency: 'yen', price: 5392.421300000001 } ] console.dir(cartInYen);
  • 75. function createCartExchanger(string $currency, float $rate) { return function (array $item) use ($currency, $rate) { return [ 'label' => $item['label'], 'currency' => $currency, 'price' => $item['price'] * $rate, ]; }; } $cartToEuro = createCartExchanger('eur', 0.88); $cartInEur = array_map($cartToEuro, $cart);
  • 76. // As of PHP 7.4. function createCartExchanger(string $currency, float $rate) { return fn($item) => [ 'label' => $item['label'], 'currency' => $currency, 'price' => $item['price'] * $rate, ]; } $cartToEuro = createCartExchanger('eur', 0.88); $cartInEur = array_map($cartToEuro, $cart);
  • 77. Perl
  • 78. Schwartzian Transform In computer programming, the Schwartzian transform is a technique used to improve the efficiency of sorting a list of items.
  • 79. Schwartzian Transform • Sorting based on a certain property • Calculating that property is expensive • e.g. sort orders based on total value • Can work without intermediate variables • It’s possible in PHP but horrible. • A Javascript example is simpler
  • 80. const unsorted = [2, 0, 5, 3, 1, 4]; let seen = [0, 0, 0, 0, 0, 0]; // Copy the array and sort it. Count the // number of times each item is compared. const sorted = unsorted.slice().sort( (a, b) => { seen[a]++; seen[b]++; return a - b; } ); console.log("NumbertTimes seen"); seen.forEach((times, number) => { console.log(`${number}t${times}`); }); Number 0 1 2 3 4 5 Times seen 3 3 5 4 3 4
  • 81. // slowTransform: wait 1s and return x * 2. const unsorted = [2, 0, 5, 3, 1, 4]; // Copy the array and sort it. const sorted = unsorted.slice().sort( (a, b) => { // Access network, disk, calculate prime number or fibonacci. return slowTransform(a) - slowTransform(b); } ); // [ 0, 1, 2, 3, 4, 5 ] console.log(sorted); // Takes about 22 seconds.
  • 82. // slowTransform: wait 1s and return x * 2. const unsorted = [2, 0, 5, 3, 1, 4]; // Copy the array, transform, then sort. const sorted = unsorted.slice() .map(slowTransform) .sort( (a, b) => { return a - b; } ); // [ 0, 2, 4, 6, 8, 10 ] console.log(sorted); // Takes about 6 seconds.
  • 83. // slowTransform: wait 1s and return x * 2. const unsorted = [2, 0, 5, 3, 1, 4]; // Slice copies the array. const sorted = unsorted.slice() .map(x => [x, slowTransform(x)]) .sort( (a, b) => { return a[1] - b[1]; } ) .map(x => x[0]); // [ 0, 1, 2, 3, 4, 5 ] console.log(sorted); // Takes about 6 seconds.
  • 85. Be consistent and use common sense
  • 86. Thank you! Questions? Slides: tiny.cc/dc2019slides Snippets: tiny.cc/dc2019code Locate this session at the DrupalCon Amsterdam website: https://drupal.kuoni-congress.info/2019/program/ Take the Survey!
 https://www.surveymonkey.com/r/DrupalConAmsterdam
  • 87. Join us for contribution opportunities Thursday, October 31, 2019 9:00-18:00 Room: Europe Foyer 2 Mentored Contribution First Time Contributor Workshop General Contribution #DrupalContributions 9:00-14:00 Room: Diamond Lounge 9:00-18:00 Room: Europe Foyer 2