Top Banner
Simple by Design: Clojure @stuarthalloway [email protected] Copyright Cognitect, Inc. This presentation is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License. See http://creativecommons.org/licenses/by-nc-sa/3.0/us/
85
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Clojure: Simple By Design

Simple by Design: Clojure

@stuarthalloway [email protected]

Copyright Cognitect, Inc. This presentation is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.

See http://creativecommons.org/licenses/by-nc-sa/3.0/us/

Page 2: Clojure: Simple By Design

Thoughtworks Radar

Oct 2012: Adopt Clojure

http://www.thoughtworks.com/radar

Page 3: Clojure: Simple By Design

Redmonk Top 20

http://redmonk.com/sogrady/2014/06/13/language-rankings-6-14/

Clojure

Page 4: Clojure: Simple By Design

Design !

specification of an artifact using components to meet goals subject to constraints

Page 5: Clojure: Simple By Design

Simple !

not compound

Page 6: Clojure: Simple By Design

Valuable But Not Simple

convenience

beginner-friendliness

ease

familiarity

smaller size

lesser count

Page 7: Clojure: Simple By Design

Simple !

not compound

Page 8: Clojure: Simple By Design

Agenda

examples of simplicity in Clojure

benefits of simplicity in Clojure

producing Clojure

Page 9: Clojure: Simple By Design

Examples of Simplicity

syntax

protocols

values and references

Page 10: Clojure: Simple By Design

Examples of Simplicity

syntax

protocols

values and references

Page 11: Clojure: Simple By Design

"Hello World"

Page 12: Clojure: Simple By Design

"Hello World"

that is the program

Page 13: Clojure: Simple By Design

Everything is Data

Page 14: Clojure: Simple By Design

type examples

string "foo"

character \f

integer 42, 42N

floating point 3.14, 3.14M

boolean true

nil nil

symbol foo, +

keyword :foo, ::foo

Page 15: Clojure: Simple By Design

type properties examples

list sequential (1 2 3)

vector sequential and random access [1 2 3]

map associative {:a 100! :b 90}

set membership #{:a :b}

Page 16: Clojure: Simple By Design

Function Call

(+ 2 2)

fn call argssemantics:

structure: symbol longs

list

Page 17: Clojure: Simple By Design

Function Definition

(defn greet! "Returns a friendly greeting"! [your-name]! (str "Hello, " your-name))

define a fn fn namedocstring

arguments

fn body

Page 18: Clojure: Simple By Design

…Still Just Data

(defn greet! "Returns a friendly greeting"! [your-name]! (str "Hello, " your-name))

symbol symbolstring

vector

list

Page 19: Clojure: Simple By Design

Complexities Avoided

lots of syntax to learn

ordering dependencies

operator precedence

code over data bias

tedious metaprogramming

Page 20: Clojure: Simple By Design

Examples of Simplicity

syntax

protocols

values and references

Page 21: Clojure: Simple By Design

Reversible

Jacket Belt String

Page 22: Clojure: Simple By Design

Reversible

Jacket Belt String

interface

implementation

Page 23: Clojure: Simple By Design

Reversible

Jacket Belt String

interface

implementationextension

Page 24: Clojure: Simple By Design

(defprotocol Reversible! (reverse [_]))!!!!(defrecord ReversibleTie [a b])!!!!(extend-protocol Reversible! ReversibleTie! (reverse [tie] (->ReversibleTie (:b tie) (:a tie)))! String! (reverse [s] (-> s! StringBuilder.! .reverse! .toString)))

interface

implementation

extension

Page 25: Clojure: Simple By Design

Complexities Avoided

adapter pattern

wrapper pattern

translator pattern

monkey patching

StringUtils

note that these are all combinatorial

Page 26: Clojure: Simple By Design

Examples of Simplicity

syntax

protocols

values and references

Page 27: Clojure: Simple By Design

Me 182

Page 28: Clojure: Simple By Design

Me 182

nachos

Page 29: Clojure: Simple By Design

Me 182

nachos

184

Page 30: Clojure: Simple By Design

Watch OO Flounder

Me 182

nachos

184

instance?

field?

method?

??

Page 31: Clojure: Simple By Design

If you have more things than names, your design

is broken.

Page 32: Clojure: Simple By Design

Clojure’s Simplicity

Me 182

nachos

184

reference

value

pure function

new valuesuccession function

Page 33: Clojure: Simple By Design

Values and References

(defprotocol Nachos! (yum [_] "eat some nachos"))!!(defrecord Person [name lbs]! Nachos! (yum [person]! (update-in person [:lbs] + 2)))!!(def me (atom (->Person "Stu" 182)))!!(def me-before @me)!!(swap! me yum)!!(def me-after @me)

Page 34: Clojure: Simple By Design

Values and References

(defprotocol Nachos! (yum [_] "eat some nachos"))!!(defrecord Person [name lbs]! Nachos! (yum [person]! (update-in person [:lbs] + 2)))!!(def me (atom (->Person "Stu" 182)))!!(def me-before @me)!!(swap! me yum)!!(def me-after @me)

functional

Page 35: Clojure: Simple By Design

Values and References

