SlideShare una empresa de Scribd logo
1 de 26
Descargar para leer sin conexión
Managing Complexity
                                Sam Goldman
                              @nontrivialzeros
                          github.com/samwgoldman




Monday, December 17, 12
What is Complexity?
                   • Lines of code?
                   • Duplication?
                   • Coupling?
                   • LOC/Method?
                   • # Methods/Class?
                   • # Features?
Monday, December 17, 12
Noticing Complexity
                   • Feature development costs increase
                   • Bugs increase superlinearly with code size
                   • “Boring bugs” keep happening
                   • New dev onboarding takes weeks
                   • Local changes have unexpected, non-local
                          effects


Monday, December 17, 12
Reasoning about
                            Complexity
                   • How can you compare two solutions?
                   • Lots of guidelines, e.g., SOLID
                   • Lots of cargo culting
                   • We need to do better than a gut check
                   • Patterns are still good

Monday, December 17, 12
Factorization
                   • Large numbers factorized by primes
                    • 288 = 2 × 2 × 2 × 2 × 2 × 3 × 3
                   • Some large numbers can’t be factorized
                    • 195845982777569926302400511
                   • Fundamental theorem of arithmetic
                   • No efficient algorithm
Monday, December 17, 12
Probabilistic Factors

                   • Take binary random variables A, B, and C
                   • P(A) has two possible configurations
                   • P(A, B) has 4
                   • P(A, B, C) has 8
                   • Joint configurations grow exponentially

Monday, December 17, 12
Probabilistic Factors

                   • Distributions factorized by independence
                   • P(A, B) = P(A)P(B) if A, B are independent
                   • Let A and B each have 100 discrete values
                    • Not independent: 10000 configurations
                    • Independent: 200 configurations

Monday, December 17, 12
Probabilistic Factors




Monday, December 17, 12
OOP

                   • Software is factorized by encapsulation
                   • Controlling dependencies is key
                   • Conversely: Discover independencies


Monday, December 17, 12
Tell, Don’t Ask

                   • Depending on collaborators’ states breaks
                          encapsulation
                   • Depend on behaviors, not state
                   • Law of Demeter


Monday, December 17, 12
Asking
   Questionnaire = Struct.new(:questions) do
     def render(html)
       html.form
         questions.each do |question|
           html.fieldset {
             case question
             when ShortAnswerQuestion
               html.label(:for => question.id) { html.text question.prompt }
               html.input(:type => "text", :id => question.id, :name => question.id)
             when MultipleChoiceQuestion
               html.label { html.text question.prompt }
               html.ul {
                 question.choices.each do |choice|
                   html.li {
                      html.label(:for => choice.id) { html.text choice.title }
                      html.input(:type => "radio", :id => choice.id, :name => choice.id)
                   }
                 end
               }
             end
           }
         end
       end
     end
   end


Monday, December 17, 12
Telling

                          Questionnaire = Struct.new(:questions) do
                            def render(html)
                              html.form do
                                questions.each do |question|
                                  html.fieldset { question.render(html) }
                                end
                              end
                            end
                          end




Monday, December 17, 12
Telling
                          ShortAnswerQuestion = Struct.new(:id, :prompt) do
                            def render(html)
                              html.label(:for => id) { html.text prompt }
                              html.input(:type => "text", :id => id, :name => id)
                            end
                          end

                          MultipleChoiceQuestion = Struct.new(:id, :prompt, :choices) do
                            def render(html)
                              html.label { html.text prompt }
                              html.ul {
                                choices.each do |choice|
                                  html.li { choice.render(html) }
                                end
                              }
                            end
                          end

                          Choice = Struct.new(:id, :title) do
                            def render(html)
                              html.label(:for => id) { html.text title }
                              html.input(:type => "radio", :id => id, :name => id)
                            end
                          end



Monday, December 17, 12
Mocks

                   • How can we write assertions when objects
                          hide their internal state?
                   • We need to assert that objects are sending
                          the right messages to one another




