living without objects (thinking in functions)

57
LIVING W/O OBJECTS THINKING IN FUNCTIONS Osvaldas Grigas | @ogrigas

Upload: osvaldas-grigas

Post on 09-Aug-2015

168 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Living without Objects (Thinking in Functions)

LIVING W/O OBJECTSTHINKING IN FUNCTIONS

Osvaldas Grigas | @ogrigas

Page 2: Living without Objects (Thinking in Functions)

OOP HANGOVER

Page 3: Living without Objects (Thinking in Functions)

DESIGN

Page 4: Living without Objects (Thinking in Functions)

DESIGNBefore After

Page 5: Living without Objects (Thinking in Functions)

MONOLITHIC DESIGN

Page 6: Living without Objects (Thinking in Functions)

OO DESIGNNoun-orientedVerb-orientedDomain-driven?

Page 7: Living without Objects (Thinking in Functions)

NOUNSCustomerDAOCustomerServiceCustomerController

Page 8: Living without Objects (Thinking in Functions)

VERBSRegisterCustomerPromoteCustomerToVIPRenderCustomerProfilePage

Page 9: Living without Objects (Thinking in Functions)

OO DESIGN PRINCIPLESSingle ResponsibilityInterface SegregationDependency Inversion

Page 10: Living without Objects (Thinking in Functions)

SINGLE RESPONSIBILITYpublic class ZipDownloadService

public List<File> downloadAndExtract(String location)

Page 11: Living without Objects (Thinking in Functions)

SINGLE RESPONSIBILITYpublic class FileDownloader

public List<File> downloadFiles(String location) ...

public class ZipExtractor

public File extractZip(File archive) ...

Page 12: Living without Objects (Thinking in Functions)

OR ... JUST FUNCTIONS(defn download­files [location] (...))

(defn extract­zip [archive] (...))

Page 13: Living without Objects (Thinking in Functions)

CLOJUREin a nutshell

( some-function arg1 arg2 arg3 )

Page 14: Living without Objects (Thinking in Functions)

INTERFACE SEGREGATIONpublic class ProductCatalog public ProductId Save(Product product) ...

public Product FindById(ProductId id) ...

Page 15: Living without Objects (Thinking in Functions)

INTERFACE SEGREGATIONpublic class ProductSaver public ProductId Save(Product product) ...

public class ProductFinder public Product FindById(ProductId id) ...

Page 16: Living without Objects (Thinking in Functions)

Somethin' ain't right

Page 17: Living without Objects (Thinking in Functions)

INTERFACE SEGREGATIONpublic class ProductRepository public ProductId Save(Product product) ...

public class ProductQuery public Product FindById(ProductId id) ...

Page 18: Living without Objects (Thinking in Functions)

Feelin' good now

Page 19: Living without Objects (Thinking in Functions)

OR ... JUST FUNCTIONS(defn save­product [product] (...))

(defn find­product­by­id [id] (...))

Page 20: Living without Objects (Thinking in Functions)

Applying OO design principleseventually leads to...

functional design

Page 21: Living without Objects (Thinking in Functions)

WHAT'S MISSINGCode organizationEncapsulationInheritance hierarchiesPolymorphism

Page 22: Living without Objects (Thinking in Functions)

NO CODE ORGANIZATION?

(ns my.product.repository)

(defn save [product] (...))

(defn find­by­id [id] (...))

