SlideShare a Scribd company logo
Law of Demeter
Don’t Mess With The Law
‘
@michaelelfassy
Michael Elfassy
Smashing Boxes
Definition
1. Each unit should have only limited knowledge about
other units
2. Each unit should only talk to its friends; don't talk to
strangers.
3. Only talk to your immediate friends.
source: Wikipedia
In other words
An object should only invoke methods of these kind of
objects:
1. itself
2. its parameters
3. any objects it creates
4. its direct component objects
5. objects of the same type*
itself
class User
attr_accessor :first_name, :last_name
def name
"#{first_name} #{last_name}"
end
end
its parameters
def nickname(name)
"#{name[0..2]}o"
end
objects it creates
def total
calculator = Calculator.new
average + calculator.square(mean)
end
direct components
def initialize()
@calculator = Calculator.new
end
def total
average + @calculator.square(mean)
end
objects of the same type*
# String
name.strip.gsub(/^a/,'b').constantize
# ActiveRecord Relation
User.where(...).order
Violations
class User
belongs_to :department
def division_name
department.division.name
end
end
Violations
try().try()
smells bad!
class User
belongs_to :department
def division_name
# we know the user has a department
dep = department
# we're assuming the department has a function called division
# which returns the associated division object
# we're assuming that every department belongs to a division
div = dep.division
# we're assuming the division has a name attribute
division_name = div.name
end
end
Dependency assumption
● Duplication
o Once you traverse in one place you are likely to traverse in another place
● Few places understand the relationships
● Don’t create “context”
● at each step of the traversal, the value
returned is decided by the object being
asked
Following the Law
class User
belongs_to :department
def division_name
# ask the department for a division name (you decide how you are going to get it!)
department.try(:division_name)
end
end
class Department
belongs_to :division
def division_name
# ask the division for a name (you decide how you are going to get it!)
division.name
end
end
The rails way(™)
class User
belongs_to :department
delegate :division_name, to: :department, allow_nil: true
end
class Department
belongs_to :division
delegate :name, to: :division, prefix: true
delegate :director, to: :division
end
Testing
Now we can test models independently without
having to do nested stubs!
I am the law
let’s replace all . with _ !
NO…
Don’t only fix the violations, look at what they
are telling you. Refactor!
Wallet example
class Wallet
attr_accessor :cash
end
class Customer
has_one :wallet
end
class Paperboy
def collect_money(customer, due_amount)
if customer.wallet.cash < due_ammount
raise InsufficientFundsError
else
customer.wallet.cash -= due_amount
@collected_amount += due_amount
end
end
end
paperboy should not be taking cash
out of a customer's wallet
Delegate attributes
class Customer
has_one :wallet
# attribute delegation
def cash
@wallet.cash
end
end
class Paperboy
def collect_money(customer, due_amount)
if customer.cash < due_ammount
raise InsufficientFundsError
else
customer.cash -= due_amount
@collected_amount += due_amount
end
end
end
paperboy doesn’t need to know how much
cash the client has in his wallet
Delegate Behaviour
class Customer
has_one :wallet
# behavior delegation
def pay(amount)
@wallet.withdraw(amount)
end
end
class Paperboy
def collect_money(customer, due_amount)
@collected_amount += customer.pay(due_amount)
end
end
Tell don’t ask
Summary
● It’s a guideline more than a law
● Look for the spirit of the law
● try.try just smells
Hint, it’s not a real gun
Cardboard - CMS / Admin Panel
https://github.com/smashingboxes/cardboard

More Related Content

Similar to The Law of Demeter

Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & Stubs
PatchSpace Ltd
 
Nedap Rails Workshop
Nedap Rails WorkshopNedap Rails Workshop
Nedap Rails Workshop
Andre Foeken
 
Metaprogramming in Ruby
Metaprogramming in RubyMetaprogramming in Ruby
Metaprogramming in Ruby
ConFoo
 

Similar to The Law of Demeter (20)

جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
 
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونیاسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.
 
TDC2016POA | Trilha Ruby - Melhorando seu código com Law of Demeter e Tell do...
TDC2016POA | Trilha Ruby - Melhorando seu código com Law of Demeter e Tell do...TDC2016POA | Trilha Ruby - Melhorando seu código com Law of Demeter e Tell do...
TDC2016POA | Trilha Ruby - Melhorando seu código com Law of Demeter e Tell do...
 
Melhorando seu código com Law of Demeter e Tell don't ask
Melhorando seu código com Law of Demeter e Tell don't askMelhorando seu código com Law of Demeter e Tell don't ask
Melhorando seu código com Law of Demeter e Tell don't ask
 
Chap 3 Python Object Oriented Programming - Copy.ppt
Chap 3 Python Object Oriented Programming - Copy.pptChap 3 Python Object Oriented Programming - Copy.ppt
Chap 3 Python Object Oriented Programming - Copy.ppt
 
C++ Interview Questions
C++ Interview QuestionsC++ Interview Questions
C++ Interview Questions
 
Advanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID PrinciplesAdvanced Object-Oriented/SOLID Principles
Advanced Object-Oriented/SOLID Principles
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
 
About Python
About PythonAbout Python
About Python
 
Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & Stubs
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
S12.s01 - Material TP.pdf
S12.s01 - Material TP.pdfS12.s01 - Material TP.pdf
S12.s01 - Material TP.pdf
 
Values
ValuesValues
Values
 
Python classes objects
Python classes objectsPython classes objects
Python classes objects
 
Learning puppet chapter 2
Learning puppet chapter 2Learning puppet chapter 2
Learning puppet chapter 2
 
Nedap Rails Workshop
Nedap Rails WorkshopNedap Rails Workshop
Nedap Rails Workshop
 