Monday, December 17, 12
Mocks

                          describe Questionnaire do
                            it "renders every question" do
                              question1 = mock
                              question2 = mock
                              questionnaire = Questionnaire.new([question1, question2])
                              builder = stub

                              question1.should_receive(:render).with(builder).ordered
                              question2.should_receive(:render).with(builder).ordered

                              questionnaire.render(builder)
                            end
                          end




Monday, December 17, 12
Mocks Aren’t Stubs
                          describe ArrearsReport do
                            it "displays customers who owe money" do
                              report = ArrearsReport.new

                              foo_customer = stub(:in_arrears? => true)
                              bar_customer = stub(:in_arrears? => false)

                              result = report.run([foo_customer, bar_customer])
                              result.should eq([foo_customer])
                            end
                          end
                          describe Questionnaire do
                            it "renders every question" do
                              question1 = mock
                              question2 = mock
                              questionnaire = Questionnaire.new([question1, question2])
                              builder = stub

                              question1.should_receive(:render).with(builder).ordered
                              question2.should_receive(:render).with(builder).ordered

                              questionnaire.render(builder)
                            end
                          end


Monday, December 17, 12
Mocks Aren’t Stubs
                          describe ArrearsReport do
                            it "displays customers who owe money" do
                              report = ArrearsReport.new

                              foo_customer = stub(:in_arrears? => true)
                                            Stub Queries
                              bar_customer = stub(:in_arrears? => false)

                              result = report.run([foo_customer, bar_customer])
                              result.should eq([foo_customer])
                            end
                          end
                          describe Questionnaire do
                            it "renders every question" do
                              question1 = mock
                              question2 = mock
                              questionnaire = Questionnaire.new([question1, question2])
                              builder = stub
                                            Mock Actions
                              question1.should_receive(:render).with(builder).ordered
                              question2.should_receive(:render).with(builder).ordered

                              questionnaire.render(builder)
                            end
                          end


Monday, December 17, 12
Values

                   • SmartLogic’s Nerdword project
                   • Services: Player, Pouch, Board
                   • Values: Move, Direction, Position


Monday, December 17, 12
Values

                          module Direction
                            HORIZONTAL = "Horizontal".freeze
                            VERTICAL = "Vertical".freeze

                            def self.opposite(direction)
                              if direction == HORIZONTAL
                                VERTICAL
                              else
                                HORIZONTAL
                              end
                            end
                          end




Monday, December 17, 12
Values
                          Position = Struct.new(:col, :row) do
                            def shift(offset, direction)
                              if direction == Direction::HORIZONTAL
                                Position.new(col + offset, row)
                              else
                                Position.new(col, row + offset)
                              end
                            end

                           def previous(direction)
                             shift(-1, direction)
                           end

                            def next(direction)
                              shift(1, direction)
                            end
                          end




Monday, December 17, 12
Values

                          Move = Struct.new(:word, :position, :direction) do
                            def each_position
                              word.length.times do |i|
                                yield position.shift(i, direction)
                              end
                            end
                          end




Monday, December 17, 12
Values

                   • We happily depend on Array, Date, String...
                   • Create values in your domain
                   • Separate services from values
                   • Better messages, better factors
                   • Don’t stub values

Monday, December 17, 12
Abstractions
                   • RemoteFile, not S3
                   • PaymentProcessor, not Braintree
                   • Wrap services around 3rd party code
                   • “Ports and Adapters”
                   • Write integrated tests for wrapper services
                   • “Test double” wrapper services elsewhere
                   • ActiveRecord?
Monday, December 17, 12
Acceptance Tests
                   • “How does the client know it works?”
                   • Write acceptance tests your client would
                          understand
                   • Write acceptance tests your client would
                          want to read
                   • Write as few acceptance tests as possible

Monday, December 17, 12
Integration Tests

                   • “How do we know if it works?”
                   • Ports and Adapters is a good factorization
                   • Write as few integration tests as you need
                   • You don’t need as many as you think

Monday, December 17, 12
Thank you

                               @smartlogic
                          facebook.com/smartlogic
                           github.com/smartlogic