(require '[my.product.repository :as product­repo])

(product­repo/find­by­id 42)

Page 23: Living without Objects (Thinking in Functions)

NO ENCAPSULATION?

Data is not an objectData is immutable

Page 24: Living without Objects (Thinking in Functions)

NO INHERITANCE HIERARCHIES?

Blimey! What a showstopper

Page 25: Living without Objects (Thinking in Functions)

NO POLYMORPHISM?

We'll get there

Page 26: Living without Objects (Thinking in Functions)

COMPOSITION

Page 27: Living without Objects (Thinking in Functions)
Page 28: Living without Objects (Thinking in Functions)

COMPOSITIONAvoiding hard-coded dependencies

Page 29: Living without Objects (Thinking in Functions)

OO COMPOSITIONpublic class ProfilePage

public String render(Repository repository, int customerId) return toHtml(repository.loadProfile(customerId));

Repository repository = new Repository();ProfilePage page = new ProfilePage();

String html = page.render(repository, customerId);

Page 30: Living without Objects (Thinking in Functions)

FP COMPOSITION(defn render­page [repository­fn customer­id] (to­html (repository­fn customer­id)))

(defn load­profile [customer­id] (...))

(render­page load­profile customer­id)

Page 31: Living without Objects (Thinking in Functions)

OO "DEPENDENCY INJECTION"ProfilePage pageInjected = new ProfilePage(new Repository());

pageInjected.render(customerId);

Page 32: Living without Objects (Thinking in Functions)

FP "DEPENDENCY INJECTION"(def render­injected (fn [customer­id] (render­page load­profile customer­id)))

(render­injected customer­id)

Page 33: Living without Objects (Thinking in Functions)

PARTIAL APPLICATION(def render­injected (partial render­page load­profile))

(render­injected customer­id)

Page 34: Living without Objects (Thinking in Functions)

"ADAPTER" PATTERN(defn parse­int [s] (Integer/parseInt s))

(render­page (comp load­profile parse­int) customer­id)

(defn to­view­model [profile] (...))

(render­page (comp to­view­model load­profile) customer­id)

Page 35: Living without Objects (Thinking in Functions)

"DECORATOR" PATTERN(defn with­logging [f] (fn [& args] (log/debug "Called with params" args) (def [result (apply f args)] (log/debug "Returned" result) result)))

(render­page (with­logging load­profile) customer­id)

Page 36: Living without Objects (Thinking in Functions)

POLYMORPHISM

Page 37: Living without Objects (Thinking in Functions)
Page 38: Living without Objects (Thinking in Functions)

POLYMORPHISMI don't know.

I don't want to know.

Page 39: Living without Objects (Thinking in Functions)

POLYMORPHISMSubtypeParametricAd-hoc

Page 40: Living without Objects (Thinking in Functions)

OO POLYMORPHISMInheritance hierarchyInterfacesDependency inversion

Page 41: Living without Objects (Thinking in Functions)

public interface JsonObj String toJson();

Page 42: Living without Objects (Thinking in Functions)

public class JsonString implements JsonObj private final String value;

public JsonString(String value) this.value = value;

public String toJson() return "\"" + value + "\"";

Page 43: Living without Objects (Thinking in Functions)

public class JsonList implements JsonObj private final List<? extends JsonObj> list;

public JsonString(List<? extends JsonObj> list) this.list = list;

public String toJson() return "[" + list.stream() .map(JsonObj::toJson) .collect(joining(",")) + "]";

Page 44: Living without Objects (Thinking in Functions)

JsonObj obj = new JsonList(asList( new JsonString("a"), new JsonList(asList( new JsonString("b"), new JsonString("c") )), new JsonString("d")));

System.out.println(obj.toJson());

// ["a",["b","c"],"d"]

Page 45: Living without Objects (Thinking in Functions)

LIMITATIONS

Need wrapper typesCannot extend existing types

Page 46: Living without Objects (Thinking in Functions)

Too constraining!

Page 47: Living without Objects (Thinking in Functions)

FP POLYMORPHISMFunction compositionDispatch on parameters

Page 48: Living without Objects (Thinking in Functions)

PROTOCOLSopen type system

Page 49: Living without Objects (Thinking in Functions)

(defprotocol Json (to­json [this]))

Page 50: Living without Objects (Thinking in Functions)

(extend­type String Json (to­json [this] (str "\"" this "\"")))

(extend­type List Json (to­json [this] (str "[" (­>> this (map to­json) (string/join ",")) "]")))

(extend­type nil Json (to­json [this] "null"))

Page 51: Living without Objects (Thinking in Functions)

(to­json ["a" ["b" "c"] nil "d"])

;;=> ["a",["b","c"],null,"d"]

Page 52: Living without Objects (Thinking in Functions)

Why stop there?

Page 53: Living without Objects (Thinking in Functions)

MULTIMETHODS

Page 54: Living without Objects (Thinking in Functions)

(defmulti greet :country)

(defmethod greet "LT" [person] (println "Labas," (:name person) ". Kaip sekasi?"))

(defmethod greet "FR" [person] (println "Bonjour," (:name person) "!"))

(defmethod greet :default [person] (println "Hi," (:name person)))

(greet :name "Jacques" :country "FR")

;;=> Bonjour, Jacques !

Page 55: Living without Objects (Thinking in Functions)

(defmulti say (fn [text n] (even? n)))

(defmethod say true [text n] (println text n "is even"))

(defmethod say false [text n] (println text n "is odd"))

(say "Guess what?" 5)

;;=> Guess what? 5 is odd

Page 56: Living without Objects (Thinking in Functions)

CONCLUSIONDesignCompositionPolymorphism

Page 57: Living without Objects (Thinking in Functions)

I'm probably over time already

(questions? "Osvaldas Grigas" @ogrigas)