SlideShare a Scribd company logo
Drupaljam:XL 2019
Photo by Émile Perron on Unsplash
Multilingualism makes
better programmers -
A look beyond PHP and
JavaScript
describe(‘Alexander Varwijk’)
• Programming for 15+ years
• 7 years of Drupal
• Developer for Open Social
• Love for sports, beer and pretty code
About this talk
• 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
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
(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?
“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
• Reduce 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;
}
function nl() { p(“n"); }
ret_true() && p("&& print"); nl();
ret_true() || p("|| print"); nl();
ret_false() && p("&& print"); nl();
ret_false() || p("|| print"); nl();
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;
}
function nl() { echo "n"; }
ret_true() && p("&& print"); nl();
ret_true() || p("|| print"); nl();
ret_false() && p("&& print"); nl();
ret_false() || p("|| print"); nl();
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.launch_state = false.
/** 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];
}
@todo: A lot of code still uses non-fields (e.g. $entity->content in view
builders) by reference. Clean that up.
Javascript Proxy
• Emulates PHP’s magic methods
• MDN Documentation
• Could be a talk on its own
• Doesn’t work in Internet Explorer
Photo by Alex on Unsplash
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.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
• Have changed drastically (March 2019) 

since I last presented on the subject
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
Photo by Jimmy Ofisia on Unsplash
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 - Parameter type hints for Interface and Class names
• 5.1 - Parameter type hints for arrays
• 5.4 - Parameter type hints for callables
• 7.0 - Parameter type hints for all primitive types, return type hints
• 7.1 - Nullable types
• 7.4 - 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 {
/**
* 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 {
/**
* Gets the text direction (left-to-right or
* right-to-left).
*
* @return string
* Either self::DIRECTION_LTR
* or self::DIRECTION_RTL.
*/
public function getDirection();
}
// 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
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);
}
Drupaljam xl 2019 presentation   multilingualism makes better programmers
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");
}
}
}
Drupaljam xl 2019 presentation   multilingualism makes better programmers
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);
Photo by Jimmy Ofisia on Unsplash
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, we’ll use Javascript
const unsorted = [2, 0, 5, 3, 1, 4];
let seen = [0, 0, 0, 0, 0, 0];
// Slice copies the array.
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 Times seen
0 3
1 3
2 5
3 4
4 3
5 4
// slowTransform: wait 1s and return x * 2.
const unsorted = [2, 0, 5, 3, 1, 4];
// Slice copies the array.
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];
// Slice copies the array.
const sorted = unsorted.slice()
.map(slowTransform)
.sort(
(a, b) => {
// Access network, disk, calculate prime number or fibonacci.
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) => {
// Access network, disk, calculate prime number or fibonacci.
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?
Let me know what you thought:
http://tiny.cc/dj2019feedback
Slides: http://tiny.cc/dj2019slides
Snippets: http://tiny.cc/dj2019code

More Related Content

PPT
Class 7 - PHP Object Oriented Programming
PPT
Class 3 - PHP Functions
PPT
Class 2 - Introduction to PHP
PDF
STC 2016 Programming Language Storytime
PDF
A Gentle Introduction To Object Oriented Php
PDF
Introduction to web programming with JavaScript
ZIP
Object Oriented PHP5
PPT
Php Oop
Class 7 - PHP Object Oriented Programming
Class 3 - PHP Functions
Class 2 - Introduction to PHP
STC 2016 Programming Language Storytime
A Gentle Introduction To Object Oriented Php
Introduction to web programming with JavaScript
Object Oriented PHP5
Php Oop

What's hot (20)

PPTX
TEMPLATES IN JAVA
PPT
Oops in PHP
PDF
Choose'10: Ralf Laemmel - Dealing Confortably with the Confusion of Tongues
PPTX
Oop in-php
PPTX
JavaScript Literacy
PDF
OOP in PHP
PDF
Php Tutorials for Beginners
PPTX
Domain-Specific Languages
PPT
Class and Objects in PHP
PPTX
Groovy Programming Language
PPT
Javascript
PDF
Practical Models in Practice
PDF
EmberConf 2021 - Crossfile Codemodding with Joshua Lawrence
PDF
Object Oriented Programming with PHP 5 - More OOP
PDF
Design attern in php
PPTX
Modelling and Programming: Isn&rsquo;t it all the same?
PPTX
Php basics
PPTX
Class 8 - Database Programming
ODP
PHP Web Programming
TEMPLATES IN JAVA
Oops in PHP
Choose'10: Ralf Laemmel - Dealing Confortably with the Confusion of Tongues
Oop in-php
JavaScript Literacy
OOP in PHP
Php Tutorials for Beginners
Domain-Specific Languages
Class and Objects in PHP
Groovy Programming Language
Javascript
Practical Models in Practice
EmberConf 2021 - Crossfile Codemodding with Joshua Lawrence
Object Oriented Programming with PHP 5 - More OOP
Design attern in php
Modelling and Programming: Isn&rsquo;t it all the same?
Php basics
Class 8 - Database Programming
PHP Web Programming
Ad

Similar to Drupaljam xl 2019 presentation multilingualism makes better programmers (20)

PDF
Multilingualism makes better programmers
PDF
PHP 8: Process & Fixing Insanity
PPT
PPT
Accessing loosely structured data from F# and C#
PDF
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
PPTX
PHP in one presentation
PDF
WebCamp: Developer Day: DDD in PHP on example of Symfony - Олег Зинченко
PDF
Supercharging WordPress Development in 2018
PDF
Dependency injection in Drupal 8
PPT
Go OO! - Real-life Design Patterns in PHP 5
PDF
Objects, Testing, and Responsibility
PDF
Building Custom PHP Extensions
PDF
Having Fun with Play
PDF
lab4_php
PDF
lab4_php
PPTX
PHP: GraphQL consistency through code generation
KEY
PDF
Groovy On Trading Desk (2010)
PDF
PHP: 4 Design Patterns to Make Better Code
PPT
Php Reusing Code And Writing Functions
Multilingualism makes better programmers
PHP 8: Process & Fixing Insanity
Accessing loosely structured data from F# and C#
Kicking off with Zend Expressive and Doctrine ORM (PHP Srbija 2017)
PHP in one presentation
WebCamp: Developer Day: DDD in PHP on example of Symfony - Олег Зинченко
Supercharging WordPress Development in 2018
Dependency injection in Drupal 8
Go OO! - Real-life Design Patterns in PHP 5
Objects, Testing, and Responsibility
Building Custom PHP Extensions
Having Fun with Play
lab4_php
lab4_php
PHP: GraphQL consistency through code generation
Groovy On Trading Desk (2010)
PHP: 4 Design Patterns to Make Better Code
Php Reusing Code And Writing Functions
Ad

Recently uploaded (20)

PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Complete Guide to Website Development in Malaysia for SMEs
PDF
medical staffing services at VALiNTRY
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PPTX
history of c programming in notes for students .pptx
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Nekopoi APK 2025 free lastest update
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
Patient Appointment Booking in Odoo with online payment
PPTX
Computer Software and OS of computer science of grade 11.pptx
PPTX
Transform Your Business with a Software ERP System
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PPTX
Monitoring Stack: Grafana, Loki & Promtail
DOCX
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Complete Guide to Website Development in Malaysia for SMEs
medical staffing services at VALiNTRY
Operating system designcfffgfgggggggvggggggggg
Advanced SystemCare Ultimate Crack + Portable (2025)
history of c programming in notes for students .pptx
Odoo Companies in India – Driving Business Transformation.pdf
Nekopoi APK 2025 free lastest update
wealthsignaloriginal-com-DS-text-... (1).pdf
Navsoft: AI-Powered Business Solutions & Custom Software Development
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Patient Appointment Booking in Odoo with online payment
Computer Software and OS of computer science of grade 11.pptx
Transform Your Business with a Software ERP System
Why Generative AI is the Future of Content, Code & Creativity?
Monitoring Stack: Grafana, Loki & Promtail
Greta — No-Code AI for Building Full-Stack Web & Mobile Apps

Drupaljam xl 2019 presentation multilingualism makes better programmers

  • 1. Drupaljam:XL 2019 Photo by Émile Perron on Unsplash Multilingualism makes better programmers - A look beyond PHP and JavaScript
  • 2. describe(‘Alexander Varwijk’) • Programming for 15+ years • 7 years of Drupal • Developer for Open Social • Love for sports, beer and pretty code
  • 3. About this talk • 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
  • 5. Syntax The arrangement of words and phrases to create well-formed sentences in a language The structure of statements in a computer language
  • 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. “Ruby, Ruby, Ruby, Ruby” 
— Kaiser Chiefs
  • 8. The Ruby Styleguide A community driven effort to create standards Applicable beyond Ruby rubocop-hq/ruby-style-guide
  • 9. 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.
  • 10. Keep functions short • Give functions a single purpose • Reduce mental load • Makes it easier to put the code in presentations ;-) • Find the right balance
  • 11. 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] }
  • 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()) { $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] }
  • 13. if as modifier Prefer modifier if / unless usage when you have a single-line body. Another good alternative is the usage of control flow && / ||.
  • 14. # good (doesn't work in PHP/JS) do_something if some_condition # another good option some_condition && do_something
  • 15. function p(x) { process.stdout.write(x); } function ret_true() { p("true "); return true; } function ret_false() { p("false "); return false; } function nl() { p(“n"); } ret_true() && p("&& print"); nl(); ret_true() || p("|| print"); nl(); ret_false() && p("&& print"); nl(); ret_false() || p("|| print"); nl(); 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; } function nl() { echo "n"; } ret_true() && p("&& print"); nl(); ret_true() || p("|| print"); nl(); ret_false() && p("&& print"); nl(); ret_false() || p("|| print"); nl(); PHP Javascript Output
  • 16. 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.launch_state = false.
  • 17. /** 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]; }
  • 18. @todo: A lot of code still uses non-fields (e.g. $entity->content in view builders) by reference. Clean that up.
  • 19. Javascript Proxy • Emulates PHP’s magic methods • MDN Documentation • Could be a talk on its own • Doesn’t work in Internet Explorer
  • 20. Photo by Alex on Unsplash Java
  • 21. 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
  • 22. 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()); } }
  • 23. 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 }
  • 24. 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
  • 25. 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 • Have changed drastically (March 2019) 
 since I last presented on the subject
  • 26. 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
  • 28. 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.
  • 29. Strongly Typed PHP • 5.0 - Parameter type hints for Interface and Class names • 5.1 - Parameter type hints for arrays • 5.4 - Parameter type hints for callables • 7.0 - Parameter type hints for all primitive types, return type hints • 7.1 - Nullable types • 7.4 - Type hints for class properties
  • 30. /* 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; } }
  • 31. /* 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();
  • 32. // 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();
  • 33. 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
  • 35. Pattern Matching Patterns are a special syntax in Rust for matching against the structure of types, both complex and simple.
  • 36. 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
  • 37. // 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"); }
  • 38. match x { e @ 1 ... 5 => println!("got a range element {}", e), i => println!("{} was not in our range", i), }
  • 39. 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
  • 40. Enum The enum keyword allows the creation of a type which may be one of a few different variants.
  • 41. 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] }
  • 42. /** * Defines a language. */ interface LanguageInterface { /** * Gets the text direction (left-to-right or * right-to-left). * * @return string * Either self::DIRECTION_LTR * or self::DIRECTION_RTL. */ public function getDirection(); }
  • 43. class Gibberish implements LanguageInterface { // Required methods omitted for brevity. public function getDirection() { return 'outside-in'; } } /** * Defines a language. */ interface LanguageInterface { /** * Gets the text direction (left-to-right or * right-to-left). * * @return string * Either self::DIRECTION_LTR * or self::DIRECTION_RTL. */ public function getDirection(); }
  • 44. // 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
  • 45. NULL does not exist Error: Call to a member function someFunction() on null
  • 46. /** * 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();
  • 47. 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); }
  • 49. 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.
  • 50. enum Result<T, E> { Ok(T), Err(E), } // Source: https://doc.rust-lang.org/std/result/
  • 51. 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"); } } }
  • 54. Closures A closure is the combination of a function and the lexical environment within which that function was declared.
  • 55. Closures • Mozilla’s Developer Network (MDN) Web docs are awesome • Let us borrow some examples
  • 56. 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
  • 57. 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
  • 58. function addFunction (x) { return x + 5; } const addArrowFn = x => x + 5; console.log(addFunction(2)); // 7 console.log(addArrowFn(2)); // 7
  • 59. 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
  • 60. 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
  • 61. 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);
  • 62. 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);
  • 63. 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);
  • 64. 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);
  • 65. // 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);
  • 67. Schwartzian Transform In computer programming, the Schwartzian transform is a technique used to improve the efficiency of sorting a list of items.
  • 68. 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, we’ll use Javascript
  • 69. const unsorted = [2, 0, 5, 3, 1, 4]; let seen = [0, 0, 0, 0, 0, 0]; // Slice copies the array. 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 Times seen 0 3 1 3 2 5 3 4 4 3 5 4
  • 70. // slowTransform: wait 1s and return x * 2. const unsorted = [2, 0, 5, 3, 1, 4]; // Slice copies the array. 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.
  • 71. // slowTransform: wait 1s and return x * 2. const unsorted = [2, 0, 5, 3, 1, 4]; // Slice copies the array. const sorted = unsorted.slice() .map(slowTransform) .sort( (a, b) => { // Access network, disk, calculate prime number or fibonacci. return a - b; } ); // [ 0, 2, 4, 6, 8, 10 ] console.log(sorted); // Takes about 6 seconds.
  • 72. // 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) => { // Access network, disk, calculate prime number or fibonacci. return a[1] - b[1]; } ) .map(x => x[0]); // [ 0, 1, 2, 3, 4, 5 ] console.log(sorted); // Takes about 6 seconds.
  • 74. Be consistent and use common sense
  • 75. Thank you! Questions? Let me know what you thought: http://tiny.cc/dj2019feedback Slides: http://tiny.cc/dj2019slides Snippets: http://tiny.cc/dj2019code