SlideShare ist ein Scribd-Unternehmen logo
1 von 53
Downloaden Sie, um offline zu lesen
GET BETTER AT REFACTORING
stanly@odd-e.com

@stanlylau
INTRODUCTION
ABOUT ME
▸ Lives in Singapore
▸ Software development coach /
mentor
▸ Goal: Reduce the cost of change
▸ Agile Singapore community
1. PROBLEM
2. REFACTORING
3. DEMO
4. TIPS
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String post(@ModelAttribute MailSendForm form, Model model) {
model.addAttribute("form", form);
return "send";
}
loc: 4
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String post(@ModelAttribute MailSendForm form, Model model) {
// TODO Validate Request
String address = form.getAddress();
boolean isMailAddress = Validator.isMailAddress(address);
if (!isMailAddress) {
model.addAttribute("form", form);
model.addAttribute("error", "error");
return "send";
}
String subject = form.getSubject();
boolean isSubject = Validator.isSubject(subject);
String body = form.getBody();
boolean isBody = Validator.isBody(body);
// TODO Mail Send
// TODO Show the page
model.addAttribute("form", form);
return "send";
}
loc: 14
@RequestMapping(value = "/sendEmail", method = RequestMethod.POST)
public String sendEmail(@ModelAttribute MailSendForm form, Model model) {
if (!Validator.isMailAddress(form.getAddress())) {
model.addAttribute("error", "error");
return "send";
}
if (!Validator.isSubject(form.getSubject())) {
model.addAttribute("error", "error");
return "send";
}
if (!Validator.isBody(form.getBody())) {
model.addAttribute("error", "error");
return "send";
}
MailInfo mail = new MailInfo("gadget.mailsender@gmail.com",
form.getAddress(), form.getSubject(), form.getBody());
try {
mailService.send(mail);
} catch (Exception e) {
e.printStackTrace();
}
return "send";
}
loc: 17
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model)
{
if (result.hasErrors()) {
model.addAttribute("errorMessage", "error");
return "send";
}
String[] addresses = form.getAddress().split("s*;s*");
boolean isValid = Stream.of(addresses).anyMatch(address -> !Validator.isMailAddress(address));
if (isValid) {
model.addAttribute("errorMessage", "error");
return "send";
}
for (String address : addresses) {
MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, form.getSubject(),
form.getBody());
try {
mailService.send(mail);
} catch (Exception e) {
model.addAttribute("errorMessage", "error");
return "send";
}
}
return "send";
}
loc: 18
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String sendEmail(@ModelAttribute MailSendForm form, Model model) {
if (!Validator.isSubject(form.getSubject())) {
model.addAttribute("errorMessage", "error");
return "send";
}
if (!Validator.isBody(form.getBody())) {
model.addAttribute("errorMessage", "error");
return "send";
}
String addressFromForm = form.getAddress();
if (StringUtils.isEmpty(addressFromForm)) {
model.addAttribute("errorMessage", "error");
return "send";
}
String[] addresses = addressFromForm.split(";");
for(String address : addresses) {
if (!Validator.isMailAddress(address)) {
model.addAttribute("errorMessage", "error");
return "send";
}
MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, form.getSubject(),
form.getBody());
try {
mailService.send(mail);
} catch (Exception e) {
model.addAttribute("errorMessage", "error");
}
}
return "send";
}
loc: 23
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) {
if (result.hasErrors()) {
model.addAttribute("errorMessage", "error");
return "send";
}
String[] addresses = form.getAddress().split(“s*;s*");
boolean isValid = Stream.of(addresses).anyMatch(address -> !Validator.isMailAddress(address));
if (isValid) {
model.addAttribute("errorMessage", "error");
return "send";
}
try {
List<MailInfo> mailInfoList = new ArrayList<>();
String subject = form.getSubject();
for (String address : addresses) {
AddressItem addressItem = addressBookService.findByAddress(address);
if (addressItem != null) {
if (StringUtils.isEmpty(addressItem.getName()) && StringUtils.contains(subject, "$name")) {
throw new Exception("name attribute is empty!!");
}
subject = StringUtils.replace(subject, "$name", addressItem.getName());
}
MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, subject, form.getBody());
mailInfoList.add(mail);
}
mailService.sendMultiple(mailInfoList);
} catch (Exception e) {
model.addAttribute("errorMessage", "error");
return "send";
}
return "send";
loc: 26
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) {
if (result.hasErrors()) {
model.addAttribute("errorMessage", "error");
return "send";
}
String[] addresses = form.getAddress().split("s*;s*");
boolean isValid = Stream.of(addresses).anyMatch(address -> !Validator.isMailAddress(address));
if (isValid) {
model.addAttribute("errorMessage", "error");
return "send";
}
try {
List<MailInfo> mailInfoList = new ArrayList<>();
String subject = form.getSubject();
for (String address : addresses) {
AddressItem addressItem = addressBookService.findByAddress(address);
String replacedSubject = subject;
if (addressItem != null) {
if (StringUtils.isEmpty(addressItem.getName()) && StringUtils.contains(subject, "$name")) {
throw new Exception("name attribute is empty!!");
}
replacedSubject = StringUtils.replace(subject, "$name", addressItem.getName());
}else {
if (StringUtils.contains(subject, "$name")){
throw new Exception("email address is not registered");
}
}
MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, replacedSubject, form.getBody());
mailInfoList.add(mail);
}
mailService.sendMultiple(mailInfoList);
} catch (Exception e) {
model.addAttribute("errorMessage", "error");
return "send";
}
return "send";
loc: 30
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) {
if (result.hasErrors()) {
FieldError fieldError = result.getFieldErrors().get(0);
model.addAttribute("errorMessage", fieldError.getField() + " " + fieldError.getDefaultMessage());
return "send";
}
String[] addresses = form.getAddress().split("s*;s*");
boolean isValid = Stream.of(addresses)
.anyMatch(address -> !Validator.isMailAddress(address));
if (isValid) {
model.addAttribute("errorMessage", "Email address is invalid");
return "send";
}
try {
List<MailInfo> mailInfoList = new ArrayList<>();
String subject = form.getSubject();
String body = form.getBody();
for (String address : addresses) {
Contact addressItem = addressBookService.findByAddress(address);
String replacedSubject = subject;
String replacedBody = body;
if (addressItem != null) {
if ("".equals(addressItem.getName()) && (subject.contains("$name") || body.contains("$name"))) {
throw new Exception("Can't render template with an empty name in contact");
}
replacedSubject = subject.replace("$name", addressItem.getName());
replacedBody = body.replace("$name", addressItem.getName());
}else {
if (subject.contains("$name") || body.contains("$name")){
throw new Exception("No matching contact found to render template");
}
}
MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, replacedSubject, replacedBody);
mailInfoList.add(mail);
}
mailService.sendMultiple(mailInfoList);
} catch (Exception e) {
model.addAttribute("errorMessage", e.getMessage());
return "send";
}
return "send";
}
loc: 33
http://www.marketingfirepower.info
A NATURE OF SOFTWARE DEVELOPMENT
AMOUNT OF
"BAD” CODE
# BUGS
TIME SPENT
ON FIXING
BUGS
PANIC
QUICK HACKS
MOTIVATION OF
DEVELOPERS
CASUAL LOOP
DIAGRAM
A NATURE OF SOFTWARE DEVELOPMENT
REQUIREMENTS
TIME
(you)
(competitor)
COMPETING BY CHANGE
The Management of Computer Programming Projects
Charles Lecht - 1967
Equally responsible for the initiation of project with
predefined failure is management that insists upon having
fixed commitments from programming personnel prior to
the latter’s understanding what the commitment are for.
Too frequently, management does not realize that in
asking the staff for “the impossible”, the staff will feel the
obligation to respond out of respect, fear or misguided
loyalty. Saying “no” to the boss frequently requires
courage, political and psychological wisdom, and
business maturity that comes with much experience.
A NATURE OF SOFTWARE DEVELOPMENT
AMOUNT OF
"BAD” CODE
# BUGS
TIME SPENT
ON FIXING
BUGS
PANIC
QUICK HACKS
MOTIVATION OF
DEVELOPERS
AMOUNT OF
CODE SMELLS
REFACTORING
OPPORTUNITY FOR
INDICATES
REFACTORING 101
SOFTWARE MAINTAINABILITY
REFACTORING
“…IS A DISCIPLINED TECHNIQUE FOR
RESTRUCTURING AN EXISTING BODY OF
CODE, ALTERING ITS INTERNAL
STRUCTURE WITHOUT CHANGING ITS
EXTERNAL BEHAVIOR.”
MARTIN FOWLER
INTRODUCE
PARAMETER OBJECT
EXTRACT CLASS
INTRODUCE
LOCAL VARIABLE
RENAME
MOVE METHODEXTRACT METHOD
INLINE VARIABLE
Q: WHEN DO WE REFACTOR?
A: WHEN THE CODE SMELLS!
CODE SMELLS
“A CODE SMELL IS A SURFACE
INDICATION THAT USUALLY
CORRESPONDS TO A DEEPER PROBLEM
IN THE SYSTEM”
MARTIN FOWLER
DUPLICATED CODE
MAGIC NUMBER
FEATURE ENVY
PRIMITIVE OBSESSION
LONG METHOD
COMMENTS
ABOUT DEMO
PERSONALISED EMAILER
WEB APP
JAVA
SPRING MVC
RECEIVED (NORMAL)
TO: NON-CONTACT@GMAIL.COM
SUBJECT: SEASONS GREETING
TO: NON-CONTACT2@GMAIL.COM
SUBJECT: SEASONS GREETING
RECEIVED (TEMPLATE)
TO: STANLY@ODD-E.COM
SUBJECT: SEASONS GREETING STANLY
TO: AKI@ODD-E.COM
SUBJECT: SEASONS GREETING AKI
Subject with
attribute
Body with
attribute
Send to
multiple
recipients …
✓ ✓
@RequestMapping(value = "/send", method = RequestMethod.POST)
public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) {
if (result.hasErrors()) {
FieldError fieldError = result.getFieldErrors().get(0);
model.addAttribute("errorMessage", fieldError.getField() + " " + fieldError.getDefaultMessage());
return "send";
}
String[] addresses = form.getAddress().split("s*;s*");
boolean isValid = Stream.of(addresses)
.anyMatch(address -> !Validator.isMailAddress(address));
if (isValid) {
model.addAttribute("errorMessage", "Email address is invalid");
return "send";
}
try {
List<MailInfo> mailInfoList = new ArrayList<>();
String subject = form.getSubject();
String body = form.getBody();
for (String address : addresses) {
Contact addressItem = addressBookService.findByAddress(address);
String replacedSubject = subject;
String replacedBody = body;
if (addressItem != null) {
if ("".equals(addressItem.getName()) && (subject.contains("$name") || body.contains("$name"))) {
throw new Exception("Can't render template with an empty name in contact");
}
replacedSubject = subject.replace("$name", addressItem.getName());
replacedBody = body.replace("$name", addressItem.getName());
}else {
if (subject.contains("$name") || body.contains("$name")){
throw new Exception("No matching contact found to render template");
}
}
MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, replacedSubject, replacedBody);
mailInfoList.add(mail);
}
mailService.sendMultiple(mailInfoList);
} catch (Exception e) {
model.addAttribute("errorMessage", e.getMessage());
return "send";
}
return "send";
}
WHAT DID YOU
SMELL?
WHAT DID YOU
SMELL?
L O N G M E T H O D
MailController