Monday, December 17, 12

Más contenido relacionado

La actualidad más candente

Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)lennartkats
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Eelco Visser
 
Heroku Postgres SQL Tips, Tricks, Hacks
Heroku Postgres SQL Tips, Tricks, HacksHeroku Postgres SQL Tips, Tricks, Hacks
Heroku Postgres SQL Tips, Tricks, HacksSalesforce Developers
 
Building High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 FirestarterBuilding High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 FirestarterMithun T. Dhar
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of CompositionScott Wlaschin
 
02 JavaScript Syntax
02 JavaScript Syntax02 JavaScript Syntax
02 JavaScript SyntaxYnon Perek
 
03 Advanced JavaScript
03 Advanced JavaScript03 Advanced JavaScript
03 Advanced JavaScriptYnon Perek
 
Ceylon - the language and its tools
Ceylon - the language and its toolsCeylon - the language and its tools
Ceylon - the language and its toolsMax Andersen
 
DevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a DatastoreDevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a DatastoreXavier Coulon
 
A Critical Look at Fixtures
A Critical Look at FixturesA Critical Look at Fixtures
A Critical Look at FixturesActsAsCon
 

La actualidad más candente (15)

Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
 
Heroku Postgres SQL Tips, Tricks, Hacks
Heroku Postgres SQL Tips, Tricks, HacksHeroku Postgres SQL Tips, Tricks, Hacks
Heroku Postgres SQL Tips, Tricks, Hacks
 
Building High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 FirestarterBuilding High Perf Web Apps - IE8 Firestarter
Building High Perf Web Apps - IE8 Firestarter
 
Intermediate JavaScript
Intermediate JavaScriptIntermediate JavaScript
Intermediate JavaScript
 
SOLID Ruby SOLID Rails
SOLID Ruby SOLID RailsSOLID Ruby SOLID Rails
SOLID Ruby SOLID Rails
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
 
Ruby struct
Ruby structRuby struct
Ruby struct
 
02 JavaScript Syntax
02 JavaScript Syntax02 JavaScript Syntax
02 JavaScript Syntax
 
OO in JavaScript
OO in JavaScriptOO in JavaScript
OO in JavaScript
 
03 Advanced JavaScript
03 Advanced JavaScript03 Advanced JavaScript
03 Advanced JavaScript
 
Values
ValuesValues
Values
 
Ceylon - the language and its tools
Ceylon - the language and its toolsCeylon - the language and its tools
Ceylon - the language and its tools
 
DevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a DatastoreDevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a Datastore
 
A Critical Look at Fixtures
A Critical Look at FixturesA Critical Look at Fixtures
A Critical Look at Fixtures
 

Destacado

SmartLogic Webinar - Arnold_Duckworth - OCT14
SmartLogic Webinar - Arnold_Duckworth - OCT14SmartLogic Webinar - Arnold_Duckworth - OCT14
SmartLogic Webinar - Arnold_Duckworth - OCT14Adam Duckworth
 
Beyond Big Data
Beyond Big DataBeyond Big Data
Beyond Big DataSmartlogic
 
Keep the Complexity. Simplify with SKOS
Keep the Complexity. Simplify with SKOSKeep the Complexity. Simplify with SKOS
Keep the Complexity. Simplify with SKOSJames R. Morris
 
You're Having a Laugh
You're Having  a LaughYou're Having  a Laugh
You're Having a LaughJames Thomas
 
Beyond Big Data: Mining Content for Business Value in Healthcare
Beyond Big Data: Mining Content for Business Value in HealthcareBeyond Big Data: Mining Content for Business Value in Healthcare
Beyond Big Data: Mining Content for Business Value in HealthcareDATA360US
 
Managing Complexity and Change with Scalable Software Design
Managing Complexity and Change with Scalable Software DesignManaging Complexity and Change with Scalable Software Design
Managing Complexity and Change with Scalable Software Designlbergmans
 

Destacado (6)