(defprotocol Nachos! (yum [_] "eat some nachos"))!!(defrecord Person [name lbs]! Nachos! (yum [person]! (update-in person [:lbs] + 2)))!!(def me (atom (->Person "Stu" 182)))!!(def me-before @me)!!(swap! me yum)!!(def me-after @me)

update semantics

Page 36: Clojure: Simple By Design

Values and References

(defprotocol Nachos! (yum [_] "eat some nachos"))!!(defrecord Person [name lbs]! Nachos! (yum [person]! (update-in person [:lbs] + 2)))!!(def me (atom (->Person "Stu" 182)))!!(def me-before @me)!!(swap! me yum)!!(def me-after @me)

multiple point-in-time

values

Page 37: Clojure: Simple By Design

Complexities Avoided incidental complexity temporal reasoning

single-threading

locking

defensive copying

setter methods

String vs. StringBuilder vs. StringBuffer

note (again!) that these are all combinatorial

Page 38: Clojure: Simple By Design

Benefits of Clojure

concision

generality

robustness

agility

Page 39: Clojure: Simple By Design

Benefits of Clojure

concision

generality

robustness

agility

Page 40: Clojure: Simple By Design

StringUtils indexOfAny

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html

Page 41: Clojure: Simple By Design

StringUtils.indexOfAny(null, *) = -1!StringUtils.indexOfAny("", *) = -1!StringUtils.indexOfAny(*, null) = -1!StringUtils.indexOfAny(*, []) = -1!StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0!StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3!StringUtils.indexOfAny("aba", ['z']) = -1

indexOfAny Spec

Page 42: Clojure: Simple By Design

// From Apache Commons Lang, http://commons.apache.org/lang/!public static int indexOfAny(String str, char[] searchChars) {! if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) {! return -1;! }! for (int i = 0; i < str.length(); i++) {! char ch = str.charAt(i);! for (int j = 0; j < searchChars.length; j++) {! if (searchChars[j] == ch) {! return i;! }! }! }! return -1;!}

indexOfAny Impl

Page 43: Clojure: Simple By Design

public static int indexOfAny(String str, char[] searchChars) {! when (searchChars)! for (int i = 0; i < str.length(); i++) {! char ch = str.charAt(i);! for (int j = 0; j < searchChars.length; j++) {! if (searchChars[j] == ch) {! return i;! }! }! }! }!}

- Corner Cases

Page 44: Clojure: Simple By Design

indexOfAny(str, searchChars) {! when (searchChars)! for (i = 0; i < str.length(); i++) {! ch = str.charAt(i);! for (j = 0; j < searchChars.length; j++) {! if (searchChars[j] == ch) {! return i;! }! }! }! }!}

- Type Decls

Page 45: Clojure: Simple By Design

indexOfAny(str, searchChars) {! when (searchChars)! for (i = 0; i < str.length(); i++) {! ch = str.charAt(i); ! when searchChars(ch) i;! }! }!}

+ When Clause

Page 46: Clojure: Simple By Design

indexOfAny(str, searchChars) {! when (searchChars)! for ([i, ch] in indexed(str)) {! when searchChars(ch) i;! }! }!}

+ Comprehension

Page 47: Clojure: Simple By Design

(defn index-filter [pred coll]! (when pred ! (for [[idx elt] (indexed coll) :when (pred elt)] idx)))

Lispify

Page 48: Clojure: Simple By Design

Benefits of Clojure

concision

generality

robustness

agility

Page 49: Clojure: Simple By Design

imperative functional

searches strings searches any sequence

matches characters matches any predicate

returns first match returns lazy seq of all matches

Page 50: Clojure: Simple By Design

