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

PDF
Ruby Classes
PDF
Advanced CPP Lecture 1- Summer School 2014 - ACA CSE IITK
PDF
Advanced CPP Lecture 2- Summer School 2014 - ACA CSE IITK
PPT
string tokenization
DOC
Serialization Surrogates
PDF
Law of Demeter & Objective Sense of Style
PPTX
Software design principles
DOCX
Python Metaclasses
Ruby Classes
Advanced CPP Lecture 1- Summer School 2014 - ACA CSE IITK
Advanced CPP Lecture 2- Summer School 2014 - ACA CSE IITK
string tokenization
Serialization Surrogates
Law of Demeter & Objective Sense of Style
Software design principles
Python Metaclasses

Similar to The Law of Demeter (20)

PDF
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
PDF
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
PDF
Object Trampoline: Why having not the object you want is what you need.
PDF
TDC2016POA | Trilha Ruby - Melhorando seu código com Law of Demeter e Tell do...
PDF
Melhorando seu código com Law of Demeter e Tell don't ask
PPT
Chap 3 Python Object Oriented Programming - Copy.ppt
PPT
C++ Interview Questions
PPTX
Advanced Object-Oriented/SOLID Principles
KEY
Intro to Ruby - Twin Cities Code Camp 7
PPT
what is class in C++ and classes_objects.ppt
PPTX
Python Basic for Data science enthusiast
PPTX
About Python
PPT
Lesson on Python Classes by Matt Wufus 2003
KEY
Uses & Abuses of Mocks & Stubs
PPT
Working Effectively With Legacy Code
PDF
S12.s01 - Material TP.pdf
PDF
Values
PDF
OOPs theory about its concepts and properties.
PDF
Learning puppet chapter 2
جلسه هفتم پایتون برای هکر های قانونی دوره مقدماتی پاییز ۹۲
اسلاید جلسه ۹ کلاس پایتون برای هکر های قانونی
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...
Melhorando seu código com Law of Demeter e Tell don't ask
Chap 3 Python Object Oriented Programming - Copy.ppt
C++ Interview Questions
Advanced Object-Oriented/SOLID Principles
Intro to Ruby - Twin Cities Code Camp 7
what is class in C++ and classes_objects.ppt
Python Basic for Data science enthusiast
About Python
Lesson on Python Classes by Matt Wufus 2003
Uses & Abuses of Mocks & Stubs
Working Effectively With Legacy Code
S12.s01 - Material TP.pdf
Values
OOPs theory about its concepts and properties.
Learning puppet chapter 2
Ad

More from Smashing Boxes (6)

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

Recently uploaded (20)

PDF
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
PPTX
Microsoft User Copilot Training Slide Deck
PPTX
Module 1 Introduction to Web Programming .pptx
PDF
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
PDF
Electrocardiogram sequences data analytics and classification using unsupervi...
PDF
Enhancing plagiarism detection using data pre-processing and machine learning...
PPTX
Internet of Everything -Basic concepts details
PDF
Co-training pseudo-labeling for text classification with support vector machi...
PDF
A hybrid framework for wild animal classification using fine-tuned DenseNet12...
PDF
EIS-Webinar-Regulated-Industries-2025-08.pdf
PDF
Dell Pro Micro: Speed customer interactions, patient processing, and learning...
PPTX
MuleSoft-Compete-Deck for midddleware integrations
PDF
Early detection and classification of bone marrow changes in lumbar vertebrae...
PDF
“The Future of Visual AI: Efficient Multimodal Intelligence,” a Keynote Prese...
PDF
Improvisation in detection of pomegranate leaf disease using transfer learni...
PDF
Transform-Your-Supply-Chain-with-AI-Driven-Quality-Engineering.pdf
PDF
Data Virtualization in Action: Scaling APIs and Apps with FME
PDF
Introduction to MCP and A2A Protocols: Enabling Agent Communication
PDF
A symptom-driven medical diagnosis support model based on machine learning te...
PPTX
agenticai-neweraofintelligence-250529192801-1b5e6870.pptx
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
Microsoft User Copilot Training Slide Deck
Module 1 Introduction to Web Programming .pptx
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
Electrocardiogram sequences data analytics and classification using unsupervi...
Enhancing plagiarism detection using data pre-processing and machine learning...
Internet of Everything -Basic concepts details
Co-training pseudo-labeling for text classification with support vector machi...
A hybrid framework for wild animal classification using fine-tuned DenseNet12...
EIS-Webinar-Regulated-Industries-2025-08.pdf
Dell Pro Micro: Speed customer interactions, patient processing, and learning...
MuleSoft-Compete-Deck for midddleware integrations
Early detection and classification of bone marrow changes in lumbar vertebrae...
“The Future of Visual AI: Efficient Multimodal Intelligence,” a Keynote Prese...
Improvisation in detection of pomegranate leaf disease using transfer learni...
Transform-Your-Supply-Chain-with-AI-Driven-Quality-Engineering.pdf
Data Virtualization in Action: Scaling APIs and Apps with FME
Introduction to MCP and A2A Protocols: Enabling Agent Communication
A symptom-driven medical diagnosis support model based on machine learning te...
agenticai-neweraofintelligence-250529192801-1b5e6870.pptx

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

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