https://slides.com/davesters/remove-magic-functional-programming
+10 MR
let results = accounts
.where({
first_name: 'Bob',
last_name: 'Sacameno',
deleted: NULL,
ref_id: 2
})
.not().andWhere({ other_id: 3 })
.orderByDesc('created')
.limit(10);
let results = db.query("SELECT * FROM accounts WHERE
first_name = 'bob' AND last_name = 'Sacameno' AND
deleted IS NULL AND ref_id = 2 AND other_id <> 3
ORDER BY created DESC LIMIT 10");
$container->bind('iFooContext', '\Foo\Context');
$container->bind('iBarController', '\Controllers\BarController');
…
public class Account {
public int id;
public string name;
public string email;
}
var account = Mapper.Map<Account>(databaseAccount);
CreateMap<Account, DatabaseAccount>()
.ForMember(m => m.name, a => a.name = a.first_name + " " + a.last_name)
.ForMember(m => m.email, a => a.email.ToLower);
public class Account {
public int id;
public string name;
public string email;
public static function Map(DatabaseAccount account) {
var a = new Account();
a.id = account.id;
a.name = account.first_name + " " + account.last_name;
a.email = account.email.ToLower();
return account;
}
}
var account = Account.Map(databaseAccount);
You are responsible for ALL the code in your project
"A style of building computer programs, that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data..."
- Wikipedia
+50 MR
First-class functions
Pure functions
Immutable Data
Plenty more...
let add = function(a, b) {
return a + b;
};
function getSomeAsyncData('foo', function(data) {
// do something with async data here.
});
function add(a, b) {
return a + b;
}
let sum = add(2, 3);
let sum = 5;
let numbers = [1, 2, 3, 4, 5];
for (x = 0; x < numbers.length; x++) {
numbers[x] = numbers[x] + 5;
}
An immutable object is an object whose state cannot be modified after it is created.
let numbers = [1, 2, 3, 4, 5];
for (x = 0; x < numbers.length; x++) {
numbers[x] = numbers[x] + 5;
}
let biggerNumbers = numbers.map(function(num) {
return num + 5;
});
Functional Way
let biggerNumbers = numbers.map(add5);
function add5(a) {
return a + 5;
}
function add5(a) {
return add(a, 5);
}
let num = add5(7); // 12
function add5(a) {
return a + 5;
}
function add(a, b) {
return a + b;
}
require 'vendor/autoload.php';
require 'src/TodoApp.php';
require 'src/Mustache.php';
$handlers = [];
$mustache = Mustache::Render(new Mustache_Engine(), function($tpl) {
return file_get_contents(__DIR__ . "/views/$tpl.mustache");
});
$klein = new \Klein\Klein();
$todoApp = new TodoApp($klein, $mustache, $handlers);
$todoApp->setRoutes();
$todoApp->start();
class TodoApp {
private $app, $handlers, $mustache;
public function __construct(Klein $app, $mustache, $handlers) {
$this->app = $app;
$this->handlers = $handlers;
$this->mustache = $mustache;
}
public function start() {
$this->app->dispatch();
}
public function setRoutes() { ... }
private function handle($view, $handlers) { ... }
}
public function setRoutes() {
$h = $this->handlers;
$this->app->respond('/', $this->handle('index', $h['index']));
}
private function handle($view, array $handlers) {
// Loop over $handlers array and build view model
$this->render($this->mustache($view, $model));
}
class IndexHandler {
public static function Handle($dataSource) {
return function($model, $params) {
$todos = $dataSource('SELECT id, todo, completed
FROM todos WHERE deleted IS NULL ORDER BY created');
return [
'title' => 'Todo App',
'todos' => $todos,
'count' => count($todos)
];
};
}
}
$handlers = [
'index' => [ Handlers\IndexHandler::Handle($dataSource) ]
];
$handlers = [
'index' => [ Handlers\IndexHandler::Handle($dataSource) ],
'add' => [ Handlers\AddTodoHandler::Handle($dataSource) ],
'update' => [ Handlers\UpdateTodoHandler::Handle($dataSource) ]
];
class IndexQuery {
public static function Query($dataSource) {
return function($model, $params) {
$todos = $dataSource('SELECT id, todo, completed
FROM todos WHERE deleted IS NULL ORDER BY created');
return [ 'todos' => $todos ];
};
}
}
class IndexHandler {
public static function Handle() {
return function($model, $params) {
return [
'title' => 'Todo App',
'todos' => $model['todos']
'count' => count($model['todos']
];
};
}
}
$handlers = [
'index' => [
Queries\IndexQuery::Query($dataSource),
Handlers\IndexHandler::Handle()
],
...
];
Can I change my problem around so I don’t need it?
Sample App:
https://github.com/davesters/functional-todo-example
"8 Lines of Code" Keynote:
http://www.infoq.com/presentations/8-lines-code-refactoring
Contact:
Twitter - @davesters
Github - davesters
Website - http://www.lovesmesomecode.com