——————

sendEmail()
MailInfo
AddressBookService

(interface)

———————

findAddress()
MailService

(interface)

——————

sendMultiple()
MailSendForm
LET’S REFACTOR
sendEmail()
CODE COVERAGE
✓
MailController

——————

sendEmail()
Mail
ContactDao

(interface)

———————

findAddress()
MailService

(interface)

——————

sendMultiple()
EmailTemplate

————-————

populate()

hasPopulateError()

getPopulateErrorMessage()
CODE SMELLS
LONG METHOD
TEMPORARY VARIABLE
FEATURE ENVY
DUPLICATE CODE
MAGIC NUMBER
UNCOMMUNICATIVE NAME
PRIMITIVE OBSESSION
sendEmail()
BREAKS SINGLE RESPONSIBILITY
MAIL CREATION
ERROR HANDLING
TEMPLATE RENDERING
VALIDITY OF RECIPIENT ADDRESS
REFACTORING
EXTRACT METHOD
INLINE VAR. / METHOD
INTRODUCE PARAMETER
RENAME
MOVE METHOD
TIPS
LEARN TO SMELL
THE CODE
CODE SMELLS
DESIGN PRINCIPLES
SINGLE RESPONSIBILITY
HI COHESION, LOW COUPLING
while(change_for_new_functionality()){
DO_NOT_REFACTOR()
}
PROGRAMMING IS THE ART OF
DOING ONE THING AT A TIME
Michael Feathers
TIPS
REFACTORING
WHY? WHAT? HOW?
GET READY
FOR
CHANGE
DESIGN CODE
SMELLS
HOW TO START
ESSENTIAL SKILLS
▸ Explain the code with design principles
▸ Identify code smells
▸ Refactor either manually or through IDE
▸ Familiar working with unit/integration tests
▸ Familiar with the functionality you’re changing
PRACTICE
REFACTORING KATA
https://github.com/stanlylau/tictactoe_csharp
https://github.com/stanlylau/refactoring-kata
https://github.com/emilybache/Tennis-Refactoring-Kata
https://github.com/emilybache/GildedRose-Refactoring-Kata
https://github.com/stanlylau/trivia-csharp
TEACH TO LEARN
1. CREATE CODE SMELLS EXERCISES
2. PRACTICE REMOVING THE SMELLS
3. INVITE PEOPLE TO REMOVE THE SMELLS
4. CODE REVIEW
5. DEMO
Unconscious

