SlideShare a Scribd company logo
1 of 87
Download to read offline
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

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.5Leonardo 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 MySteve McMahon
 
Dependency Injection Smells
Dependency Injection SmellsDependency Injection Smells
Dependency Injection SmellsMatthias Noback
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan 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
 
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 DevsRebecca Murphey
 
Drupal 8: Entities
Drupal 8: EntitiesDrupal 8: Entities
Drupal 8: Entitiesdrubb
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form componentSamuel ROZE
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownpartsBastian 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 clienteLeonardo 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 CodeRebecca Murphey
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesSiarhei 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.0Yevhen 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 programmersAlexander 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 Symfony2Hugo 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 DjangoJoaquim 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 CodeSWIFTotter 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 scenariosDivante
 
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
 
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 GuyDavid Padbury
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVCAlive 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

Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 

Recently uploaded (20)

Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 

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