SlideShare une entreprise Scribd logo
1  sur  105
Télécharger pour lire hors ligne
A Critical Look at
                             Fixtures
                               Jim Weirich
                              Chief Scientist
                              EdgeCase LLC
                               @jimweirich



Copyright 2009, Jim Weirich
   All Rights Reserved
Fixtures:
Who Likes ‘Em?
Why?
<<insert apology here>>
The Grand Unified
                     Theory of Software
                       Development
                               Jim Weirich
                              Chief Scientist
                              EdgeCase LLC
                               @jimweirich


Copyright 2009, Jim Weirich
   All Rights Reserved
GUT
Principle
a. a comprehensive and fundamental law,
   doctrine, or assumption
b.
     (1) a rule or code of conduct
     (2) habitual devotion to right principles <a
        man of principle>
c. the laws or facts of nature underlying the
   working of an artificial device
Some Principles ...
• SOLID
• Law of Demeter
• DRY
• Small Methods
• Design by Contract
1978
Coupling & Cohesion
No

           Types of
Coupling

  Data

           Coupling
Coupling

 Stamp
Coupling

 Control
Coupling

External
Coupling

Common
Coupling

Content
Coupling
No

                      Types of
  Less     Coupling

Coupling     Data

                      Coupling
 (good)    Coupling

            Stamp
           Coupling

            Control
           Coupling

           External
           Coupling

           Common
 More      Coupling
Coupling   Content
 (bad)     Coupling
No
Coupling

  Data
Coupling

 Stamp
Coupling

 Control
Coupling

External
Coupling

Common
Coupling

Content
Coupling
No
Coupling

  Data
Coupling

 Stamp
Coupling

 Control
Coupling

External
Coupling

Common
Coupling

Content
Coupling
No
Coupling




           }
  Data
Coupling
               Local Data
 Stamp
Coupling

 Control
Coupling




           }
External
Coupling

               Global Data
Common
Coupling

Content
Coupling
No
             Coupling




                        }
 Simple        Data
             Coupling
  Data
                            Local Data
              Stamp
             Coupling

              Control
             Coupling




                        }
             External
Structured   Coupling
   Data                     Global Data
             Common
             Coupling

             Content
             Coupling
No
Coupling

  Data
Coupling

 Stamp
Coupling

 Control
Coupling

External
Coupling

Common
Coupling

Content
Coupling
Control Coupling
• Method has a “flag” parameter
• The flag controls which algorithm to use
Control Coupling
 • Method has a “flag” parameter
 • The flag controls which algorithm to use
• Symptoms
 • The word “OR” in description
 • Flag value is arbitrary and not related to
    problem domain.
Control Coupling

Array.instance_methods
Control Coupling

Array.instance_methods
Array.instance_methods(true)
Array.instance_methods(false)
Control Coupling

Array.instance_methods
Array.instance_methods(true)
Array.instance_methods(false)

     ... the instance methods in mod
       are returned, otherwise the
        methods in mod and mod's
         superclasses are returned.
Control Coupling

Array.instance_methods
Array.instance_methods(true)
Array.instance_methods(false)

     ... the instance methods in mod
     are returned, otherwise the
        methods in mod and mod's
         superclasses are returned.
Another Example?
Control Coupling


Customer.find(:first, ...)
Customer.find(:all, ...)
Control Coupling
                   Returns object


Customer.find(:first, ...)
Customer.find(:all, ...)



                Returns list of objects
Myer’s Classifications
     were ‘OK’
Failed to extend
well to Objects and
Dynamic Languages
1996
Connascence

1. The common birth of two or more at the
   same tome; production of two or more
   together.
2. That which is born or produced with
   another.
3. The act of growing together.
Connascence

Two pieces of software share
connascence when a changes in
one requires a corresponding
change in the other.
CoN
class Customer
  def email
    ...
  end
end

                 def send_mail(customer)
                   customer.email
                   ...
                 end
class Customer
  def email
    ...
  end
end

                 def send_mail(customer)
                   customer.email
                   ...
                 end
Connascence of Name
class Customer
  def email
    ...
  end
end

                 def send_mail(customer)
                   customer.email
                   ...
                 end
Connascence of Name
create_table “customers” do |t|
  t.column :email, :string
  ...
end




                       def send_mail(customer)
                         customer.email
                         ...
                       end