Competence
Conscious

Competence
Conscious

Incompetence
Unconscious

Incompetence
FOUR STAGES OF COMPETENCE
TO LEVEL UP
REVIEW THE CODE WITH A MENTOR,
BE REFLECTIVE
EXPERIENCED PROGRAMMERS DO NOT
WRITE INFINITELY COMPLEX CODE;
THEY WRITE CODE THAT’S BLINDINGLY
SIMPLE
99 Bottles of OOP
TIPS
REFACTORING IS
AN EXERCISE IN
KINDNESS
Kent Beck
THANK YOU
STANLY@ODD-E.COM

Weitere ähnliche Inhalte

Was ist angesagt?

Less ismorewithcoffeescript webdirectionsfeb2012
Less ismorewithcoffeescript webdirectionsfeb2012Less ismorewithcoffeescript webdirectionsfeb2012
Less ismorewithcoffeescript webdirectionsfeb2012Jo Cranford
 
Enterprise workflow with Apps Script
Enterprise workflow with Apps ScriptEnterprise workflow with Apps Script
Enterprise workflow with Apps Scriptccherubino
 
Form demoinplaywithmysql
Form demoinplaywithmysqlForm demoinplaywithmysql
Form demoinplaywithmysqlKnoldus Inc.
 
Why (I think) CoffeeScript Is Awesome
Why (I think) CoffeeScript Is AwesomeWhy (I think) CoffeeScript Is Awesome
Why (I think) CoffeeScript Is AwesomeJo Cranford
 
