Friday, 9 May 14
Friday, 9 May 14 Welcome to your New Project Friday, 9 May 14 - - PowerPoint PPT Presentation
Friday, 9 May 14 Welcome to your New Project Friday, 9 May 14 - - PowerPoint PPT Presentation
Friday, 9 May 14 Welcome to your New Project Friday, 9 May 14 Friday, 9 May 14 Friday, 9 May 14 Things are starting to smell Friday, 9 May 14 Code Smells Symptoms in the source code that indicate there may be trouble ahead: Bugs Reduced
Welcome to your New Project
Friday, 9 May 14
Friday, 9 May 14
Friday, 9 May 14
Things are starting to smell
Friday, 9 May 14
Code Smells
Symptoms in the source code that indicate there may be trouble ahead: Bugs Reduced development speed Readability/maintainability problems Heuristics, not hard and fast rules
Friday, 9 May 14
Example: Long parameter Lists
¡
(defn ¡make-‑cheese ¡ ¡ ¡[name ¡ ¡ ¡region ¡ ¡ ¡country ¡ ¡ ¡aoc? ¡ ¡ ¡pdo? ¡ ¡ ¡doc? ¡ ¡ ¡milk-‑origin ¡ ¡ ¡milk-‑origin-‑subspecies ¡ ¡ ¡pastuerized? ¡ ¡ ¡aging-‑time ¡ ¡ ¡mould-‑type])
Friday, 9 May 14
Example: Long parameter Lists
¡
(defn ¡make-‑cheese ¡ ¡ ¡[name ¡ ¡ ¡region ¡ ¡ ¡country ¡ ¡ ¡aoc? ¡ ¡ ¡pdo? ¡ ¡ ¡doc? ¡ ¡ ¡milk-‑origin ¡ ¡ ¡milk-‑origin-‑subspecies ¡ ¡ ¡pastuerized? ¡ ¡ ¡aging-‑time ¡ ¡ ¡mould-‑type])
(make-‑cheese ¡"Bleu ¡de ¡Gex" ¡ ¡"Jura" ¡ ¡"France" ¡true ¡ ¡false ¡ ¡false ¡ ¡:cows ¡ ¡"Montbéliard" ¡ ¡false ¡ ¡(weeks ¡3) ¡ ¡"Penicillium ¡glaucum") ¡ (make-‑cheese ¡ ¡"Stilton" ¡ ¡["Derbyshire" ¡"Leicestershire" ¡ "Nottinghamshire"] ¡ ¡"United ¡Kingdom" ¡ ¡false ¡ ¡true ¡ ¡false ¡ ¡:cows ¡ ¡"local" ¡ ¡true ¡ ¡(weeks ¡9) ¡ ¡"Penicillium ¡roqueforti")
Friday, 9 May 14
What smells?
Hard to read Hard to change Error prone (easy to switch around literals)
Friday, 9 May 14
What smells?
Hard to read Hard to change Error prone (easy to switch around literals)
Next steps
Obvious refactoring: extract parameter
- bjects, alternative
functions make-‑uk-‑ cheese But... indicates underlying issues with how we have chosen to model our data - can we address that too?
Friday, 9 May 14
“Standard” Code Smells
Martin Fowler + Kent Beck in “Refactoring...”: http:// www.amazon.co.uk/Refactoring- Improving-Design-Existing-Technology/ dp/0201485672 Define a standard set of smells focussed on OO and statically typed languages (Java)
Friday, 9 May 14
Taxonomy
Mäntylä, M. V. and Lassenius, C. "Subjective Evaluation of Software Evolvability Using Code Smells: An Empirical Study". Journal of Empirical Software Engineering, vol. 11, no. 3, 2006, pp. 395-431.
BLOATERS Long Method Large Class Primitive Obsession Long Parameter List DataClumps OO ABUSERS Switch Statements Temporary Field Refused Bequest Alternative Classes with Different Interfaces CHANGE PREVENTERS Divergent Change Shotgun Surgery Parallel Inheritance Hierarchies DISPENSIBLES Lazy class Data class Duplicate Code Dead Code Speculativ e Generality COUPLERS Feature Envy Inappropriate Intimacy Message Chains Middle Man Friday, 9 May 14
What do code smells look like in Clojure?
(Or: What do they smell like?)
Friday, 9 May 14
... and why do we care?
Friday, 9 May 14
My CV
2000s
C
Pascal C#
2010s
C++
Java JavaScript Ruby Clojure
Friday, 9 May 14
My CV
2000s
C
Pascal C#
2010s
C++
Java JavaScript Ruby Clojure
IMPERATIVE
EXPRESSION ORIENTED
Friday, 9 May 14
My CV
2000s
C
Pascal C#
2010s
C++
Java JavaScript Ruby Clojure
(Mainly) OO
FUNCTIONAL
Friday, 9 May 14
Friday, 9 May 14
Building on prior work
BLOATERS Long Method Large Class Primitive Obsession Long Parameter List DataClumps OO ABUSERS Switch Statements Temporary Field Refused Bequest Alternative Classes with Different Interfaces CHANGE PREVENTERS Divergent Change Shotgun Surgery Parallel Inheritance Hierarchies DISPENSIBLES Lazy class Data class Duplicate Code Dead Code Speculativ e Generality COUPLERS Feature Envy Inappropriate Intimacy Message Chains Middle Man Friday, 9 May 14
OO-Specific Stuff
BLOATERS Long Method Large Class Primitive Obsession Long Parameter List DataClumps OO ABUSERS Switch Statements Temporary Field Refused Bequest Alternative Classes with Different Interfaces CHANGE PREVENTERS Divergent Change Shotgun Surgery Parallel Inheritance Hierarchies DISPENSIBLES Lazy class Data class Duplicate Code Dead Code Speculative Generality COUPLERS Feature Envy Inappropriate Intimacy Message Chains Middle Man Friday, 9 May 14
A few edits...
BLOATERS
Long method function Large Class namespace
Primitive Obsession Long Parameter List DataClumps CHANGE PREVENTERS Divergent Change Shotgun Surgery DISPENSIBLES
Lazy Class function
Duplicate Code Dead Code Speculative Generality COUPLERS Feature Envy Inappropriate Intimacy Message Chains Middle Man Friday, 9 May 14
Mäntylä, M. V. and Lassenius, C. "Subjective Evaluation of Software Evolvability Using Code Smells: An Empirical Study". Journal of Empirical Software Engineering, vol. 11, no. 3, 2006, pp. 395-431.
BLOATERS Long function Large namespace Long Parameter List DataClumps CHANGE PREVENTERS Divergent Change Shotgun Surgery DISPENSIBLES Lazy function Duplicate Code Dead Code Speculative Generality COUPLERS Feature Envy Inappropriate Intimacy Message Chains Middle Man Primitive Obsession
Primitive Obsession
“Primitive Obsession is using primitive data types to represent domain
- ideas. For example, we use a String to represent a message, an Integer to
represent an amount of money, or a Struct/Dictionary/Hash to represent a specific object.” http://c2.com/cgi/wiki?PrimitiveObsession
... are collections in Clojure that primitive?
A few edits...
Friday, 9 May 14
Clojure-specific Smells
DYS-FUNCTIONAL CODE
??? ??? ??? ???
Friday, 9 May 14
Magic Keys
(clavis magica)
AKA: Data structure coupling Over-sharing structure / content of maps/records leading to implicit coupling
Friday, 9 May 14
Example
{ ¡:name ¡"Stilton" ¡ ¡:milk ¡{:milk-‑type ¡:cows ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:origin-‑subspecies ¡"local" ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:is-‑pasteurized? ¡true} ¡ ¡:mould-‑type ¡"Penicillium ¡roqueforti" ¡ ¡:region ¡ ¡ ¡["Derbyshire" ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡"Leicestershire" ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡"Nottinghamshire"] ¡ ¡:country ¡"United ¡Kingdom" ¡ ¡:aging-‑time ¡nil}
Friday, 9 May 14
Example
(defn ¡calculate-‑olfactory-‑offence ¡ ¡[{:keys ¡[milk ¡mould-‑type ¡aging-‑time ¡washing-‑solution]}] ¡ ¡(let ¡[pasteurization-‑factor ¡(if ¡(:is-‑pasteurized? ¡milk) ¡0.5 ¡1)] ¡ ¡ ¡ ¡(* ¡aging-‑time ¡ ¡ ¡ ¡ ¡ ¡ ¡(+ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(milk-‑type-‑>smell ¡(:milk-‑type ¡milk)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡pasteurization-‑factor ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(mould-‑>smell ¡mould-‑type) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(washing-‑solution-‑>smell ¡washing-‑solution-‑>smell))))) ¡ (defn ¡lactose-‑levels ¡[{:keys ¡[milk ¡quantity]}] ¡ ¡(if ¡(:is-‑pasteurized? ¡milk) ¡ ¡ ¡ ¡(calculate-‑pasteurized-‑lactose-‑levels ¡quantity ¡(:milk-‑type ¡milk)) ¡ ¡ ¡ ¡(calculate-‑unpasteurized-‑lactose-‑levels ¡quantity ¡(:milk-‑type ¡milk))))
Friday, 9 May 14
Example
(defn ¡calculate-‑olfactory-‑offence ¡ ¡[{:keys ¡[milk ¡mould-‑type ¡aging-‑time ¡washing-‑solution]}] ¡ ¡(let ¡[pasteurization-‑factor ¡(if ¡(:is-‑pasteurized? ¡milk) ¡0.5 ¡1)] ¡ ¡ ¡ ¡(* ¡aging-‑time ¡ ¡ ¡ ¡ ¡ ¡ ¡(+ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(milk-‑type-‑>smell ¡(:milk-‑type ¡milk)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡pasteurization-‑factor ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(mould-‑>smell ¡mould-‑type) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(washing-‑solution-‑>smell ¡washing-‑solution-‑>smell))))) ¡ (defn ¡lactose-‑levels ¡[{:keys ¡[milk ¡quantity]}] ¡ ¡(if ¡(:is-‑pastuerized? ¡milk) ¡ ¡ ¡ ¡(calculate-‑pastuerized-‑lactose-‑levels ¡quantity ¡(:milk-‑type ¡milk)) ¡ ¡ ¡ ¡(calculate-‑unpasteurized-‑lactose-‑levels ¡quantity ¡(:milk-‑type ¡milk)))) ¡
Friday, 9 May 14
What smells?
Hard to figure out the cost of change of key names, data types etc. Unexpected errors if data is in the wrong shape in production ... too many fns know the intimate details about the structure. Easy mess to get into - tradeoff of modelling data as maps
Friday, 9 May 14
What smells?
Hard to figure out the cost of change of key names, data types etc. Unexpected errors if data is in the wrong shape in production ... too many fns know the intimate details about the structure. Easy mess to get into - tradeoff of modelling data as maps
What to do
Keep data-aware fns together (defrecord?) Minimise how many fns know about structure For data that is coming from elsewhere, consider core.contracts or something like Schema to add appropriate checks
Friday, 9 May 14
Better?
(defn ¡milk-‑>smell ¡[{:keys ¡[milk-‑type ¡is-‑pasteurized?]}] ¡ ¡(+ ¡ ¡ ¡(if ¡is-‑pasterurized? ¡0.5 ¡1) ¡ ¡ ¡(milk-‑type-‑>smell ¡milk-‑type))) ¡ (defn ¡lactose-‑levels ¡[{:keys ¡[milk-‑origin ¡is-‑pasteurized?]}] ¡ ¡(if ¡is-‑pasteurized? ¡ ¡ ¡ ¡(calculate-‑pasteurized-‑lactose-‑levels ¡milk-‑origin) ¡ ¡ ¡ ¡(calculate-‑unpasteurized-‑lactose-‑levels ¡milk-‑origin)))
Getting there.
Friday, 9 May 14
Parens Proliferation
(involvimus in aeternum)
AKA: Over-nesting Excessive nesting of expressions making things hard to read and understand
Friday, 9 May 14
Example
(defn ¡make-‑mozarella ¡[citric-‑acid ¡rennet ¡milk] ¡ ¡(zipmap ¡[:curds ¡:whey] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(separate ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(stir-‑for ¡(minutes ¡5) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(warm-‑to ¡(farenheit ¡105) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(cut-‑into-‑squares ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(leave-‑until-‑turned-‑into-‑curds ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(minutes ¡5) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(combine ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(dissolve-‑in-‑water ¡rennet) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(warm-‑to ¡(farenheit ¡90) ¡milk)))))))))
Friday, 9 May 14
Example
(defn ¡make-‑mozarella ¡[citric-‑acid ¡rennet ¡milk] ¡ ¡(zipmap ¡[:curds ¡:whey] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(separate ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(stir-‑for ¡(minutes ¡5) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(warm-‑to ¡(farenheit ¡105) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(cut-‑into-‑squares ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(leave-‑until-‑turned-‑into-‑curds ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(minutes ¡5) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(combine ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(dissolve-‑in-‑water ¡rennet) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(warm-‑to ¡(farenheit ¡90) ¡milk)))))))))
Friday, 9 May 14
What smells?
Trying to do everything on
- ne line
Easy to evaluate, hard to read, nightmare to debug Side-affect of being an expression-oriented language
Friday, 9 May 14
What smells?
Trying to do everything on
- ne line
Easy to evaluate, hard to read, nightmare to debug Side-affect of being an expression-oriented language
What to do
Keep a balance between terseness and readability: not everything needs to be on one line! Excessive )))))) is a good heuristic let, ¡-‑>, ¡-‑>> are your friends
Friday, 9 May 14
Better?
(defn ¡make-‑mozarella-‑improved ¡[citric-‑acid ¡rennet ¡milk] ¡ ¡(let ¡[ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡rennet-‑solution ¡(dissolve-‑in-‑water ¡rennet) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡warmed-‑milk ¡(warm-‑to ¡(farenheit ¡90) ¡milk)] ¡ ¡ ¡ ¡(-‑>> ¡[rennet-‑solution ¡warmed-‑milk] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(combine) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(leave-‑until-‑turned-‑into-‑curds) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(cut-‑into-‑squares) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(warm-‑to ¡(farenheit ¡105)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(stir-‑for ¡(minutes ¡5)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(separate) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(zipmap ¡[:curds ¡:whey]))))
If recipes looked like this, I would be a better cheese maker
Friday, 9 May 14
Lazi-itis
(codex dormientes)
Nested levels of lazy sequences leading to errors popping up in confusing places
Friday, 9 May 14
Example
What happens if ‘load-cheese-by-id’ has a database connection problem?
(defn ¡cheese-‑smell-‑analyser ¡[cheeses-‑to-‑assess] ¡ ¡(-‑>> ¡cheeses-‑to-‑assess ¡ ¡ ¡ ¡ ¡ ¡ ¡(map ¡parse-‑cheese-‑ids) ¡ ¡ ¡ ¡ ¡ ¡ ¡(map ¡load-‑cheese-‑by-‑id) ¡ ¡ ¡ ¡ ¡ ¡ ¡(map ¡#(select-‑keys ¡% ¡[:mould-‑type ¡:aging-‑time])) ¡ ¡ ¡ ¡ ¡ ¡ ¡(map ¡get-‑odour-‑level) ¡ ¡ ¡ ¡ ¡ ¡ ¡(reduce ¡#(merge-‑with ¡max ¡%1 ¡%2) ¡{})))
Friday, 9 May 14
Stack trace
java.lang.Exception: ¡Kablammo ¡at ¡cheese_factory.mozarella$load_cheese_by_id.invoke ¡(cheese.clj:66) ¡ ¡ ¡ ¡clojure.core$map$fn__4207.invoke ¡(core.clj:2485) ¡ ¡ ¡ ¡clojure.lang.LazySeq.sval ¡(LazySeq.java:42) ¡ ¡ ¡ ¡clojure.lang.LazySeq.seq ¡(LazySeq.java:60) ¡ ¡ ¡ ¡clojure.lang.RT.seq ¡(RT.java:484) ¡ ¡ ¡ ¡clojure.core$seq.invoke ¡(core.clj:133) ¡ ¡ ¡ ¡clojure.core$map$fn__4207.invoke ¡(core.clj:2479) ¡ ¡ ¡ ¡clojure.lang.LazySeq.sval ¡(LazySeq.java:42) ¡ ¡ ¡ ¡clojure.lang.LazySeq.seq ¡(LazySeq.java:60) ¡ ¡ ¡ ¡clojure.lang.RT.seq ¡(RT.java:484) ¡ ¡ ¡ ¡clojure.core$seq.invoke ¡(core.clj:133) ¡ ¡ ¡ ¡clojure.core$map$fn__4207.invoke ¡(core.clj:2479) ¡ ¡ ¡ ¡clojure.lang.LazySeq.sval ¡(LazySeq.java:42) ¡ ¡ ¡ ¡clojure.lang.LazySeq.seq ¡(LazySeq.java:60) ¡ ¡ ¡ ¡clojure.lang.RT.seq ¡(RT.java:484) ¡ ¡ ¡ ¡clojure.core$seq.invoke ¡(core.clj:133) ¡ ¡ ¡ ¡clojure.core.protocols$seq_reduce.invoke ¡(protocols.clj:30) ¡ ¡ ¡ ¡clojure.core.protocols/fn ¡(protocols.clj:54) ¡ ¡ ¡ ¡clojure.core.protocols$fn__5979$G__5974__5992.invoke ¡(protocols.clj:13) ¡ ¡ ¡ ¡clojure.core$reduce.invoke ¡(core.clj:6177) ¡ ¡ ¡ ¡cheese_factory.mozarella$cheese_smell_analyser.invoke ¡(NO_SOURCE_FILE:3) ¡ ¡ ¡ ¡cheese_factory.mozarella$eval1517.invoke ¡(NO_SOURCE_FILE:1) ¡ ¡ ¡ ¡clojure.lang.Compiler.eval ¡(Compiler.java:6619) ¡ ¡ ¡ ¡clojure.lang.Compiler.eval ¡(Compiler.java:6582) ¡ ¡ ¡ ¡clojure.core$eval.invoke ¡(core.clj:2852) ¡ ¡ ¡ ¡clojure.main$repl$read_eval_print__6588$fn__6591.invoke ¡(main.clj:259) ¡ ¡ ¡ ¡clojure.main$repl$read_eval_print__6588.invoke ¡(main.clj:259) ¡ ¡ ¡...
Friday, 9 May 14
What smells?
Many discrete steps with final step that executes the sequence Hard to isolate failures (which cheese didn’t load?)
Friday, 9 May 14
What smells?
Many discrete steps with final step that executes the sequence Hard to isolate failures (which cheese didn’t load?)
What to do
Friday, 9 May 14
What smells?
Many discrete steps with final step that executes the sequence Hard to isolate failures (which cheese didn’t load?)
What to do
Consider pulling things into coarser-grained steps to avoid long pipelines Add in failure mode support for external system access - not just exceptions! Realise lazy sequences in a consistent way - module boundaries?
Friday, 9 May 14
Better?
(defn ¡cheese-‑smell-‑analyser-‑2 ¡[cheeses-‑to-‑assess] ¡ ¡(-‑>> ¡cheeses-‑to-‑assess ¡ ¡ ¡ ¡ ¡ ¡ ¡(load-‑cheeses) ¡ ¡ ¡ ¡ ¡ ¡ ¡(map ¡get-‑odour-‑level) ¡ ¡ ¡ ¡ ¡ ¡ ¡(reduce ¡calculate-‑stats)))
TODO: Better error handling...
Friday, 9 May 14
Clojure Code Smells
BLOATERS Long function Large namespace Long Parameter List DataClumps CHANGE PREVENTERS Divergent Change Shotgun Surgery DISPENSIBLES Lazy function Duplicate Code Dead Code Speculative Generality COUPLERS Feature Envy Inappropriate Intimacy Message Chains Middle Man Primitive Obsession
DYS-FUNCTIONAL CODE
Magic Keys Parenthesen Proliferation Lazy-itis Friday, 9 May 14
Other suggestions
Macromania Indirection by partiality Locally scoped atoms (more?)
Friday, 9 May 14
Do we need code smells?
Friday, 9 May 14
Do we need code smells?
Friday, 9 May 14
Do we need code smells?
Friday, 9 May 14
The common factor Software developer
(Codex scriptor familiaris)
Friday, 9 May 14
Are smells just
- verdoing it?
Data as maps => magic keys Lazy sequences => lazyitis expression-oriented => parens proliferation macros => macromania partial function application => indirection by partiality
Friday, 9 May 14
Probably...
We should be thinking more and writing less and evaluating the tradeoffs and applicability of our approaches Code smells can help us guide us in the right direction and learn from each other
Friday, 9 May 14
FIN
Friday, 9 May 14
Image credits
- http://www.flickr.com/photos/photophilde/3514290419/
- http://www.flickr.com/photos/marilynjane/341095494/
- http://www.flickr.com/photos/jeremyrebelka/3242678416/
- http://www.flickr.com/photos/huggleperson/7980839256/
- http://www.flickr.com/photos/eighttrees/3225831955/
- http://www.clker.com/clipart-key-vintage.html
- https://twitter.com/otfrom
Friday, 9 May 14