Keeping code clean
Upcoming SlideShare
Loading in...5
×
 

Keeping code clean

on

  • 319 views

One of the main hindrances to teams being able to respond rapidly to new features are technical problems resulting from bad coding practices, also known as technical debt. Melissa and Brett will cover ...

One of the main hindrances to teams being able to respond rapidly to new features are technical problems resulting from bad coding practices, also known as technical debt. Melissa and Brett will cover Agile tools and practices that help development teams write better code and increase maintainability. Topics that will be covered include:

Pair programming
Automated Unit Testing
Refactoring
Test-Driven Development
Agile Architecture

Statistics

Views

Total Views
319
Views on SlideShare
76
Embed Views
243

Actions

Likes
0
Downloads
0
Comments
0

3 Embeds 243

http://www.bmchild.com 239
http://www.200please.com 3
http://prlog.ru 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Keeping code clean Keeping code clean Presentation Transcript

  • Keeping Code Clean Agile tools and practices for better code
  • Topics ● Pair Programming ● Automated Unit Testing ● Refactoring ● Test-Driven Development ● Agile Architecture
  • Pair Programming
  • Pair Programming
  • ● Continuous Code Review ● Better Design w/ Less Code ● Faster Problem Solving ● More People Familiar w/ System ● Team Grows Closer Pair Programming - Benefits
  • Pair Programming - Evidence
  • Pair Programming - Evidence Williams 2000 ● Efforts +15%, Schedule -43% Baheti 2002 ● Effort +2%, Schedule -49% Ciokowlski 2002 ● Effort +9%, Schedule -46%
  • Automated Unit Testing
  • What is Automated Unit Testing? Use of special software to control the execution of unit tests and the comparison of actual outcomes with predicted outcomes. To get full benefit run as part of the build process and schedule to run automatically once or twice a day.
  • Automated Unit Test Suite Benefits ● Unit tests find problems early in the development cycle ● Developers will be less afraid to change code ● Development process becomes more flexible ● Easier for a developer to take over code they are unfamiliar with (improves “Truck Factor”) ● Reduces need for manual testing ● Software development becomes more testable and repeatable
  • What is a Unit Test Case? ● A test for a single unit of functionality ● Each method tests a specific bit of functionality ● Automated by the test-runner framework
  • AAA Test Structure ● Structure: ○ Arrange ○ Act ○ Assert ● Benefits: ○ Readable ○ Consistent public class SalesTaxTest { private SalesTax unit; @Test public void TestCalculate() { unit = new SalesTax(); // ARRANGE double tax = unit.Calculate(10); // ACT Assert.assertEquals(tax, 0.9); // ASSERT } }
  • Unit Testing Best Practices ● Test simple stuff first ● Get it working - then test boundaries/exceptions ● Use assert ● Keep tests small & understandable ● Make test method names descriptive ● Keep tests independent of each other ● Avoid System.out messages ● Don’t repeat tests! Test once and trust it.
  • Test Doubles ● Stand in for a collaborating object e.g. database, webservice ● Create test independence ● Make tests run faster ● Types of Doubles ○ Fakes: working implementation e.g.fake web service ○ Mocks: preprogrammed with expectations ○ Stubs: provide canned answers to the test’s calls
  • Refactoring
  • Refactoring ● What is refactoring? ● Why refactor? ● When to refactor?
  • What is Refactoring? “A change to the system that leaves its behavior unchanged, but enhances some non-functional quality - simplicity, flexibility, understandability, performance” -- Kent Beck, Extreme Programing Explained (p. 179) “A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.” -- Martin Fowler, Refactoring (p. 53)
  • Why Refactor the Code? ● Prevent “design decay” ● Clean up messes ● Simplify ● Increase readability / understandability ● Find bugs ● Reduce debugging time ● Build in what we learn about the application ● It’s part of the creative process
  • When to Refactor ● Code reviews / TDD cycle ● Rule of three ○ cut & paste. Third time copying? Now is the time to generalize and move this to a new procedure. ● When you: ○ add functionality ○ learn something about the code ○ identify a code smell
  • What is a Code Smell? ● any symptom in the code that possibly indicates a deeper problem. ● not bugs - but indicate weaknesses in design that may be slowing down development or increasing the risk of bugs or failures in the future.
  • Code Smells (1/2) ● Duplicated code: near-identical code in multiple places ● Long method: a too large method/function/procedure ● Large class: a class that has grown too large. ● Too many parameters: decreases readability/quality. ● Identifier names are too short or excessively long ● Complex conditionals: branches that check lots of unrelated conditions and edge cases that don't seem to capture the meaning of a block of code.
  • Code Smells (2/2) ● Comments - refactor so these are no longer needed! ● Feature envy: excessive use of another class’ methods ● Inappropriate intimacy: a class that has dependencies on implementation details of another class. ● Lazy class / Freeloader: a class that does too little. ● Contrived complexity: simpler design would suffice. ● Excessive use of literals (use named constants)
  • Why Developers Resist Refactoring ● Lack of understanding ● Short-term focus ● Not paid for overhead tasks like refactoring ● Fear of breaking current program Use TDD to overcome this fear!
  • Test-Driven Development
  • TDD as a Design Approach ● Tests define up front what “works” means ● Programing by intention - write tests for what code intends to do not what the code you just wrote does. ● Focus on minimum set of required features ● Regular integration of small changes ● Evolutionary Design: Tests provide a safety net for refactoring.
  • Red-Green-Refactor Cycle
  • How to Get to Green? Implement it! Obvious Implementation code the real implementation, if it's obvious and can quickly make test pass, otherwise... public int Sum(int x, int y) { return x + y; }
  • How to Get to Green? Fake it Fake it hardcode constants to make test pass, gradually generalize code using variables public int Fibonacci(int n) { if (n >= 1) return 1; return 0; }
  • How to Get to Green? Triangulate Triangulate figure out the behavior of an algorithm by examining a couple of test cases instead of just one. public void TestSum() { Assert.AreEqual(4, Plus(3, 1)); Assert.AreEqual(7, Plus(4, 3)); }
  • Use TDD to Earn a Gift Card! TDD is a great tool to use in solving the code challenges. E.g. Function takes a Roman Numeral String and returns the Decimal value. ● Start with simple valid numbers I, III... up to more complex tests ● Incorporate tests for boundary conditions and invalid numbers ● With a set of tests you can easily refactor your solution. VALID NUMBERS INVALID NUMBERS I Boundary: Empty, 0, MMMM III iii IV IVIV, IIII, IIX, MXXXX VI, XLIX, MMMDCCCLXXXVIII ABCDEF
  • A Great TDD Example! ● Bowling Kata - how to score a bowling game. ● Eclipse and junit step-by-step presentation on red - green - refactor to solve (butunclebob. com/files/downloads/Bowling%20Game%20Kata.ppt)
  • Agile Architecture
  • ● Collaborative Design ● Good coding Standards and Principles Agile Architecture
  • Collaborative Design ● Emergent Design ○ Light Design Up Front (LDUF) ● Every team member contributes ● No command and control
  • Collaborative Design - payoff http://martinfowler.com/bliki/DesignStaminaHypothesis.html
  • Standards and Principles ● Agree as a team ○ coding and naming conventions ○ toolset ■ Static Code Analysis, Test mocks, etc ○ best practices ● Avoid Technical Debt ● Follow well established principles and patterns
  • Object Oriented Design Principles S ingle Responsibilty O pen/Closed L iskov Substitution I nterface Segregation D ependency Inversion
  • The Single Responsibility Principle ● Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility. ● Single Reason to Change
  • class Book { function getTitle() { return "A Great Book"; } function getAuthor() { return "John Doe"; } function turnPage() { // pointer to next page } function printCurrentPage() { echo "current page content"; } }
  • The Open/Closed Principle ● You should be able to extend a classes behavior without modifying it ● Open for extension, but closed for modification
  • public double Area(object[] shapes) { double area = 0; foreach (var shape in shapes) { if (shape is Rectangle) { Rectangle rectangle = (Rectangle) shape; area += rectangle.Width*rectangle.Height; } else { Circle circle = (Circle)shape; area += circle.Radius * circle.Radius * Math.PI; } } return area; }
  • The Liskov Substitution Principle ● Derived classes must be substitutable for their base classes
  • public class Rectangle { private int width; private int height; // setters and getters } public class Square extends Rectangle { public Square(int height, int width) { setWidth(width); setHeight(height); } }
  • The Interface Segregation Principle ● No client should be forced to depend on methods it does not use
  • interface Worker { void work(); void eat(); } class HumanWorker implements Worker { Public void work { /* do work stuff */ } Public void eat { /* eat stuff */ } } class RobotWorker implements Worker { Public void work { /* do work stuff */ } Public void eat { /* ACK! I don't eat! */ } } interface Worker { void work(); } interface Eater { void eat(); } class HumanWorker implements Worker, Eater { Public void work { /* do work stuff */ } Public void eat { /* eat stuff */ } } class RobotWorker implements Worker { Public void work { /* do work stuff */ } }
  • The Dependency Inversion Principle ● High-level modules should not depend on low-level modules. Both should depend on abstractions. ● Abstractions should not depend on details. Details should depend on abstractions.
  • class Worker { private FileWriter fileWriter; public Worker() { fileWriter = new FileWriter(); } } class Worker { private FileWriter fileWriter; public Worker(FIleWriter writer) { fileWriter = writer; } } interface FileWriter { // writer files or something }
  • Object Orient Patterns ● Common Design Patterns ○ Strategy, Command, Decorator, Adapter, etc ● Enterprise Integration Patterns
  • Acknowledgements Pair Programming: ● http://www.cs.pomona.edu/classes/cs121/supp/williams_prpgm.pdf ● http://collaboration.csc.ncsu.edu/laurie/Papers/ieeeSoftware.PDF SOLID ● http://lostechies.com/derickbailey/2009/02/11/solid-development-principles-in-motivational- pictures/ Content based on: ● SolutionsIQ CSD training slides ● http://en.wikipedia.org/wiki/Code_smell ● http://www.codeproject.com/Articles/5404/The-benefits-of-automated-unit-testing