Wann soll ich mocken?
Wann soll ich mocken?Wann soll ich mocken?
Wann soll ich mocken?David Völkel
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF Luc Bors
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
jQuery Rescue Adventure
jQuery Rescue AdventurejQuery Rescue Adventure
jQuery Rescue AdventureAllegient
 
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...jaxconf
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick IntroductionDamian Jureczko
 

Was ist angesagt? (16)

Less ismorewithcoffeescript webdirectionsfeb2012
Less ismorewithcoffeescript webdirectionsfeb2012Less ismorewithcoffeescript webdirectionsfeb2012
Less ismorewithcoffeescript webdirectionsfeb2012
 
Enterprise workflow with Apps Script
Enterprise workflow with Apps ScriptEnterprise workflow with Apps Script
Enterprise workflow with Apps Script
 
SOLID in Practice
SOLID in PracticeSOLID in Practice
SOLID in Practice
 
Form demoinplaywithmysql
Form demoinplaywithmysqlForm demoinplaywithmysql
Form demoinplaywithmysql
 
Why (I think) CoffeeScript Is Awesome
Why (I think) CoffeeScript Is AwesomeWhy (I think) CoffeeScript Is Awesome
Why (I think) CoffeeScript Is Awesome
 
Web 5 | JavaScript Events
Web 5 | JavaScript EventsWeb 5 | JavaScript Events
Web 5 | JavaScript Events
 
Wann soll ich mocken?
Wann soll ich mocken?Wann soll ich mocken?
Wann soll ich mocken?
 
How te bring common UI patterns to ADF
How te bring common UI patterns to ADFHow te bring common UI patterns to ADF
How te bring common UI patterns to ADF
 
How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF How to Bring Common UI Patterns to ADF
How to Bring Common UI Patterns to ADF
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
Web 6 | JavaScript DOM
Web 6 | JavaScript DOMWeb 6 | JavaScript DOM
Web 6 | JavaScript DOM
 