Connascence of Name
                 Another example?
class Customer
  def email
    ...
  end
end

                 def send_mail(customer)
                   customer.email
                   ...
                 end
Connascence of Name
                 Another example?
class Customer



                 X
  def email
    ...
  end
end

                  def send_mail(customer)
                    customer.email
                    ...
                  end
Connascence of Name
                 Another example?
class Customer
  def email
    ...
  end
end

                  def send_mail(customer)
                    customer.email
                    ...
                  end
Locality Matters
Rule of Locality
  Stronger
 Connascence
                 Weaker
               Connascence
Rule of Locality

  As the distance between
software elements increases,
    use weaker forms of
       connascence.
CoP
:orders => {
                  “3” => “1”,
                  “5” => “2”
                }



Translate params hash
          to
    A List of Pairs


     [
         [ Order.find(3), true ],
         [ Order.find(5), false ],
     ]
def process_orders(list_of_pairs)
  list_of_pairs.each do |order, expedite|
    # handle an order
  end
end


 Order of the data
  within the pair
   is significant

    [
        [ Order.find(3), true ],
        [ Order.find(5), false ],
    ]
class OrdersController
  def build_order_list(params)
      [order, flag]
  end
end


       class Orders
         def process_orders(pairs)
             pairs.each do |order, flag| ... end
         end
       end
Connascence of Position
class OrdersController
  def build_order_list(params)
      [order, flag]
  end
end


       class Orders
         def process_orders(pairs)
             pairs.each do |order, flag| ... end
         end
       end
Consider
Low Degree of CoP


    [ order, expedite ]
High Degree of CoP

[
    order, expedite, confirmation_number,
    ordered_date, expiration, special
]
CoP               CoN
class OrderDisposition
  attr_reader :order,
    :expedite,
    :confirmation_number,
    :ordered_date,
    :expiration,
    :special
  ...
end
Degree Matters
CoN < CoP
Rule of Degree


Convert high degrees of connascence
                into
   weaker forms of connascence
Another Example?
Customers.find(
  [“last_name = ?”, “Weirich”], “age”)




   def find(conditions, ordered_by)
     ...
   end
Customers.find(
  [“last_name = ?”, “Weirich”], “age”,
  12, 24, [‘first_name’, ‘last_name’])




   def find(conditions, ordered_by,
   limit, offset, selected)
     ...
   end
CoP                  CoN
Customers.find(
  :conditions => [“last_name = ?”, “Weirich”],
  :order_by => “age”,
  :limit => 12,
  :offset => 24,
  :select => [‘first_name’, ‘last_name’])



      def find(options={})
        ...
      end
Another Example?
Connascence of Position

def test_user_can_do_something_interesting
  user = User.find(:first)
  ...
end
Connascence of Position

def test_user_can_do_something_interesting
  user = User.find_by_name(“Jim”)
  ...
end
CoM
<input type=quot;checkboxquot; value=quot;2quot; />
<input type=quot;checkboxquot; value=quot;1quot; />
<input type=quot;checkboxquot; value=quot;2quot; />
<input type=quot;checkboxquot; value=quot;1quot; />
<input type=quot;checkboxquot; value=quot;2quot; />
<input type=quot;checkboxquot; value=quot;1quot; />




if params[:med][id] == quot;1quot;
  mark_given(id)
elsif params[:med][id] == quot;2quot;
  mark_not_given(id)
end
Connascence of Meaning
<input type=quot;checkboxquot; value=quot;2quot; />
<input type=quot;checkboxquot; value=quot;1quot; />




if params[:med][id] == quot;1quot;
  mark_given(id)
elsif params[:med][id] == quot;2quot;
  mark_not_given(id)
end
Connascence of Meaning


MED_GIVEN = quot;1quot;
MED_NOT_GIVEN = quot;2quot;
CoM                   CoN
MED_GIVEN = quot;1quot;
MED_NOT_GIVEN = quot;2quot;



<input type=quot;checkboxquot; value=quot;<%= MED_GIVEN %>quot; />
<input type=quot;checkboxquot; value=quot;<%= MED_NOT_GIVEN %>quot; />


if params[:med][id] == MED_GIVEN
  mark_given(id)
elsif params[:med][id] == MED_NOT_GIVEN
  mark_not_given(id)
end
CoM                   CoN
MED_GIVEN = “1”
MED_NOT_GIVEN = “2”