SmartLogic Webinar - Arnold_Duckworth - OCT14
SmartLogic Webinar - Arnold_Duckworth - OCT14SmartLogic Webinar - Arnold_Duckworth - OCT14
SmartLogic Webinar - Arnold_Duckworth - OCT14
 
Beyond Big Data
Beyond Big DataBeyond Big Data
Beyond Big Data
 
Keep the Complexity. Simplify with SKOS
Keep the Complexity. Simplify with SKOSKeep the Complexity. Simplify with SKOS
Keep the Complexity. Simplify with SKOS
 
You're Having a Laugh
You're Having  a LaughYou're Having  a Laugh
You're Having a Laugh
 
Beyond Big Data: Mining Content for Business Value in Healthcare
Beyond Big Data: Mining Content for Business Value in HealthcareBeyond Big Data: Mining Content for Business Value in Healthcare
Beyond Big Data: Mining Content for Business Value in Healthcare
 
Managing Complexity and Change with Scalable Software Design
Managing Complexity and Change with Scalable Software DesignManaging Complexity and Change with Scalable Software Design
Managing Complexity and Change with Scalable Software Design
 

Similar a Managing complexity

MongoSV Schema Workshop
MongoSV Schema WorkshopMongoSV Schema Workshop
MongoSV Schema WorkshopMongoDB
 
Domain Primitives In Action - Explore DDD 2017
Domain Primitives In Action - Explore DDD 2017Domain Primitives In Action - Explore DDD 2017
Domain Primitives In Action - Explore DDD 2017Omegapoint Academy
 
MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011Steven Francia
 
Webinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in DocumentsWebinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in DocumentsMongoDB
 
Why certain code is hard to test?
Why certain code is hard to test?Why certain code is hard to test?
Why certain code is hard to test?Kosala Nuwan Perera
 
Indexing thousands of writes per second with redis
Indexing thousands of writes per second with redisIndexing thousands of writes per second with redis
Indexing thousands of writes per second with redispauldix
 
MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011Steven Francia
 
Day 3 distributive property
Day 3 distributive propertyDay 3 distributive property
Day 3 distributive propertyErik Tjersland
 
What do you mean, Backwards Compatibility?
What do you mean, Backwards Compatibility?What do you mean, Backwards Compatibility?
What do you mean, Backwards Compatibility?Trisha Gee
 
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 7Brian Hogan
 