jQuery Rescue Adventure
jQuery Rescue AdventurejQuery Rescue Adventure
jQuery Rescue Adventure
 
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
MVC on the Server and on the Client: How to Integrate Spring MVC and Backbone...
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick Introduction
 
Python training for beginners
Python training for beginnersPython training for beginners
Python training for beginners
 

Ähnlich wie Get better at Refactoring (Voxxed Days)

Get better at Refactoring | Stanly Lau
Get better at Refactoring | Stanly LauGet better at Refactoring | Stanly Lau
Get better at Refactoring | Stanly LauAgileTour@TW
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
SPFx: Working with SharePoint Content
SPFx: Working with SharePoint ContentSPFx: Working with SharePoint Content
SPFx: Working with SharePoint ContentVladimir Medina
 
SPFx working with SharePoint data
SPFx working with SharePoint dataSPFx working with SharePoint data
SPFx working with SharePoint dataVladimir Medina
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaiMasters
 
WordPress: From Antispambot to Zeroize
WordPress: From Antispambot to ZeroizeWordPress: From Antispambot to Zeroize
WordPress: From Antispambot to ZeroizeYoav Farhi
 
מ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכירים
מ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכיריםמ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכירים
מ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכיריםMiriam Schwab
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Seri Moth
 
How to write code you won't hate tomorrow
How to write code you won't hate tomorrowHow to write code you won't hate tomorrow
How to write code you won't hate tomorrowPete McFarlane
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB jhchabran
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Codestasimus
 
Basic Object Oriented Concepts
Basic Object Oriented ConceptsBasic Object Oriented Concepts
Basic Object Oriented ConceptsScott Lee
 
Bare-knuckle web development
Bare-knuckle web developmentBare-knuckle web development
Bare-knuckle web developmentJohannes Brodwall
 
Webmontag Berlin "coffee script"
Webmontag Berlin "coffee script"Webmontag Berlin "coffee script"
Webmontag Berlin "coffee script"Webmontag Berlin
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutesBarang CK
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 

Ähnlich wie Get better at Refactoring (Voxxed Days) (20)

Get better at Refactoring | Stanly Lau
Get better at Refactoring | Stanly LauGet better at Refactoring | Stanly Lau
Get better at Refactoring | Stanly Lau
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
SPFx: Working with SharePoint Content
SPFx: Working with SharePoint ContentSPFx: Working with SharePoint Content
SPFx: Working with SharePoint Content
 
SPFx working with SharePoint data
SPFx working with SharePoint dataSPFx working with SharePoint data
SPFx working with SharePoint data
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio Akita
 
WordPress: From Antispambot to Zeroize
WordPress: From Antispambot to ZeroizeWordPress: From Antispambot to Zeroize
WordPress: From Antispambot to Zeroize
 
מ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכירים
מ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכיריםמ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכירים
מ-antispambot ועד zeroise – עשר פונקציות וורדפרס שאתם כנראה לא מכירים
 
Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
Week 12 code
Week 12 codeWeek 12 code
Week 12 code
 
How to write code you won't hate tomorrow
How to write code you won't hate tomorrowHow to write code you won't hate tomorrow
How to write code you won't hate tomorrow
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
Groovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony CodeGroovy vs Boilerplate and Ceremony Code
Groovy vs Boilerplate and Ceremony Code
 
Basic Object Oriented Concepts
Basic Object Oriented ConceptsBasic Object Oriented Concepts
Basic Object Oriented Concepts
 
Bare-knuckle web development
Bare-knuckle web developmentBare-knuckle web development
Bare-knuckle web development
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Webmontag Berlin "coffee script"
Webmontag Berlin "coffee script"Webmontag Berlin "coffee script"
Webmontag Berlin "coffee script"
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
PHP POWERPOINT SLIDES
PHP POWERPOINT SLIDESPHP POWERPOINT SLIDES
PHP POWERPOINT SLIDES
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 

Kürzlich hochgeladen

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 

Kürzlich hochgeladen (20)

Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 