Metaprogramming in Ruby
Metaprogramming in RubyMetaprogramming in Ruby
Metaprogramming in Ruby
 
Metaprogramming
MetaprogrammingMetaprogramming
Metaprogramming
 
Ruby objects
Ruby objectsRuby objects
Ruby objects
 

More from Smashing Boxes

Leverage IoT to Enhance Security and Improve User Experience
Leverage IoT to Enhance Security and Improve User ExperienceLeverage IoT to Enhance Security and Improve User Experience
Leverage IoT to Enhance Security and Improve User Experience
Smashing Boxes
 

More from Smashing Boxes (6)

Leverage IoT to Enhance Security and Improve User Experience
Leverage IoT to Enhance Security and Improve User ExperienceLeverage IoT to Enhance Security and Improve User Experience
Leverage IoT to Enhance Security and Improve User Experience
 
UX and Machine Learning
UX and Machine Learning UX and Machine Learning
UX and Machine Learning
 
Bourbon on a Budget with IoT - Pinetop Distillery | RIoT NC
Bourbon on a Budget with IoT - Pinetop Distillery | RIoT NCBourbon on a Budget with IoT - Pinetop Distillery | RIoT NC
Bourbon on a Budget with IoT - Pinetop Distillery | RIoT NC
 
The Future of Wearables
The Future of WearablesThe Future of Wearables
The Future of Wearables
 
Growth engineering 101: Google Analytics Essentials
Growth engineering 101: Google Analytics EssentialsGrowth engineering 101: Google Analytics Essentials
Growth engineering 101: Google Analytics Essentials
 
What is a Growth Engineer?
What is a Growth Engineer?What is a Growth Engineer?
What is a Growth Engineer?
 

Recently uploaded

Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 

Recently uploaded (20)

IESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIESVE for Early Stage Design and Planning
IESVE for Early Stage Design and Planning
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
 
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Powerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaPowerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara Laskowska
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří Karpíšek
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
ODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User GroupODC, Data Fabric and Architecture User Group
ODC, Data Fabric and Architecture User Group
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
10 Differences between Sales Cloud and CPQ, Blanka Doktorová
10 Differences between Sales Cloud and CPQ, Blanka Doktorová10 Differences between Sales Cloud and CPQ, Blanka Doktorová
10 Differences between Sales Cloud and CPQ, Blanka Doktorová
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 

The Law of Demeter

  • 1. Law of Demeter Don’t Mess With The Law ‘
  • 3. Definition 1. Each unit should have only limited knowledge about other units 2. Each unit should only talk to its friends; don't talk to strangers. 3. Only talk to your immediate friends. source: Wikipedia
  • 4. In other words An object should only invoke methods of these kind of objects: 1. itself 2. its parameters 3. any objects it creates 4. its direct component objects 5. objects of the same type*
  • 5. itself class User attr_accessor :first_name, :last_name def name "#{first_name} #{last_name}" end end
  • 7. objects it creates def total calculator = Calculator.new average + calculator.square(mean) end
  • 8. direct components def initialize() @calculator = Calculator.new end def total average + @calculator.square(mean) end
  • 9. objects of the same type* # String name.strip.gsub(/^a/,'b').constantize # ActiveRecord Relation User.where(...).order
  • 10. Violations class User belongs_to :department def division_name department.division.name end end
  • 11. Violations try().try() smells bad! class User belongs_to :department def division_name # we know the user has a department dep = department # we're assuming the department has a function called division # which returns the associated division object # we're assuming that every department belongs to a division div = dep.division # we're assuming the division has a name attribute division_name = div.name end end
  • 12. Dependency assumption ● Duplication o Once you traverse in one place you are likely to traverse in another place ● Few places understand the relationships ● Don’t create “context” ● at each step of the traversal, the value returned is decided by the object being asked
  • 13. Following the Law class User belongs_to :department def division_name # ask the department for a division name (you decide how you are going to get it!) department.try(:division_name) end end class Department belongs_to :division def division_name # ask the division for a name (you decide how you are going to get it!) division.name end end
  • 14. The rails way(™) class User belongs_to :department delegate :division_name, to: :department, allow_nil: true end class Department belongs_to :division delegate :name, to: :division, prefix: true delegate :director, to: :division end
  • 15. Testing Now we can test models independently without having to do nested stubs!
  • 16. I am the law let’s replace all . with _ ! NO… Don’t only fix the violations, look at what they are telling you. Refactor!
  • 17. Wallet example class Wallet attr_accessor :cash end class Customer has_one :wallet end class Paperboy def collect_money(customer, due_amount) if customer.wallet.cash < due_ammount raise InsufficientFundsError else customer.wallet.cash -= due_amount @collected_amount += due_amount end end end paperboy should not be taking cash out of a customer's wallet
  • 18. Delegate attributes class Customer has_one :wallet # attribute delegation def cash @wallet.cash end end class Paperboy def collect_money(customer, due_amount) if customer.cash < due_ammount raise InsufficientFundsError else customer.cash -= due_amount @collected_amount += due_amount end end end paperboy doesn’t need to know how much cash the client has in his wallet
  • 19. Delegate Behaviour class Customer has_one :wallet # behavior delegation def pay(amount) @wallet.withdraw(amount) end end class Paperboy def collect_money(customer, due_amount) @collected_amount += customer.pay(due_amount) end end Tell don’t ask
  • 20. Summary ● It’s a guideline more than a law ● Look for the spirit of the law ● try.try just smells Hint, it’s not a real gun
  • 21. Cardboard - CMS / Admin Panel https://github.com/smashingboxes/cardboard

Editor's Notes

  1. maintainable and adaptable code objects are less dependent on the internal structure of other objects object containers can be changed without reworking their callers.