; idxs of heads in stream of coin flips!(index-filter #{:h} [:t :t :h :t :h :t :t :t :h :h]) !-> (2 4 8 9)!!; Fibonaccis pass 1000 at n=17!(first ! (index-filter #(> % 1000) (fibo)))!-> 17

+ Generality

Page 51: Clojure: Simple By Design

Clojure programs can have fewer

lines of code than OO programs have files

Page 52: Clojure: Simple By Design

Benefits of Clojure

concision

generality

robustness

agility

Page 53: Clojure: Simple By Design

imperative functional

functions 1 1

classes 1 0

internal exit points 2 0

variables 3 0

branches 4 0

boolean ops 1 0

function calls* 6 3

total 18 4

Page 54: Clojure: Simple By Design

Benefits of Clojure

concision

generality

robustness

agility

Page 55: Clojure: Simple By Design

Plain Immutable Collection Objects

(PICOs)

Page 56: Clojure: Simple By Design

PICOS Everywhere

collections

directories

files

XML

JSON

result sets

web requests

web responses

sessions

configuration

metrics

logs

Page 57: Clojure: Simple By Design

Consuming JSON

http://developer.rottentomatoes.com/docs/read/json/v10/Box_Office_Movies

What actors are in more than one movie currently topping the box office charts?

Page 58: Clojure: Simple By Design

Consuming JSON

http://developer.rottentomatoes.com/docs/read/json/v10/Box_Office_Movies

find the JSON input!download it!parse json!walk the movies!accumulating cast!extract actor name!get frequencies!sort by highest frequency

Page 59: Clojure: Simple By Design

Consuming JSON

http://developer.rottentomatoes.com/docs/read/json/v10/Box_Office_Movies

(->> box-office-uri! slurp! json/read-json! :movies! (mapcat :abridged_cast)! (map :name)! frequencies! (sort-by (comp - second)))

Page 60: Clojure: Simple By Design

Consuming JSON

http://developer.rottentomatoes.com/docs/read/json/v10/Box_Office_Movies

["Shiloh Fernandez" 2] !["Ray Liotta" 2] !["Isla Fisher" 2] !["Bradley Cooper" 2] !["Dwayne \"The Rock\" Johnson" 2] !["Morgan Freeman" 2] !["Michael Shannon" 2] !["Joel Edgerton" 2] !["Susan Sarandon" 2] !["Leonardo DiCaprio" 2]

Page 61: Clojure: Simple By Design

PICOs for Big Data

(defn my-data-2 [] (->> (pig/load-tsv "input.tsv") (pig/map (fn [[a b c]] {:sum (+ (Integer/valueOf a) (Integer/valueOf b)) :name c})) (pig/filter (fn [{:keys [sum]}] (< sum 5))))) !=> (pig/dump (my-data-2)) [{:sum 3, :name "foo"}]

https://github.com/Netflix/PigPen

Page 62: Clojure: Simple By Design

Me 182

nachos

184

reference

value

pure function

new value

succession function

Page 63: Clojure: Simple By Design

Me t-1

transact

t-2

connection

db value

pure function

new db value

ACID

Page 64: Clojure: Simple By Design

ACID data of record

persistent data structures: “scm for business data”

distributed, componentized, read scalable & elastic

information and logic as PICOs in any peer process

Page 65: Clojure: Simple By Design

Connection conn = !connect("datomic:ddb://us-east-1/mb/mbrainz");!!!Database db = conn.db();!!!Set results = q(..., db);!!!Set crossDbResults = q(..., db1, db2);!!!Entity e = db.entity(42);

Connect and Query

Page 66: Clojure: Simple By Design

Connection conn = !connect("datomic:ddb://us-east-1/mb/mbrainz");!!!Database db = conn.db();!!!Set results = q(..., db);!!!Set crossDbResults = q(..., db1, db2);!!!Entity e = db.entity(42);

Connect and Query

database is a lazily realized value, available

to all peers equally

Page 67: Clojure: Simple By Design

Producing Clojure

Page 68: Clojure: Simple By Design

Design !

specification of an artifact using components to meet goals subject to constraints

Page 69: Clojure: Simple By Design

Goal !

give skilled devs superpowers to build business software

systems

Page 70: Clojure: Simple By Design

Goal !

give skilled devs superpowers to build business software

systems

Page 71: Clojure: Simple By Design

Goal !

give skilled devs superpowers to build business software

systems

Page 72: Clojure: Simple By Design

Constraints

for wide adoption

open source

target established platforms

for viability

performance

stability

Page 73: Clojure: Simple By Design

Constraints

for wide adoption

open source

target established platforms

for viability

performance

stability

Page 74: Clojure: Simple By Design

Open Source

licensed under EPL

contributor agreement

artifacts in Maven Central

not just language: bunch of libs too

Page 75: Clojure: Simple By Design

Might Surprise You

we take patches, not pull requests

we prefer designs over patches

we prefer problem statements over designs

Page 76: Clojure: Simple By Design

Constraints

for wide adoption

open source

target established platforms

for viability

performance

stability

Page 77: Clojure: Simple By Design

Server Performance

http://benchmarksgame.alioth.debian.org/u64q/which-programs-are-fastest.php

Clojure

note: log

scale!

Page 78: Clojure: Simple By Design

Constraints

for wide adoption

open source

target established platforms

for viability

performance

stability

Page 79: Clojure: Simple By Design

2009

Page 80: Clojure: Simple By Design

Maintaining Programming Clojure

release date breakage*

1.0 05/2009 -

1.1 12/2009 None

1.2 08/2010 None

1.3 09/2011 Small

1.4 04/2012 None

1.5 03/2013 None

1.6 03/2014 None

1.7 TBD None

Page 81: Clojure: Simple By Design

One size does not fit all

Page 82: Clojure: Simple By Design

Examples of Simplicity

syntax

protocols

values and references

PICOs!

Page 83: Clojure: Simple By Design

Benefits of Clojure

concision

generality

robustness

agility

Page 84: Clojure: Simple By Design

@stuarthalloway

Page 85: Clojure: Simple By Design

Clojure http://clojure.com. The Clojure language. http://cognitect.com/. The company behind Clojure, ClojureScript, & Datomic. http://blog.cognitect.com/cognicast/. The Cognicast. http://bit.ly/clojure-bookshelf. 40 recommendations from Rich. http://clojure.in/. Planet Clojure. !@stuarthalloway https://github.com/stuarthalloway/presentations/wiki. Presentations. https://github.com/stuarthalloway/exploring-clojure. Sample Code. http://pragprog.com/book/shcloj2/programming-clojure. Programming Clojure. mailto:[email protected]