Get better at Refactoring (Voxxed Days)

  • 1. GET BETTER AT REFACTORING stanly@odd-e.com
 @stanlylau
  • 2. INTRODUCTION ABOUT ME ▸ Lives in Singapore ▸ Software development coach / mentor ▸ Goal: Reduce the cost of change ▸ Agile Singapore community
  • 4. @RequestMapping(value = "/send", method = RequestMethod.POST) public String post(@ModelAttribute MailSendForm form, Model model) { model.addAttribute("form", form); return "send"; } loc: 4
  • 5. @RequestMapping(value = "/send", method = RequestMethod.POST) public String post(@ModelAttribute MailSendForm form, Model model) { // TODO Validate Request String address = form.getAddress(); boolean isMailAddress = Validator.isMailAddress(address); if (!isMailAddress) { model.addAttribute("form", form); model.addAttribute("error", "error"); return "send"; } String subject = form.getSubject(); boolean isSubject = Validator.isSubject(subject); String body = form.getBody(); boolean isBody = Validator.isBody(body); // TODO Mail Send // TODO Show the page model.addAttribute("form", form); return "send"; } loc: 14
  • 6. @RequestMapping(value = "/sendEmail", method = RequestMethod.POST) public String sendEmail(@ModelAttribute MailSendForm form, Model model) { if (!Validator.isMailAddress(form.getAddress())) { model.addAttribute("error", "error"); return "send"; } if (!Validator.isSubject(form.getSubject())) { model.addAttribute("error", "error"); return "send"; } if (!Validator.isBody(form.getBody())) { model.addAttribute("error", "error"); return "send"; } MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", form.getAddress(), form.getSubject(), form.getBody()); try { mailService.send(mail); } catch (Exception e) { e.printStackTrace(); } return "send"; } loc: 17
  • 7. @RequestMapping(value = "/send", method = RequestMethod.POST) public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("errorMessage", "error"); return "send"; } String[] addresses = form.getAddress().split("s*;s*"); boolean isValid = Stream.of(addresses).anyMatch(address -> !Validator.isMailAddress(address)); if (isValid) { model.addAttribute("errorMessage", "error"); return "send"; } for (String address : addresses) { MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, form.getSubject(), form.getBody()); try { mailService.send(mail); } catch (Exception e) { model.addAttribute("errorMessage", "error"); return "send"; } } return "send"; } loc: 18
  • 8. @RequestMapping(value = "/send", method = RequestMethod.POST) public String sendEmail(@ModelAttribute MailSendForm form, Model model) { if (!Validator.isSubject(form.getSubject())) { model.addAttribute("errorMessage", "error"); return "send"; } if (!Validator.isBody(form.getBody())) { model.addAttribute("errorMessage", "error"); return "send"; } String addressFromForm = form.getAddress(); if (StringUtils.isEmpty(addressFromForm)) { model.addAttribute("errorMessage", "error"); return "send"; } String[] addresses = addressFromForm.split(";"); for(String address : addresses) { if (!Validator.isMailAddress(address)) { model.addAttribute("errorMessage", "error"); return "send"; } MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, form.getSubject(), form.getBody()); try { mailService.send(mail); } catch (Exception e) { model.addAttribute("errorMessage", "error"); } } return "send"; } loc: 23
  • 9. @RequestMapping(value = "/send", method = RequestMethod.POST) public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("errorMessage", "error"); return "send"; } String[] addresses = form.getAddress().split(“s*;s*"); boolean isValid = Stream.of(addresses).anyMatch(address -> !Validator.isMailAddress(address)); if (isValid) { model.addAttribute("errorMessage", "error"); return "send"; } try { List<MailInfo> mailInfoList = new ArrayList<>(); String subject = form.getSubject(); for (String address : addresses) { AddressItem addressItem = addressBookService.findByAddress(address); if (addressItem != null) { if (StringUtils.isEmpty(addressItem.getName()) && StringUtils.contains(subject, "$name")) { throw new Exception("name attribute is empty!!"); } subject = StringUtils.replace(subject, "$name", addressItem.getName()); } MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, subject, form.getBody()); mailInfoList.add(mail); } mailService.sendMultiple(mailInfoList); } catch (Exception e) { model.addAttribute("errorMessage", "error"); return "send"; } return "send"; loc: 26
  • 10. @RequestMapping(value = "/send", method = RequestMethod.POST) public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("errorMessage", "error"); return "send"; } String[] addresses = form.getAddress().split("s*;s*"); boolean isValid = Stream.of(addresses).anyMatch(address -> !Validator.isMailAddress(address)); if (isValid) { model.addAttribute("errorMessage", "error"); return "send"; } try { List<MailInfo> mailInfoList = new ArrayList<>(); String subject = form.getSubject(); for (String address : addresses) { AddressItem addressItem = addressBookService.findByAddress(address); String replacedSubject = subject; if (addressItem != null) { if (StringUtils.isEmpty(addressItem.getName()) && StringUtils.contains(subject, "$name")) { throw new Exception("name attribute is empty!!"); } replacedSubject = StringUtils.replace(subject, "$name", addressItem.getName()); }else { if (StringUtils.contains(subject, "$name")){ throw new Exception("email address is not registered"); } } MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, replacedSubject, form.getBody()); mailInfoList.add(mail); } mailService.sendMultiple(mailInfoList); } catch (Exception e) { model.addAttribute("errorMessage", "error"); return "send"; } return "send"; loc: 30
  • 11. @RequestMapping(value = "/send", method = RequestMethod.POST) public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) { if (result.hasErrors()) { FieldError fieldError = result.getFieldErrors().get(0); model.addAttribute("errorMessage", fieldError.getField() + " " + fieldError.getDefaultMessage()); return "send"; } String[] addresses = form.getAddress().split("s*;s*"); boolean isValid = Stream.of(addresses) .anyMatch(address -> !Validator.isMailAddress(address)); if (isValid) { model.addAttribute("errorMessage", "Email address is invalid"); return "send"; } try { List<MailInfo> mailInfoList = new ArrayList<>(); String subject = form.getSubject(); String body = form.getBody(); for (String address : addresses) { Contact addressItem = addressBookService.findByAddress(address); String replacedSubject = subject; String replacedBody = body; if (addressItem != null) { if ("".equals(addressItem.getName()) && (subject.contains("$name") || body.contains("$name"))) { throw new Exception("Can't render template with an empty name in contact"); } replacedSubject = subject.replace("$name", addressItem.getName()); replacedBody = body.replace("$name", addressItem.getName()); }else { if (subject.contains("$name") || body.contains("$name")){ throw new Exception("No matching contact found to render template"); } } MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, replacedSubject, replacedBody); mailInfoList.add(mail); } mailService.sendMultiple(mailInfoList); } catch (Exception e) { model.addAttribute("errorMessage", e.getMessage()); return "send"; } return "send"; } loc: 33
  • 13. A NATURE OF SOFTWARE DEVELOPMENT AMOUNT OF "BAD” CODE # BUGS TIME SPENT ON FIXING BUGS PANIC QUICK HACKS MOTIVATION OF DEVELOPERS CASUAL LOOP DIAGRAM
  • 14. A NATURE OF SOFTWARE DEVELOPMENT REQUIREMENTS TIME (you) (competitor) COMPETING BY CHANGE
  • 15. The Management of Computer Programming Projects Charles Lecht - 1967 Equally responsible for the initiation of project with predefined failure is management that insists upon having fixed commitments from programming personnel prior to the latter’s understanding what the commitment are for. Too frequently, management does not realize that in asking the staff for “the impossible”, the staff will feel the obligation to respond out of respect, fear or misguided loyalty. Saying “no” to the boss frequently requires courage, political and psychological wisdom, and business maturity that comes with much experience.
  • 16. A NATURE OF SOFTWARE DEVELOPMENT AMOUNT OF "BAD” CODE # BUGS TIME SPENT ON FIXING BUGS PANIC QUICK HACKS MOTIVATION OF DEVELOPERS AMOUNT OF CODE SMELLS REFACTORING OPPORTUNITY FOR INDICATES
  • 18. REFACTORING “…IS A DISCIPLINED TECHNIQUE FOR RESTRUCTURING AN EXISTING BODY OF CODE, ALTERING ITS INTERNAL STRUCTURE WITHOUT CHANGING ITS EXTERNAL BEHAVIOR.” MARTIN FOWLER INTRODUCE PARAMETER OBJECT EXTRACT CLASS INTRODUCE LOCAL VARIABLE RENAME MOVE METHODEXTRACT METHOD INLINE VARIABLE
  • 19. Q: WHEN DO WE REFACTOR? A: WHEN THE CODE SMELLS!
  • 20. CODE SMELLS “A CODE SMELL IS A SURFACE INDICATION THAT USUALLY CORRESPONDS TO A DEEPER PROBLEM IN THE SYSTEM” MARTIN FOWLER DUPLICATED CODE MAGIC NUMBER FEATURE ENVY PRIMITIVE OBSESSION LONG METHOD COMMENTS
  • 23.
  • 24. RECEIVED (NORMAL) TO: NON-CONTACT@GMAIL.COM SUBJECT: SEASONS GREETING TO: NON-CONTACT2@GMAIL.COM SUBJECT: SEASONS GREETING
  • 25.
  • 26.
  • 27. RECEIVED (TEMPLATE) TO: STANLY@ODD-E.COM SUBJECT: SEASONS GREETING STANLY TO: AKI@ODD-E.COM SUBJECT: SEASONS GREETING AKI
  • 28. Subject with attribute Body with attribute Send to multiple recipients … ✓ ✓
  • 29. @RequestMapping(value = "/send", method = RequestMethod.POST) public String sendEmail(@Valid @ModelAttribute MailSendForm form, BindingResult result, Model model) { if (result.hasErrors()) { FieldError fieldError = result.getFieldErrors().get(0); model.addAttribute("errorMessage", fieldError.getField() + " " + fieldError.getDefaultMessage()); return "send"; } String[] addresses = form.getAddress().split("s*;s*"); boolean isValid = Stream.of(addresses) .anyMatch(address -> !Validator.isMailAddress(address)); if (isValid) { model.addAttribute("errorMessage", "Email address is invalid"); return "send"; } try { List<MailInfo> mailInfoList = new ArrayList<>(); String subject = form.getSubject(); String body = form.getBody(); for (String address : addresses) { Contact addressItem = addressBookService.findByAddress(address); String replacedSubject = subject; String replacedBody = body; if (addressItem != null) { if ("".equals(addressItem.getName()) && (subject.contains("$name") || body.contains("$name"))) { throw new Exception("Can't render template with an empty name in contact"); } replacedSubject = subject.replace("$name", addressItem.getName()); replacedBody = body.replace("$name", addressItem.getName()); }else { if (subject.contains("$name") || body.contains("$name")){ throw new Exception("No matching contact found to render template"); } } MailInfo mail = new MailInfo("gadget.mailsender@gmail.com", address, replacedSubject, replacedBody); mailInfoList.add(mail); } mailService.sendMultiple(mailInfoList); } catch (Exception e) { model.addAttribute("errorMessage", e.getMessage()); return "send"; } return "send"; }
  • 31. WHAT DID YOU SMELL? L O N G M E T H O D
  • 35. CODE SMELLS LONG METHOD TEMPORARY VARIABLE FEATURE ENVY DUPLICATE CODE MAGIC NUMBER UNCOMMUNICATIVE NAME PRIMITIVE OBSESSION
  • 36. sendEmail() BREAKS SINGLE RESPONSIBILITY MAIL CREATION ERROR HANDLING TEMPLATE RENDERING VALIDITY OF RECIPIENT ADDRESS
  • 37. REFACTORING EXTRACT METHOD INLINE VAR. / METHOD INTRODUCE PARAMETER RENAME MOVE METHOD
  • 38. TIPS
  • 39. LEARN TO SMELL THE CODE CODE SMELLS
  • 41.
  • 43. PROGRAMMING IS THE ART OF DOING ONE THING AT A TIME Michael Feathers TIPS
  • 44. REFACTORING WHY? WHAT? HOW? GET READY FOR CHANGE DESIGN CODE SMELLS
  • 45. HOW TO START ESSENTIAL SKILLS ▸ Explain the code with design principles ▸ Identify code smells ▸ Refactor either manually or through IDE ▸ Familiar working with unit/integration tests ▸ Familiar with the functionality you’re changing
  • 47. TEACH TO LEARN 1. CREATE CODE SMELLS EXERCISES 2. PRACTICE REMOVING THE SMELLS 3. INVITE PEOPLE TO REMOVE THE SMELLS 4. CODE REVIEW 5. DEMO
  • 49. TO LEVEL UP REVIEW THE CODE WITH A MENTOR, BE REFLECTIVE
  • 50. EXPERIENCED PROGRAMMERS DO NOT WRITE INFINITELY COMPLEX CODE; THEY WRITE CODE THAT’S BLINDINGLY SIMPLE 99 Bottles of OOP TIPS
  • 51.
  • 52. REFACTORING IS AN EXERCISE IN KINDNESS Kent Beck