SlideShare uma empresa Scribd logo
1 de 25
Refactoring Legacy
Code
Learnings from RedBubble
Paul Coia
What is Legacy Code?
Untested code
Dead code
Large classes/methods
Spaghetti architecture
Models too rigid to meet new
requirements
Product model
Available Option
Value
Product Type
Enumeration table
Product
Artwork
OptionOption Value
Print Size,
Frame Colour,
Matte Colour,
Frame Style
Small,
Medium,
Large,
Red,
etc.
FramedPrint
Enumeration table
Easy to add new products or options
 No new columns, just insert rows
No code changes
Can query against it
 “Find all artworks available on red t-shirts”
Populate web form elements easily
Domain model is in the DB
Product class is a generic type
What about domain logic?
„Instances‟ need a separate set of
tables
Buying a product
OptionOption Value
Available Option
Value
Product
Artwork
Product Type
Selected
Product
Selected
Option Value
Preparing the product form
framed_print = ProductType.find_by_name(“FramedPrint”)
# Get the Framed Print product
fp_product = artwork.products.detect do |p|
p.product_type == framed_print
end
aovs = fp_product.available_option_values
# Group these into the options
options_hash = {}
aovs.each do |aov|
options_hash[aov.option_value.option] << aov.option_value
end
# Order the option values, so we have S, M, L, etc.
# Populate form elements
SQL view
1. Load products by artwork_id
2. Load available_product_options by
product_id
3. Load option_values by option_value_id
4. Load options by option_id
Troublesome requirements
Some products have default
options
T-Shirt default colour and style
Options that are not constrained
Calendar start month
Inter-option constraints
Longsleeve Tee colours
Default options
Flag on available_product_option
Need to enforce one default per
option type
Render artwork with default
options
Rendering default options
Rendering the defaults
# Get the default product
tee_product = artwork.get_default_product
aovs = tee_product.available_option_values
defaults = aovs.select {|aov| aov.default? }
# Group these into the options (assuming one per option)
options_hash = {}
defaults.each do |aov|
options_hash[aov.option_value.option] << aov.option_value
end
# Need to validate that we have all required defaults
# and only one per option, etc.
SQL view
1. Load products by product_id
2. Load available_product_options by
product_id
3. Load option_values by option_value_id
4. Load options by option_id
 Same joins as the first example