<input type=quot;checkboxquot; value=quot;<%= MED_GIVEN %>quot; />
<input type=quot;checkboxquot; value=quot;<%= MED_NOT_GIVEN %>quot; />


if params[:med][id] == MED_GIVEN
  mark_given(id)
elsif params[:med][id] == MED_NOT_GIVEN
  mark_not_given(id)
end
CN
Revisit

MED_GIVEN = quot;1quot;

MED_NOT_GIVEN = quot;2quot;
MED_GIVEN = quot;1quot;

MED_NOT_GIVEN = quot;2quot;
X
MED_GIVEN = quot;1quot;

MED_NOT_GIVEN = quot;1quot;
Contranascence




      X
MED_GIVEN = quot;1quot;

MED_NOT_GIVEN = quot;1quot;
Another Example?
Contranascence

My XML Library

class Node
  ...
end
Contranascence

My XML Library   Your Graphing Library

class Node         class Node
  ...                ...
end                end
Contranascence

My XML Library   Your Graphing Library

class Node         class Node
  ...                ...
end                end
Contranascence

My XML Library   Your Graphing Library

module MyXml     module YourGraphing
  class Node       class Node
    ...              ...
  end              end
end              end
Contranascence

irb/slex.rb:92:                 class   Node
tkextlib/blt/tree.rb:15:        class   Node   <   TkObject
tkextlib/blt/treeview.rb:18:    class   Node   <   TkObject
tkextlib/blt/treeview.rb:966:   class   Node   <   TkObject
tkextlib/bwidget/tree.rb:13:    class   Node   <   TkObject
tkextlib/bwidget/tree.rb:262:   class   Node
xmlrpc/parser.rb:17:            class   Node
yaml/syck.rb:14:                class   Node
Another Example?
Contranascence

My XML Library   Your Graphing Library

module Kernel      module Kernel
  def to_node        def to_node
    ...                ...
  end                end
end                end
Contranascence




          X
My XML Library   Your Graphing Library

module Kernel      module Kernel
  def to_node        def to_node
    ...                ...
  end                end
end                end
Contranascence

Selector Namespaces
      (Ruby 2 ?)
CoA
add_check_digit(“31415972”)     “314159728”




         check?(“ 314159728”)     true

         check?(“ 314159723”)     false
def add_check_digit(digits)
  check_sum = digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
  digits + ((10 - check_sum) % 10).to_s
end



def check?(digits)
  check_sum = digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
  check_sum == 0
end
def add_check_digit(digits)
  check_sum = digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
  digits + ((10 - check_sum) % 10).to_s
end



def check?(digits)
  check_sum = digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
  check_sum == 0
end
Connascence of Algorithm
def add_check_digit(digits)
  check_sum = digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
  digits + ((10 - check_sum) % 10).to_s
end



def check?(digits)
  check_sum = digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
  check_sum == 0
end
CoA                 CoN
def add_check_digit(digits)
  digits + ((10 - check_sum(digits)) % 10).to_s
end

def check?(digits)
  check_sum(digits) == 0
end

def check_sum(digits)
  check_sum = digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
end
DRY
def add_check_digit(digits)
  digits + ((10 - check_sum(digits)) % 10).to_s
end

def check?(digits)
  check_sum(digits) == 0
end

