Getting simple

Designing and Maintaining Software (DAMS)
 Louis Rose

Habitable Software Leaner

Avoids Duplication

Less Complex

Clearer

Loosely Coupled

More Extensible

More Cohesive

???

Tactics Favour shorter methods (and classes) Favour “functional style” to loops Favour method calls to conditionals

Loops Conjecture 1: Looping is a low-level evil class Pizza def title if @toppings.empty? "Margherita" else title = "" @toppings.each do |topping| title += " and " unless title.empty? title += topping end title end end end

Loop like it’s 1999 Remember this? class Pizza def title if @toppings.empty? "Margherita" else title = "" index = 0 while index < @toppings.length topping = @toppings[index] title += " and " unless title.empty? title += topping index += 1 end title end end end

Loop like it’s 1999 Or was it this? class Pizza def title if @toppings.empty? "Margherita" else title = "" index = 0 while index <= @toppings.length topping = @toppings[index] title += " and " unless title.empty? title += topping index += 1 end title end end end

Loop like it’s 1999 Or this??! class Pizza def title if @toppings.empty? "Margherita" else title = "" index = 0 while index <= @toppings.length - 1 topping = @toppings[index] title += " and " unless title.empty? title += topping index += 1 end title end end end

Loop like it’s 2099 Let’s never do that again class Pizza def title if @toppings.empty? "Margherita" else title = "" @toppings.each do |topping| title += " and " unless title.empty? title += topping end title end end end

Loop like it’s 2099 And most modern languages have now learnt from FP class Pizza def title if @toppings.empty? "Margherita" else title = "" @toppings.each do |topping| title += " and " unless title.empty? title += topping end title end end end

Loop like it’s 2099 Ruby: see the Enumerable API

class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end end

Loop like it’s 2099 Ruby: see the Enumerable API

class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end end

Conditionals Conjecture 2: Conditionals are a low-level evil

class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end end

Conditionals Toppings is an array. Is it the right abstraction?

class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end end

Conditionals Toppings is an array. Is it the right abstraction?

class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end end

Conditionals Toppings is an array. Is it the right abstraction?

class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end end

Conditionals If only Ruby arrays knew about pizzas…

class Pizza def title @toppings.pizzaify end end

Conditionals Array is not the right abstraction.

class Pizza
 def initialize(toppings = []) @toppings = toppings end def title @toppings.pizzaify end end

Conditionals Array is not the right abstraction. class Pizza def initialize(toppings = []) if toppings.empty? @toppings = Plain.new else @toppings = Topped.new(toppings) end end def title @toppings.pizzaify end end

Conditionals Abstractions should come from the problem domain. class Pizza def initialize(toppings = []) if toppings.empty? @toppings = Plain.new else @toppings = Topped.new(toppings) end end def title @toppings.pizzaify end end