Rendering lots of products!
Data volumes
0
50
100
150
200
250
300
350
Works Products Available Option Values
Millions
Inter option constraints
Roundneck T-shirts can have all
colours
V-Neck can only have a few
How do you model that in the DB?
Do you want to?
Original driver
Want to add new products weekly
Really?
Real-world constraints
Product preparation takes months
Cannot cover all eventualities
New products always required new
code anyway
Alternative approach
Model product types as classes
Define options and constraints (DSL)
Available products is a list of keys
on Artwork
Available product options is a hash
on the Artwork
So is the default options
Product class
class TShirtProduct
option Style, "mens", "T-Shirt"
option Style, "vneck", "V-Neck T-Shirt"
option Style, "longsleeve", "Long Sleeve T-Shirt"
option Style, "womens", "Girly Fitted T-Shirt"
option Style, "mhoodie", "Hoodie"
option Size, "xs", "XS"
option Size, "small", "Small"
option Size, "medium", "Medium”
...
AVAILABLE_COLORS = {
"mens" => all_colors,
"vneck" => [”black”, ”grey”, "navy", "white”]
}
end
Database model
Artwork
What have we gained?
An expressive, flexible product
model
Simpler code, overall
Actually easier to add products now
And easier to modify existing ones
Nearly 25% average speed increase
What have we lost?
“Find all red t-shirts”
Utilise a search engine
“How many large framed prints
have we sold?”
Reporting via Data Warehouse
Online product addition
100s of millions of rows from the DB!
Refactoring product model

Mais conteúdo relacionado

Destaque (6)

Session hijacking
Session hijackingSession hijacking
Session hijacking
 
Donors profiling softlab
Donors profiling softlabDonors profiling softlab
Donors profiling softlab
 
Binary tree
Binary treeBinary tree
Binary tree
 
วิชาคอมพรีเซ็นเรื่อง วิวัฒนาการอินเตอร์เน็ตของโลก
วิชาคอมพรีเซ็นเรื่อง วิวัฒนาการอินเตอร์เน็ตของโลกวิชาคอมพรีเซ็นเรื่อง วิวัฒนาการอินเตอร์เน็ตของโลก
วิชาคอมพรีเซ็นเรื่อง วิวัฒนาการอินเตอร์เน็ตของโลก
 
Competencia liderazgo
Competencia liderazgoCompetencia liderazgo
Competencia liderazgo
 
Cloud computing and business impact
Cloud computing and business impactCloud computing and business impact
Cloud computing and business impact
 

Semelhante a Refactoring product model

BUSI 301 Book Review RubricScoreCommentsResearch 25.docx
BUSI 301 Book Review RubricScoreCommentsResearch 25.docxBUSI 301 Book Review RubricScoreCommentsResearch 25.docx
BUSI 301 Book Review RubricScoreCommentsResearch 25.docx
humphrieskalyn
 

Semelhante a Refactoring product model (20)

Le Wagon Tokyo | Build your Landing Page in 2 hours
Le Wagon Tokyo | Build your Landing Page in 2 hoursLe Wagon Tokyo | Build your Landing Page in 2 hours
Le Wagon Tokyo | Build your Landing Page in 2 hours
 
Le Wagon - 2h Landing
Le Wagon - 2h LandingLe Wagon - 2h Landing
Le Wagon - 2h Landing
 
Physical Design and Development
Physical Design and DevelopmentPhysical Design and Development
Physical Design and Development
 
Retail referencearchitecture productcatalog
Retail referencearchitecture productcatalogRetail referencearchitecture productcatalog
Retail referencearchitecture productcatalog
 
Sww 2008 Automating Your Designs Excel, Vba And Beyond
Sww 2008   Automating Your Designs   Excel, Vba And BeyondSww 2008   Automating Your Designs   Excel, Vba And Beyond
Sww 2008 Automating Your Designs Excel, Vba And Beyond
 
2018 03 27_biological_databases_part4_v_upload
2018 03 27_biological_databases_part4_v_upload2018 03 27_biological_databases_part4_v_upload
2018 03 27_biological_databases_part4_v_upload
 
Html css
Html cssHtml css
Html css
 
Introduction to Advanced Product Options
 Introduction to Advanced Product Options  Introduction to Advanced Product Options
Introduction to Advanced Product Options
 
BUSI 301 Book Review RubricScoreCommentsResearch 25.docx
BUSI 301 Book Review RubricScoreCommentsResearch 25.docxBUSI 301 Book Review RubricScoreCommentsResearch 25.docx
BUSI 301 Book Review RubricScoreCommentsResearch 25.docx
 
Le Wagon - Build your Landing Page in 2 hours
Le Wagon - Build your Landing Page in 2 hoursLe Wagon - Build your Landing Page in 2 hours
Le Wagon - Build your Landing Page in 2 hours
 
Customized Retail audit
Customized Retail auditCustomized Retail audit
Customized Retail audit
 
Le Wagon - Landing page
Le Wagon - Landing pageLe Wagon - Landing page
Le Wagon - Landing page
 
Building Sustainable Design Systems
Building Sustainable Design SystemsBuilding Sustainable Design Systems
Building Sustainable Design Systems
 
Handout7 html forms
Handout7 html formsHandout7 html forms
Handout7 html forms
 
AI Builder Deep Dive Power BI User Group Washington DC
AI Builder Deep Dive Power BI User Group Washington DCAI Builder Deep Dive Power BI User Group Washington DC
AI Builder Deep Dive Power BI User Group Washington DC
 
AI Builder Deep Dive
AI Builder Deep DiveAI Builder Deep Dive
AI Builder Deep Dive
 
Boosting Product Categorization with Machine Learning
Boosting Product Categorization with Machine LearningBoosting Product Categorization with Machine Learning
Boosting Product Categorization with Machine Learning
 
Le Wagon Tokyo - 2 hours landing page
Le Wagon Tokyo - 2 hours  landing pageLe Wagon Tokyo - 2 hours  landing page
Le Wagon Tokyo - 2 hours landing page
 
AI Builder Deep dive Super Power Saturday London 2020
AI Builder Deep dive Super Power Saturday London 2020AI Builder Deep dive Super Power Saturday London 2020
AI Builder Deep dive Super Power Saturday London 2020
 
Html 5
Html 5Html 5
Html 5
 

Último

Último (20)

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
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
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...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
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
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
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
 
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...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
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
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
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
 

Refactoring product model

  • 2.
  • 3. What is Legacy Code? Untested code Dead code Large classes/methods Spaghetti architecture Models too rigid to meet new requirements
  • 5. Available Option Value Product Type Enumeration table Product Artwork OptionOption Value Print Size, Frame Colour, Matte Colour, Frame Style Small, Medium, Large, Red, etc. FramedPrint
  • 6. Enumeration table Easy to add new products or options  No new columns, just insert rows No code changes Can query against it  “Find all artworks available on red t-shirts” Populate web form elements easily
  • 7. Domain model is in the DB Product class is a generic type What about domain logic? „Instances‟ need a separate set of tables
  • 8. Buying a product OptionOption Value Available Option Value Product Artwork Product Type Selected Product Selected Option Value
  • 9. Preparing the product form framed_print = ProductType.find_by_name(“FramedPrint”) # Get the Framed Print product fp_product = artwork.products.detect do |p| p.product_type == framed_print end aovs = fp_product.available_option_values # Group these into the options options_hash = {} aovs.each do |aov| options_hash[aov.option_value.option] << aov.option_value end # Order the option values, so we have S, M, L, etc. # Populate form elements
  • 10. SQL view 1. Load products by artwork_id 2. Load available_product_options by product_id 3. Load option_values by option_value_id 4. Load options by option_id
  • 11. Troublesome requirements Some products have default options T-Shirt default colour and style Options that are not constrained Calendar start month Inter-option constraints Longsleeve Tee colours
  • 12. Default options Flag on available_product_option Need to enforce one default per option type Render artwork with default options
  • 14. Rendering the defaults # Get the default product tee_product = artwork.get_default_product aovs = tee_product.available_option_values defaults = aovs.select {|aov| aov.default? } # Group these into the options (assuming one per option) options_hash = {} defaults.each do |aov| options_hash[aov.option_value.option] << aov.option_value end # Need to validate that we have all required defaults # and only one per option, etc.
  • 15. SQL view 1. Load products by product_id 2. Load available_product_options by product_id 3. Load option_values by option_value_id 4. Load options by option_id  Same joins as the first example
  • 16. Rendering lots of products!
  • 18. Inter option constraints Roundneck T-shirts can have all colours V-Neck can only have a few How do you model that in the DB? Do you want to?
  • 19. Original driver Want to add new products weekly Really? Real-world constraints Product preparation takes months Cannot cover all eventualities New products always required new code anyway
  • 20. Alternative approach Model product types as classes Define options and constraints (DSL) Available products is a list of keys on Artwork Available product options is a hash on the Artwork So is the default options
  • 21. Product class class TShirtProduct option Style, "mens", "T-Shirt" option Style, "vneck", "V-Neck T-Shirt" option Style, "longsleeve", "Long Sleeve T-Shirt" option Style, "womens", "Girly Fitted T-Shirt" option Style, "mhoodie", "Hoodie" option Size, "xs", "XS" option Size, "small", "Small" option Size, "medium", "Medium” ... AVAILABLE_COLORS = { "mens" => all_colors, "vneck" => [”black”, ”grey”, "navy", "white”] } end
  • 23. What have we gained? An expressive, flexible product model Simpler code, overall Actually easier to add products now And easier to modify existing ones Nearly 25% average speed increase
  • 24. What have we lost? “Find all red t-shirts” Utilise a search engine “How many large framed prints have we sold?” Reporting via Data Warehouse Online product addition 100s of millions of rows from the DB!

Notas do Editor

  1. Legacy code slows down feature developmentWe all write itSo there’s a lot around
  2. Need to determine what the product represents before we can do anything with it.For example, we need to render it differently
  3. Joining 4 tables together
  4. Each thumbnail requires the same 4 tables joined
  5. Each work has multiple products, and each has multiple available options
  6. In 4 years, RedBubble has 11 product types.Sourcing suppliers, defining the specifications and getting samples all was time consuming.The application needed to know how to provision, configure and render the product.Genericity ended up getting in the way.
  7. Selected options and defaults are on the artworkOptions are modelled in a code (DSL)Rendering a default view requires only the loading of one record
  8. Every line of code had a reason for existenceChallenge existing models for every new requirement