def check_sum(digits)
  digits.split(//).
    inject(0) { |r, n| r + n.to_i } % 10
end
So, Back to Fixtures
jim:
  id: 1
  name: Jim
  password_hash: jwSamN1gljMBA
  role_id: 2


admin:
  id: 1
  name: admin
worker:
  id: 2
  name: worker
Eliminate IDs
                 (CoP => CoN)

jim:
  name: Jim
  password_hash: jwSamN1gljMBA
  role: admin


admin:
  name: admin
worker:
  name: worker
Eliminate Literals
                 (CoA => CoN)

jim:
  name: Jim
  password_hash: <%=“password”.crypt(“jw”)%>
  role: admin


admin:
  name: admin
worker:
  name: worker
What Else?
adam:
  role: worker
bill:
  role: worker




def test_finder
  workers = User.find_all_workers
  assert_equal 2, workers.size
end
adam:
  role: worker
bill:
  role: worker
carl:
  worker: worker


def test_finder
  workers = User.find_all_workers
  assert_equal 2, workers.size
end
Rule of Locality
adam:
  role: worker
bill:
  role: worker
carl:
  worker: worker


def test_finder
  workers = User.find_all_workers
  assert_equal 2, workers.size
end
Solution?
Lots!

• Fixture Scenarios
• Factory Girl
• Foundry (Jeremy McAnally)
• Roll Your Own
Summary
Connascence
•                                       •
    Static                                  Dynamic
    •                                       •
       Connascence of Name                    Connascence of Execution
    •                                       •
       Connascence of Type                    Connascence of Timing
    •                                       •
       Connascence of Meaning                 Connascence of Value
    •                                       •
       Connascence of Algorithm               Connascence of Identity
    •                                   •
       Connascence of Position              Contranascence




                             Rules
                         •   Rule of Locality
                         •   Rule of Degree
References
•   What Every Programmer Should Know About Object Oriented
    Design, Meilir Page-Jones
•   Fundamentals of Object-Oriented Design in UML, Meilir
    Page-Jones
•   Composite/Structured Design, Glenford Myers
•   Reliable Software Through Composite Design, Glenford
    Myers
•   Agile Software Development, Principles, Patterns, and
    Practices, Robert Martin
•   Object-Oriented Software Construction, Bertrand Meyer
•   The Pragmatic Programmer: From Journeyman to Master,
    Andy Hunt & Dave Thomas
Thank You!
git://github.com/jimweirich/presentation_connascence.git


              Copyright 2009 by Jim Weirich, Some Rights Reserved

Contenu connexe

Similaire à A Critical Look at Fixtures

Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Victor Rentea
 
A Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpA Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented Php
Michael Girouard
 
Declarative Multilingual Information Extraction with SystemT
Declarative Multilingual Information Extraction with SystemTDeclarative Multilingual Information Extraction with SystemT
Declarative Multilingual Information Extraction with SystemT
Laura Chiticariu
 

Similaire à A Critical Look at Fixtures (20)

Clean Code 2
Clean Code 2Clean Code 2
Clean Code 2
 
Angular JS2 Training Session #1
Angular JS2 Training Session #1Angular JS2 Training Session #1
Angular JS2 Training Session #1
 
DataMapper
DataMapperDataMapper
DataMapper
 
Os Harris
Os HarrisOs Harris
Os Harris
 
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
Evolving a Clean, Pragmatic Architecture at JBCNConf 2019
 
Tips And Tricks For Bioinformatics Software Engineering
Tips And Tricks For Bioinformatics Software EngineeringTips And Tricks For Bioinformatics Software Engineering
Tips And Tricks For Bioinformatics Software Engineering
 
2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop2011-02-03 LA RubyConf Rails3 TDD Workshop
2011-02-03 LA RubyConf Rails3 TDD Workshop
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
A Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented PhpA Gentle Introduction To Object Oriented Php
A Gentle Introduction To Object Oriented Php
 
Automated Frontend Testing
Automated Frontend TestingAutomated Frontend Testing
Automated Frontend Testing
 
Declarative Multilingual Information Extraction with SystemT
Declarative Multilingual Information Extraction with SystemTDeclarative Multilingual Information Extraction with SystemT
Declarative Multilingual Information Extraction with SystemT
 
Things to consider for testable Code
Things to consider for testable CodeThings to consider for testable Code
Things to consider for testable Code
 
Tales About Scala Performance
Tales About Scala PerformanceTales About Scala Performance
Tales About Scala Performance
 
Groovy Architectural Flexibility
Groovy Architectural FlexibilityGroovy Architectural Flexibility
Groovy Architectural Flexibility
 
Practical Groovy DSL
Practical Groovy DSLPractical Groovy DSL
Practical Groovy DSL
 
Data Binding in qooxdoo
Data Binding in qooxdooData Binding in qooxdoo
Data Binding in qooxdoo
 
Dsl
DslDsl
Dsl
 
Testing survival Guide
Testing survival GuideTesting survival Guide
Testing survival Guide
 
An in-depth look at jQuery
An in-depth look at jQueryAn in-depth look at jQuery
An in-depth look at jQuery
 
Code Quality Practice and Tools
Code Quality Practice and ToolsCode Quality Practice and Tools
Code Quality Practice and Tools
 

Dernier

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Dernier (20)

Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 

A Critical Look at Fixtures