boston startup school - oo design
DESCRIPTION
Slides talking about object-oriented design for candidates at the Boston Startup SchoolTRANSCRIPT
OO DesignPart Deux
About Me● Bryan Warner - Engineer @ Traackr
● 10 years of programming experience
● Currently working with Java/Spring/MongoDB, ElasticSearch/Lucene, and Scala/Spray.io
● Email: [email protected]
About You● Programming experience outside of B.S.S.
● What are you hoping to learn in this session
● Ruby vs. Java
Object-Oriented Design
What is OO Design*
● Single Responsibility Principle
● Open / Closed Principle
● Data encapsulation○ The mighty DOT (.)
● Data Abstraction / Loose Coupling
● Modularization => Architectural OO
* Impossible to follow 100%
Why OO Design● Better code maintainability
● Promote code reusability (DRY)
● Less feeling like this...
When to OO Design
● Is it worth it? ... depends
● Cost of good design vs. cost of quick-and-dirty design
● Too much design (i.e. over-architecting) just as bad as no design
● What are you building?
● The future is uncertain
Bird's Eye ViewTo begin,
Let's ask the question: Where does Code live?
Hint: It's not the cloud...
MVC Architecture
RAILS APP
MODULE
CONTROLLER CONTROLLER
MODEL MODEL
MVC - 1 Year Later
RAILS APP
MODULE
CONTROLLER CONTROLLER
MODEL MODEL
CONTROLLER CONTROLLER
MODEL
MODEL MODEL MODEL
EMAIL UTILS
MVC - 2 Years Later
RAILS APP
MODULE
CONTROLLER
MODEL
MODEL
MODELMODEL
MODEL MODEL
EMAIL UTILS
MODEL
MODEL
CONTROLLER
CONTROLLER
CONTROLLER
CONTROLLER
CONTROLLER
CONTROLLER
CONTROLLER
CONTROLLER
MODEL
MODEL
MODEL MODEL MODEL MODEL
ANALYTICS UTILS
REPORTING UTILS
CRON JOB UTILS
EMAIL UTILS
WEB UTILS
Bloat● Classes => Single Responsibility Principle
○ Failure to adhere = Non-reusable code
● Applications => Single Purpose Principle○ Failure to adhere = One monolithic application
Who Cares, right?● Tougher to scale performance with one, giant application
● As the application grows, tougher to add features to it○ No matter how well you structure your code, it's just increasingly
difficult to keep the bloat under control without modularization
● Unit testing performance suffers => Less likely to add more tests (or even run the ones you have!)
● So what's the answer?
Software Modularization
What is a module?● A grouping of classes that share a common purpose
● A module should have a specification file that describes the module○ Name, summary, etc.○ Version number○ External dependencies (if any)
● Ruby: Gemspec File (http://docs.rubygems.org/read/chapter/20)○ http://rubygems.org/gems/twitter
● Java: Maven => POM File○ http://search.maven.org/#browse%7C-120342089
● Provides its own set of unit tests (hopefully!)
● A module can (and usually does) extend the functionality of another module
Modules ~ LegosModules are the building blocks of your applications!
Modular Architecture
APPLICATION
MODULES MODULES MODULES
CLASSES
CLASSES
CLASSES
CLASSES
CLASSES
CLASSES
CLASSES
CLASSES
CLASSES
Modules <-> OO Design● Efficient software modularization can't be achieved without following good
OO design principles
● The functionality a module offers is only available through the classes it provides. Think about:○ What methods (i.e. APIs) do you want to expose in your classes?○ How could one extend the functionality you provide (e.g. inheritance
structures, interfaces, mixins, etc.)
● A module's classes should only do what they are designed to do (SRP)○ Classes that make behavioral assumptions are less reusable by
others
● Classes bloat = Module bloat
Coding Exercise I● Let's create a software module!
● Identify a reusable software component that can be leveraged in your own personal projects○ Can we brainstorm ideas in class and break into teams?○ -OR-○ Program against the use-case in the next slide
● Properly structure your module according to Ruby Gem standards○ For instance, I can demonstrate how Java Maven modules are
structured
● Unit tests for your module!
● Extra Credit => Create a Ruby Gem for your module
Module Description1. Exposes one method to take in a social profile URL and return a social
profile response
2. The supported URLs will be facebook and twitter. Non-supported URLs should throw an exception
3. Use a ruby HTML parser to scrap the data from the page and extract the person's bio, picture URL, etc.
4. Create a class to encapsulate the response info
Coding Exercise II● Import our social profile retrieval module into an existing Rails App or we
can create a new one
● Let's add some properties to a Contact model○ Social Profile URL○ Bio○ Image URL○ Etc.
● When we create a Contact○ Hook into our module to automatically fetch a contact's social profile
info○ Store this information on the contact
Data Abstraction● Loosely-coupled vs. highly-coupled classes
● Dependency inversion○ High-level components should not depend directly on low-level
components. They should both depend on abstractions
○ Abstractions should not depend on details. Details should depend upon abstractions
● Hides implementation details from caller
● Allows us to switch out low-level components on the fly○ Which is terrific for unit testing, ○ Allows us to utilize a concept known as mock objects
Data Abstraction● Java => Interfaces
○ Interface methods can not provide any implementation details
● Scala => Traits○ Similar to interfaces, but a trait method can provide a default
implementation
● Ruby => "duck-typing" ... no such thing as a "design by contract" due to the lack of static typing
Dependency injection frameworks can help "wire" classes together that utilize an abstraction layer
○ Java => Spring Framework, Google Guice
Coding Exercise III● Let's re-examine our social profile retrieval module
○ Let's create an inheritance structure for our retrieval component so it can support multiple, different implementations
○ Have our existing class extend this inheritance structure and re-name the class to reflect what type of implementation it is (e.g. SocialProfilePageScrapper)
○ Create a new implementation for social profile retrieval that will mock (i.e. fake) a response instead of actually making an HTTP call, and name it appropriately
Coding Exercise IV● Let's apply the principles of data inversion to our application's dependency
on the module
○ In our Ruby on Rails app, where we create the contact, abstract the usage of the social profile retrieval component so it can be easily be "switched out" for different implementations■ Hint: the component should be a property of the class it lives in
○ Extra Credit: Write a unit test for creating a contact that will "wire in" the mock social profile implementation so we can assert for known expected values