Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Math Every Programmer Needs

The Math Every Programmer Needs

This talk was given at RailsConf 2023

Leave your fear of math behind along with the equations and symbols, we're headed to Ruby-land! On this whirlwind tour, we’ll explore how to write better conditionals with Boolean algebra, figure out how many test cases we need with combinatorics, a mental model for breaking down large tasks with graph theory, and more.

You’ll leave this talk equipped to better do your job with some ideas, techniques, and mental models from the wonderfully practical world of discrete math.

Joël Quenneville

April 24, 2023
Tweet

More Decks by Joël Quenneville

Other Decks in Technology

Transcript

  1. The Math Every
    Programmer Needs

    View Slide

  2. You must be
    really good
    at math!

    View Slide

  3. Not "good at math"

    Joël Quenneville @joelquen Principal developer at
    thoughtbot

    View Slide

  4. I mostly use basic arithmetic

    View Slide

  5. What is the most
    useful CS class
    for the working
    Rails developer?

    View Slide

  6. Not Data
    Structures and
    Algorithms

    View Slide

  7. Discrete Math

    I use this daily

    View Slide

  8. Discrete Math

    Propositional Logic
    Boolean Algebra
    Graph Theory
    Set Theory

    Combinatorics Probability Predicate Logic

    View Slide

  9. Practical
    problems

    not theory

    View Slide

  10. BOOLEAN ALGEBRA

    Unnecessary Conditionals

    View Slide

  11. View Slide

  12. def can_edit?
    if admin?
    true
    else
    false
    end
    end
    Written code like this

    View Slide

  13. def can_edit?
    admin?
    end
    Can be simplified to this

    View Slide

  14. LESSON FROM BOOLEAN ALGEBRA

    Operators

    View Slide

  15. Boolean operators

    identity (admin?)

    negation (!admin?)

    and (admin? && moderator?)

    or (admin? || moderator?)

    View Slide

  16. admin?
    Identity

    View Slide

  17. if admin?
    false
    else
    true
    end
    Negation

    View Slide

  18. !admin?
    Negation

    View Slide

  19. def can_edit_admin_post?
    return owner? unless admin?
    true
    end
    Two variables

    View Slide

  20. def can_edit_admin_post?
    owner? || admin?
    end
    Two variables

    View Slide

  21. Use operators!

    View Slide

  22. PROPOSITIONAL LOGIC

    Difficult code review

    View Slide

  23. def can_edit_admin_post?
    return owner? unless admin?
    true
    end
    Complex condition

    View Slide

  24. View Slide

  25. TOOL FROM PROPOSITIONAL LOGIC

    Truth Table

    View Slide

  26. Truth Table

    owner? admin? can_edit_admin_post?
    true true true
    true false true
    false true true
    false false false

    View Slide

  27. Two expressions are equal
    if their truth tables match

    View Slide

  28. Truth Table

    owner? admin? can_edit_admin_post?
    true true true
    true false true
    false true true
    false false false
    owner? || admin?
    true
    true
    true
    false

    View Slide

  29. Use truth tables in GitHub comments

    View Slide

  30. Use truth tables in GitHub comments

    View Slide

  31. Understand

    View Slide

  32. Improve
    communication

    View Slide

  33. BOOLEAN ALGEBRA

    Broken Authorization Logic

    View Slide

  34. Forbid signed out users
    and untrusted IPs

    View Slide

  35. def allow_access_to_site?
    !(signed_out? && untrusted_ip?)
    end
    Confusing negated code

    View Slide

  36. def allow_access_to_site?
    !signed_out? && !untrusted_ip?
    end
    Individual negation: cleaner?

    View Slide

  37. Broken

    View Slide

  38. Expected behavior

    signed_out? untrusted_ip?
    Correct
    true true false
    true false true
    false true true
    false false
    true

    View Slide

  39. Individual negation
    signed_out? untrusted_ip?
    Correct
    true true false
    true false true
    false true true
    false false
    true
    individual negation
    false
    false
    false
    true

    View Slide

  40. LESSON FROM BOOLEAN ALGEBRA

    DeMorgan's laws

    View Slide

  41. DeMorgan's laws

    To negate compound conditions
    Negate each clause

    Invert operator

    1
    2

    View Slide

  42. DeMorgan's laws

    To negate compound conditions
    !(a && b) == !a || !b

    !(a || b) == !a && !b

    1
    2

    View Slide

  43. def allow_access_to_site?
    !(signed_out? && untrusted_ip?)
    end
    Applying DeMorgan: Original

    View Slide

  44. def allow_access_to_site?
    !signed_out? && !untrusted_ip?
    end
    Applying DeMorgan: Step 1

    NEGATE INDIVIDUAL CLAUSES

    View Slide

  45. def allow_access_to_site?
    !signed_out? || !untrusted_ip?
    end
    Applying DeMorgan: Step 2

    INVERT OPERATOR

    View Slide

  46. DeMorgan

    signed_out? untrusted_ip?
    Correct
    true true false
    true false true
    false true true
    false false
    true
    DeMorgan
    false
    true
    true
    true

    View Slide

  47. def allow_access_to_site?
    !signed_out? || !untrusted_ip?
    end
    DeMorganized code

    View Slide

  48. def allow_access_to_site?
    signed_in? || trusted_ip?
    end
    Alias methods

    View Slide

  49. Make code more
    readable

    View Slide

  50. Catch bugs

    View Slide

  51. unless signed_out? && untrusted_ip?
    render :not_authorized
    end
    Unless is also negation

    View Slide

  52. COMBINATORICS
    How many test
    cases do I need?

    View Slide

  53. def can_read?
    article.access_policy&.public? || user.admin?
    end
    Policy Object

    View Slide

  54. describe "#can_read?" do
    it "allows admin to access public article"
    it "allows admin to access private article"
    it "allows non-admin to access public article"
    it "disallows non-admin from accessing private
    article"
    end
    Enough tests?

    View Slide

  55. 2 inputs

    User is admin?

    Article is public?

    1
    2

    View Slide

  56. 2 states

    user.admin?
    true

    false

    1
    2

    View Slide

  57. 3 States

    article.access_policy&.public?
    true

    false
    nil
    1
    2
    3

    View Slide

  58. LESSON FROM COMBINATORICS

    Compound
    states multiply

    View Slide

  59. 2 states x 3 states = 6 states

    View Slide

  60. Modified truth table

    Article is public? User is admin? Can read?
    true true true
    true false true
    false true true
    false false false
    nil true true
    nil false false

    View Slide

  61. class ArticleQuery
    def initialize(limit: nil, scope: Article.all)
    # ...
    end
    end
    Default parameters

    View Slide

  62. Optional params add 2
    states to your signature

    View Slide

  63. 2 states x 2 states = 4 states

    View Slide

  64. Ways of calling constructor

    new
    new(limit: 10)

    new(scope: Article.published)

    new(limit: 10, scope:
    Article.published)

    1
    2
    3
    4

    View Slide

  65. TOOL FROM SET THEORY
    Venn diagrams

    View Slide

  66. Set of tests is smaller than set of states

    Tests
    States

    View Slide

  67. Grow set of tests

    Tests
    States

    View Slide

  68. Shrink set of states

    Tests
    States

    View Slide

  69. Solution: Add more tests
    or reduce your states

    View Slide

  70. GRAPH THEORY
    Which RSpec let blocks
    actually get invoked?

    View Slide

  71. describe User do
    let(:organization) { create(:organization) }
    let(:user) { create(:user, organization: organization) }
    let!(:admin) { create(:user, admin: true, organization: organization) }
    # lots of other tests
    describe "Invoices" do
    let(:product) { create(:product) }
    let(:invoice) { create(:invoice, owner: user, items: [product] }
    it "is complete" do
    expect(invoice).to be_complete
    end
    it "is an active product" do
    expect(product).to be_active
    end
    end
    end

    View Slide

  72. Visual Model
    that I like

    View Slide

  73. List lets

    organization user admin product invoice

    View Slide

  74. Connect boxes

    organization
    user admin product
    invoice

    View Slide

  75. Dependency Graph

    Terminology

    View Slide

  76. Mark let!

    organization
    user admin product
    invoice

    View Slide

  77. LESSON FROM GRAPH THEORY
    Evaluating a node
    also requires
    evaluating all
    downstream
    nodes

    View Slide

  78. Follow dependencies

    organization
    user admin product
    invoice

    View Slide

  79. Basic State

    All tests start with this

    View Slide

  80. it "is complete" do
    expect(invoice).to be_complete
    end

    View Slide

  81. Mark items referenced in test

    organization
    user admin product
    invoice

    View Slide

  82. Follow dependencies

    organization
    user admin product
    invoice

    View Slide

  83. it "is an active product" do
    expect(product).to be_active
    end

    View Slide

  84. Mark items referenced in test

    organization
    user admin product
    invoice

    View Slide

  85. GRAPH THEORY
    Working incrementally

    View Slide

  86. Linear list

    Step1
    Step 2

    Step 3

    Step 4

    Step 5

    View Slide

  87. Actual dependencies
    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  88. Actual dependencies
    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  89. LESSON FROM GRAPH THEORY
    Evaluating a node
    also requires
    evaluating all
    downstream
    nodes

    View Slide

  90. Actual dependencies
    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  91. Doing tasks with no dependencies

    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  92. Doing tasks with no dependencies
    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  93. Doing tasks with no dependencies
    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  94. Doing tasks with no dependencies
    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  95. Doing tasks with no dependencies
    Step 1
    Step2 Step 3
    Step 4
    Step 5

    View Slide

  96. LESSON FROM GRAPH THEORY
    Dependency
    graphs must
    be evaluated
    bottom-up

    View Slide

  97. Topological Sort

    Terminology

    View Slide

  98. Replace image processing gem

    Change the
    Gemfile
    Update User
    model
    Update Article model

    View Slide

  99. Replace image processing gem

    Change image
    processing gem
    Update User
    model
    Update Article model

    View Slide

  100. Cycles
    Change image
    processing gem
    Update User
    model
    Update Article model

    View Slide

  101. LESSON FROM GRAPH THEORY
    Cycles cannot
    be evaluated
    incrementally

    View Slide

  102. Breaking Cycles
    Change image
    processing gem
    Update User
    model
    Introduce
    adapter
    Update Article model

    View Slide

  103. Directed Acyclic
    Graph (DAG)

    Terminology

    View Slide

  104. Strangler
    Fig Pattern

    View Slide

  105. COMBINATORICS

    What are the risks
    of a collision?

    View Slide

  106. SET THEORY, COMBINATORICS

    Designing a DB schema

    View Slide

  107. PREDICATE LOGIC
    Why do all? and any? behave
    like that on an empty array?

    View Slide

  108. PREDICATE LOGIC, SET THEORY

    Improve your
    communication

    View Slide

  109. Ideas from Discrete Math

    Break cycles in your dependency
    graphs
    Compound states multiply
    DeMorgan laws
    Truth tables
    Use Boolean operators
    Evaluate dependency graph bottom-
    up
    Evaluating a graph node requires
    evaluating downstream nodes

    View Slide

  110. Not "good at math"

    Joël Quenneville @joelquen Principal developer at
    thoughtbot

    View Slide