(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your GroovyAlonso Torres
 
Dpir 2014 abstractions
Dpir 2014 abstractionsDpir 2014 abstractions
Dpir 2014 abstractionsrussolsen
 
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 2019Victor Rentea
 
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.Workhorse Computing
 
Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2Ralph Schindler
 
Scaling php applications with redis
Scaling php applications with redisScaling php applications with redis
Scaling php applications with redisjimbojsb
 

Similar a Managing complexity (20)

MongoSV Schema Workshop
MongoSV Schema WorkshopMongoSV Schema Workshop
MongoSV Schema Workshop
 
Domain Primitives In Action - Explore DDD 2017
Domain Primitives In Action - Explore DDD 2017Domain Primitives In Action - Explore DDD 2017
Domain Primitives In Action - Explore DDD 2017
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011MongoDB, PHP and the cloud - php cloud summit 2011
MongoDB, PHP and the cloud - php cloud summit 2011
 
Webinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in DocumentsWebinar: Back to Basics: Thinking in Documents
Webinar: Back to Basics: Thinking in Documents
 
ActiveDOM
ActiveDOMActiveDOM
ActiveDOM
 
Why certain code is hard to test?
Why certain code is hard to test?Why certain code is hard to test?
Why certain code is hard to test?
 
Indexing thousands of writes per second with redis
Indexing thousands of writes per second with redisIndexing thousands of writes per second with redis
Indexing thousands of writes per second with redis
 
MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011MongoDB and PHP ZendCon 2011
MongoDB and PHP ZendCon 2011
 
Day 3 distributive property
Day 3 distributive propertyDay 3 distributive property
Day 3 distributive property
 
What do you mean, Backwards Compatibility?
What do you mean, Backwards Compatibility?What do you mean, Backwards Compatibility?
What do you mean, Backwards Compatibility?
 
Latinoware
LatinowareLatinoware
Latinoware
 
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
 
(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy
 
Dpir 2014 abstractions
Dpir 2014 abstractionsDpir 2014 abstractions
Dpir 2014 abstractions
 
Building Custom PHP Extensions
Building Custom PHP ExtensionsBuilding Custom PHP Extensions
Building Custom PHP Extensions
 
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
 
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.
 
Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2
 
Scaling php applications with redis
Scaling php applications with redisScaling php applications with redis
Scaling php applications with redis
 

Más de SmartLogic

Writing Game Servers with Elixir
Writing Game Servers with ElixirWriting Game Servers with Elixir
Writing Game Servers with ElixirSmartLogic
 
All Aboard The Stateful Train
All Aboard The Stateful TrainAll Aboard The Stateful Train
All Aboard The Stateful TrainSmartLogic
 
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan IvovichDC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan IvovichSmartLogic
 
Monitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with PrometheusMonitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with PrometheusSmartLogic
 
Going Multi-Node
Going Multi-NodeGoing Multi-Node
Going Multi-NodeSmartLogic
 
Kubernetes and docker
Kubernetes and dockerKubernetes and docker
Kubernetes and dockerSmartLogic
 
Serializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSerializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSmartLogic
 
Guide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei EllerbrockGuide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei EllerbrockSmartLogic
 
Introduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogicIntroduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogicSmartLogic
 
How SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan IvovichHow SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan IvovichSmartLogic
 
A Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageA Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageSmartLogic
 
Effective ActiveRecord
Effective ActiveRecordEffective ActiveRecord
Effective ActiveRecordSmartLogic
 
An Introduction to Reactive Cocoa
An Introduction to Reactive CocoaAn Introduction to Reactive Cocoa
An Introduction to Reactive CocoaSmartLogic
 
iOS Development Methodology
iOS Development MethodologyiOS Development Methodology
iOS Development MethodologySmartLogic
 
CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!SmartLogic
 
Deploying Rails Apps with Chef and Capistrano
 Deploying Rails Apps with Chef and Capistrano Deploying Rails Apps with Chef and Capistrano
Deploying Rails Apps with Chef and CapistranoSmartLogic
 
From Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to CodeFrom Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to CodeSmartLogic
 
The Language of Abstraction in Software Development
The Language of Abstraction in Software DevelopmentThe Language of Abstraction in Software Development
The Language of Abstraction in Software DevelopmentSmartLogic
 
Android Testing: An Overview
Android Testing: An OverviewAndroid Testing: An Overview
Android Testing: An OverviewSmartLogic
 
Intro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS DevelopmentIntro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS DevelopmentSmartLogic
 

Más de SmartLogic (20)

Writing Game Servers with Elixir
Writing Game Servers with ElixirWriting Game Servers with Elixir
Writing Game Servers with Elixir
 
All Aboard The Stateful Train
All Aboard The Stateful TrainAll Aboard The Stateful Train
All Aboard The Stateful Train
 
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan IvovichDC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
DC |> Elixir Meetup - Going off the Rails into Elixir - Dan Ivovich
 
Monitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with PrometheusMonitoring Your Elixir Application with Prometheus
Monitoring Your Elixir Application with Prometheus
 
Going Multi-Node
Going Multi-NodeGoing Multi-Node
Going Multi-Node
 
Kubernetes and docker
Kubernetes and dockerKubernetes and docker
Kubernetes and docker
 
Serializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara HacopianSerializing Value Objects-Ara Hacopian
Serializing Value Objects-Ara Hacopian
 
Guide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei EllerbrockGuide to food foraging by SmartLogic's Kei Ellerbrock
Guide to food foraging by SmartLogic's Kei Ellerbrock
 
Introduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogicIntroduction to Type Script by Sam Goldman, SmartLogic
Introduction to Type Script by Sam Goldman, SmartLogic
 
How SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan IvovichHow SmartLogic Uses Chef-Dan Ivovich
How SmartLogic Uses Chef-Dan Ivovich
 
A Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageA Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming Language
 
Effective ActiveRecord
Effective ActiveRecordEffective ActiveRecord
Effective ActiveRecord
 
An Introduction to Reactive Cocoa
An Introduction to Reactive CocoaAn Introduction to Reactive Cocoa
An Introduction to Reactive Cocoa
 
iOS Development Methodology
iOS Development MethodologyiOS Development Methodology
iOS Development Methodology
 
CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!CSS Preprocessors to the Rescue!
CSS Preprocessors to the Rescue!
 
Deploying Rails Apps with Chef and Capistrano
 Deploying Rails Apps with Chef and Capistrano Deploying Rails Apps with Chef and Capistrano
Deploying Rails Apps with Chef and Capistrano
 
From Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to CodeFrom Slacker to Hacker, Practical Tips for Learning to Code
From Slacker to Hacker, Practical Tips for Learning to Code
 
The Language of Abstraction in Software Development
The Language of Abstraction in Software DevelopmentThe Language of Abstraction in Software Development
The Language of Abstraction in Software Development
 
Android Testing: An Overview
Android Testing: An OverviewAndroid Testing: An Overview
Android Testing: An Overview
 
Intro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS DevelopmentIntro to DTCoreText: Moving Past UIWebView | iOS Development
Intro to DTCoreText: Moving Past UIWebView | iOS Development
 

Managing complexity

  • 1. Managing Complexity Sam Goldman @nontrivialzeros github.com/samwgoldman Monday, December 17, 12
  • 2. What is Complexity? • Lines of code? • Duplication? • Coupling? • LOC/Method? • # Methods/Class? • # Features? Monday, December 17, 12
  • 3. Noticing Complexity • Feature development costs increase • Bugs increase superlinearly with code size • “Boring bugs” keep happening • New dev onboarding takes weeks • Local changes have unexpected, non-local effects Monday, December 17, 12
  • 4. Reasoning about Complexity • How can you compare two solutions? • Lots of guidelines, e.g., SOLID • Lots of cargo culting • We need to do better than a gut check • Patterns are still good Monday, December 17, 12
  • 5. Factorization • Large numbers factorized by primes • 288 = 2 × 2 × 2 × 2 × 2 × 3 × 3 • Some large numbers can’t be factorized • 195845982777569926302400511 • Fundamental theorem of arithmetic • No efficient algorithm Monday, December 17, 12
  • 6. Probabilistic Factors • Take binary random variables A, B, and C • P(A) has two possible configurations • P(A, B) has 4 • P(A, B, C) has 8 • Joint configurations grow exponentially Monday, December 17, 12
  • 7. Probabilistic Factors • Distributions factorized by independence • P(A, B) = P(A)P(B) if A, B are independent • Let A and B each have 100 discrete values • Not independent: 10000 configurations • Independent: 200 configurations Monday, December 17, 12
  • 9. OOP • Software is factorized by encapsulation • Controlling dependencies is key • Conversely: Discover independencies Monday, December 17, 12
  • 10. Tell, Don’t Ask • Depending on collaborators’ states breaks encapsulation • Depend on behaviors, not state • Law of Demeter Monday, December 17, 12
  • 11. Asking Questionnaire = Struct.new(:questions) do def render(html) html.form questions.each do |question| html.fieldset { case question when ShortAnswerQuestion html.label(:for => question.id) { html.text question.prompt } html.input(:type => "text", :id => question.id, :name => question.id) when MultipleChoiceQuestion html.label { html.text question.prompt } html.ul { question.choices.each do |choice| html.li { html.label(:for => choice.id) { html.text choice.title } html.input(:type => "radio", :id => choice.id, :name => choice.id) } end } end } end end end end Monday, December 17, 12
  • 12. Telling Questionnaire = Struct.new(:questions) do def render(html) html.form do questions.each do |question| html.fieldset { question.render(html) } end end end end Monday, December 17, 12
  • 13. Telling ShortAnswerQuestion = Struct.new(:id, :prompt) do def render(html) html.label(:for => id) { html.text prompt } html.input(:type => "text", :id => id, :name => id) end end MultipleChoiceQuestion = Struct.new(:id, :prompt, :choices) do def render(html) html.label { html.text prompt } html.ul { choices.each do |choice| html.li { choice.render(html) } end } end end Choice = Struct.new(:id, :title) do def render(html) html.label(:for => id) { html.text title } html.input(:type => "radio", :id => id, :name => id) end end Monday, December 17, 12
  • 14. Mocks • How can we write assertions when objects hide their internal state? • We need to assert that objects are sending the right messages to one another Monday, December 17, 12
  • 15. Mocks describe Questionnaire do it "renders every question" do question1 = mock question2 = mock questionnaire = Questionnaire.new([question1, question2]) builder = stub question1.should_receive(:render).with(builder).ordered question2.should_receive(:render).with(builder).ordered questionnaire.render(builder) end end Monday, December 17, 12
  • 16. Mocks Aren’t Stubs describe ArrearsReport do it "displays customers who owe money" do report = ArrearsReport.new foo_customer = stub(:in_arrears? => true) bar_customer = stub(:in_arrears? => false) result = report.run([foo_customer, bar_customer]) result.should eq([foo_customer]) end end describe Questionnaire do it "renders every question" do question1 = mock question2 = mock questionnaire = Questionnaire.new([question1, question2]) builder = stub question1.should_receive(:render).with(builder).ordered question2.should_receive(:render).with(builder).ordered questionnaire.render(builder) end end Monday, December 17, 12
  • 17. Mocks Aren’t Stubs describe ArrearsReport do it "displays customers who owe money" do report = ArrearsReport.new foo_customer = stub(:in_arrears? => true) Stub Queries bar_customer = stub(:in_arrears? => false) result = report.run([foo_customer, bar_customer]) result.should eq([foo_customer]) end end describe Questionnaire do it "renders every question" do question1 = mock question2 = mock questionnaire = Questionnaire.new([question1, question2]) builder = stub Mock Actions question1.should_receive(:render).with(builder).ordered question2.should_receive(:render).with(builder).ordered questionnaire.render(builder) end end Monday, December 17, 12
  • 18. Values • SmartLogic’s Nerdword project • Services: Player, Pouch, Board • Values: Move, Direction, Position Monday, December 17, 12
  • 19. Values module Direction HORIZONTAL = "Horizontal".freeze VERTICAL = "Vertical".freeze def self.opposite(direction) if direction == HORIZONTAL VERTICAL else HORIZONTAL end end end Monday, December 17, 12
  • 20. Values Position = Struct.new(:col, :row) do def shift(offset, direction) if direction == Direction::HORIZONTAL Position.new(col + offset, row) else Position.new(col, row + offset) end end def previous(direction) shift(-1, direction) end def next(direction) shift(1, direction) end end Monday, December 17, 12
  • 21. Values Move = Struct.new(:word, :position, :direction) do def each_position word.length.times do |i| yield position.shift(i, direction) end end end Monday, December 17, 12
  • 22. Values • We happily depend on Array, Date, String... • Create values in your domain • Separate services from values • Better messages, better factors • Don’t stub values Monday, December 17, 12
  • 23. Abstractions • RemoteFile, not S3 • PaymentProcessor, not Braintree • Wrap services around 3rd party code • “Ports and Adapters” • Write integrated tests for wrapper services • “Test double” wrapper services elsewhere • ActiveRecord? Monday, December 17, 12
  • 24. Acceptance Tests • “How does the client know it works?” • Write acceptance tests your client would understand • Write acceptance tests your client would want to read • Write as few acceptance tests as possible Monday, December 17, 12
  • 25. Integration Tests • “How do we know if it works?” • Ports and Adapters is a good factorization • Write as few integration tests as you need • You don’t need as many as you think Monday, December 17, 12
  • 26. Thank you @smartlogic facebook.com/smartlogic github.com/smartlogic Monday, December 17, 12