class Plain def pizzaify "Margherita" end end class Topped def initialize(toppings = []) @toppings = toppings end def pizzaify @toppings.join(“ and ") end end

Conditionals Pizzaify wasn’t the greatest name… class Pizza def initialize(toppings = []) if toppings.empty? @toppings = Plain.new else @toppings = Topped.new(toppings) end end def title @toppings.title end end

class Plain def title "Margherita" end end class Topped def initialize(toppings = []) @toppings = toppings end def title @toppings.join(" and ") end end

Hang on… Classes

Methods

LOC

Cyclomatic Complexity (>1)

1

2

12

Pizza#title

3

5

25

Pizza#initialize

Conditionals But these kinds of conditionals tend to breed… class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end def cost cost = 4 if @toppings.empty? cost += 1 else cost += @toppings.size * 2 end end end

Conditionals But these kinds of conditionals tend to breed… class Pizza def title if @toppings.empty? "Margherita" else @toppings.join(" and ") end end def cost cost = 4 if @toppings.empty? cost += 1 else cost += @toppings.size * 2 end end end

Conditionals Prefer method calls to conditionals. class Plain def title "Margherita" end

class Pizza def title @toppings.title end def cost @toppings.cost + 4 end end

def cost 1 end end class Topped def title @toppings.join(" and ") end def cost @toppings.size * 2 end end

Aha! Classes

Methods

LOC

Cyclomatic Complexity (>1)

1

3

20

Pizza#title
 Pizza#cost

3

8

34

Pizza#initialize

Null Object Pattern Encapsulate the absence of an object

Active Nothing

Summary Complex methods hinder habitability. Avoid loops by using a
 declarative, functional style. Avoid conditionals by using objects
 and method calls.

Also important Strategy and Visitor patterns for
 avoiding conditionals in other situations. Further resources on designing
 to avoid conditionals: “Nothing is Something”
 Sandi Metz (RailsConf 2015)
 
 “Unconditional Programming”
 Michael Feathers (2013 blog post)

end - GitHub

Aha! Classes. Methods. LOC. Cyclomatic. Complexity (>1). 1. 3. 20. Pizza#title. Pizza#cost. 3. 8. 34. Pizza#initialize. Page 26. Null Object Pattern. Encapsulate ...

155KB Sizes 2 Downloads 204 Views

Recommend Documents

End-To-End Sequential Consistency - UCLA CS
Sequential consistency (SC) is arguably the most intuitive behavior for a shared-memory multithreaded program. It is widely accepted that language-level SC could significantly improve programmability of a multiprocessor system. How- ever, efficiently

GitHub
domain = meq.domain(10,20,0,10); cells = meq.cells(domain,num_freq=200, num_time=100); ...... This is now contaminator-free. – Observe the ghosts. Optional ...

GitHub
data can only be “corrected” for a single point on the sky. ... sufficient to predict it at the phase center (shifting ... errors (well this is actually good news, isn't it?)

END-TO-END ARGUMENTS IN SYSTEM DESIGN JH ...
Mar 30, 2001 - M.I.T. Laboratory for Computer Science ... The argument appeals to application requirements, and provides ... the application provide the basis for a class of arguments, which go as follows: ... correctly onto the disk at host A, if re

End-to-End Attention-based Large Vocabulary Speech ...
End-to-End Attention-based Large Vocabulary Speech Recognition_Last.pdf. End-to-End Attention-based Large Vocabulary Speech Recognition_Last.pdf.

End-to-end Verification of QoS Policies - Research at Google
A service level agreement (SLA) is the contract by which requests for a certain QoS are specified between the user and the Internet service provider (ISP).

End-to-End Training of Acoustic Models for Large Vocabulary ...
Large Vocabulary Continuous Speech Recognition with TensorFlow. Ehsan Variani ... to batching of training data, unrolling of recurrent acoustic models, and ...

Tracking Ransomware End-to-end - Research at Google
When the encryption completes, the ransomware displays a ransom note on the host's screen, informing the user that those files are held for ransom, payable in ...... file system, we place documents that Cerber is known to encrypt [11]. We also instru

Characterizing End-to-End Packet Reordering ... - Research at Google
Previous studies have reported statistics and character- ... The percentages of RO observed on data ... the analysis of the data collected in our four measure-.

Lattice Based Transcription Loss for End-to-End ...
architecture has performed better than traditional DNNs , and the use of temporal ..... pass large vocabulary continuous speech recognition using bi- directional ...

Correlations in End-to-End Network Metrics ... - Semantic Scholar
and services running on top of the network infrastructure. Since changes ... ROUTE. CAPACITY. Fig. 1. Correlations in different e2e network metrics along with.

Moving Beyond End-to-End Path Information to Optimize CDN ...
High combines several different data sources such as BGP tables from routers, mapping of ... In Section 4, we describe the WhyHigh system that we developed to diagnose ... the nameserver. Redirection decisions made at the granularity of.

End to end secure communication in ad-hoc ... - Semantic Scholar
Jul 13, 2009 - Different wireless technologies and different types of communication interfaces .... WiFi and a 3G interface, and can be a laptop, a PDA or a 3G.

End-to-End Service Orchestration across SDN and ... - Fulvio Risso
End-to-end service deployment of Network Functions Vir- ... 1. Service graph deployment in a multi-domain environment. the proper network parameters, thus ...

Joint Opportunistic Power Scheduling and End-to-End ...
J.-W. Lee is with CITY-Center for Information Technology of Yonsei. University, Department .... we need a central controller to collect the information of each link and perform the ...... degree in Electrical and Computer Engineer- ing from Purdue ..

End-to-end Secure Multi-hop Communication with ...
bi mod 2, i = 1...N. It is easy to see the relationship ∼ is an equivalence relationship. Therefore, it defines a partition over Λ. 1) Depending on the values of ai −bi ...