Introduc)on	
  to	
  
           Test-­‐Driven	
  Development
           Driving	
  So7ware	
  Design	
  through
         ...
Agenda

         • Test-­‐Driven	
  Development	
  (TDD)
               – The	
  “Flow”
               – Integra)ng	
  wit...
Ques>ons	
  for	
  You...

         • How	
  many	
  of	
  you	
  are	
  prac>cing	
  TDD?
         • What	
  issues	
  ar...
Test-­‐Driven	
  Development


                           Basic	
  “Flow”	
  and	
  Constructs	
  of	
  TDD




          ...
TDD	
  -­‐	
  Basic	
  “Flow”




                                                                                        ...
TDD	
  -­‐	
  Basic	
  “Flow”


                                        Write	
  
                                     Fai...
TDD	
  -­‐	
  Basic	
  “Flow”


                                        Write	
  
                                     Fai...
TDD	
  -­‐	
  Basic	
  “Flow”


                                                        Write	
  
                        ...
TDD	
  -­‐	
  Basic	
  “Flow”


                                                        Write	
  
                        ...
Steps	
  of	
  TDD	
  “Flow”

         1.        Write	
  a	
  programmer	
  test
         2.        Run	
  the	
  program...
Be	
  a	
  User	
  -­‐-­‐
       “What	
  should	
  the	
  so^ware	
  do	
  next	
  for	
  
       me?”
                  ...
Test-­‐Driven	
  Development


                           Integra>ng	
  with	
  Teams




                                ...
Integra>ng	
  with	
  Team




                                                                                    9
     ...
Integra>ng	
  with	
  Team




                Write	
  
             Failing	
  Test



                                 ...
Integra>ng	
  with	
  Team


                                      Make	
  Test	
  
                                      ...
Integra>ng	
  with	
  Team


                                      Make	
  Test	
  
                                      ...
Integra>ng	
  with	
  Team


                                      Make	
  Test	
  
                                      ...
Integra>ng	
  with	
  Team


                                      Make	
  Test	
  
                                      ...
Integra>ng	
  with	
  Team


                                      Make	
  Test	
  
                                      ...
Need-­‐Driven	
  Design




                                                                                    10
       ...
Test-­‐Driven	
  Development


                           Why	
  Is	
  TDD	
  Important?




                             ...
Accrual	
  of	
  Quality	
  Debt




                             Copyright © 2010 Sterling Barton. All rights reserved.

...
Break/Fix	
  Only	
  Prolongs	
  It




                             Copyright © 2010 Sterling Barton. All rights reserved...
Effect	
  of	
  Project	
  Constraints	
  on	
  Quality




                                                               ...
Effect	
  of	
  Project	
  Constraints	
  on	
  Quality




                                                               ...
Managing	
  So^ware	
  Debt	
  –	
  an	
  Overview
                                                                       ...
Acceptance	
  Test-­‐Driven	
  Development

        Functional                       Implement
       Requirement         ...
Con>nuous	
  Integra>on




                                                                                    17
       ...
Test-­‐Driven	
  Development


                           What	
  Causes	
  TDD	
  to	
  be	
  so	
  Difficult	
  to	
  
   ...
Impediments	
  to	
  TDD

         This	
  simple	
  technique	
  for	
  developing	
  so^ware,	
  when	
  
          used...
Schedule	
  Pressure


                                    Pressure	
  from	
  management	
  and	
  
                     ...
Lack	
  of	
  Passion


                                  Lack	
  of	
  passion	
  for	
  learning	
  and	
  
            ...
Insufficient	
  Experience


                           Insufficient	
  team	
  member	
  ra>o	
  who	
  have	
  
            ...
Legacy	
  Code


                           If	
  the	
  so^ware’s	
  design	
  is	
  poor	
  or	
  is	
  difficult	
  to	
 ...
Introducing	
  TDD	
  Approach	
  Effec>vely


                            To	
  successfully	
  adopt	
  TDD,	
  it	
  is	...
Test-­‐Driven	
  Development


                               Quick	
  Example




                                       ...
Jieer	
  –	
  Example	
  TDD	
  Session

         • Fake	
  micro-­‐blogging	
  tool	
  named	
  “Jieer”	
  is	
  made	
  ...
Expand	
  LOL	
  to	
  “laughing	
  out	
  loud”

         public class WhenUsersWantToExpandMessagesThatContainShorthandT...
But	
  wait…what	
  if…?

         • What	
  if	
  LOL	
  is	
  wrieen	
  in	
  lower	
  case?
         • What	
  if	
  it...
Expand	
  LOL	
  If	
  Lower	
  Case

         @Test
         public void shouldExpandLOLIfLowerCase() {
                 ...
Don’t	
  Expand	
  “Lol”	
  –	
  Mixed-­‐Case

         @Test
         public void shouldNotExpandLOLIfMixedCase() {
     ...
Don’t	
  Expand	
  “LOL”	
  If	
  Inside	
  Word

         @Test
         public void shouldNotExpandLOLIfInsideWord() {
 ...
Expand	
  “LOL”	
  If	
  Not	
  Inside	
  Word

         @Test
         public void shouldExpandIfSurroundingCharactersAre...
Test-­‐Driven	
  Development


                                    Refactoring




                                       ...
Merciless	
  Refactoring

         • Refactoring:	
  a	
  disciplined	
  technique	
  for	
  restructuring	
  an	
  
     ...
Where	
  to	
  Start	
  Refactoring?

         • Does	
  this	
  change	
  directly	
  affect	
  feature	
  I	
  am	
  work...
When	
  to	
  Stop	
  Refactoring?

         • Am	
  I	
  refactoring	
  code	
  not	
  directly	
  affected	
  by	
  featu...
Automate	
  Tes>ng	
  to	
  Support	
  Refactoring

         • Refactoring	
  cannot	
  be	
  done	
  effec>vely	
  without...
Automated	
  Tests

                           Application




                                                           ...
Automated	
  Tests

                           Application




                 New
                Feature




          ...
Automated	
  Tests

                             Application




                 New       Design Changes
               ...
Automated	
  Tests

                             Application



                                                          ...
Automated	
  Tests

                             Application



                                                          ...
Principles	
  of	
  Agile	
  So^ware	
  Quality

         • The	
  system	
  always	
  runs	
  
         • No	
  code	
  i...
Thank	
  you


                            Ques>ons	
  and	
  Answers




                                                ...
Chris	
  Sterling
         • Technology	
  Consultant,	
  Cer>fied	
  Scrum	
  
           Trainer	
  and	
  Agile	
  Coach...
Upcoming SlideShare
Loading in...5
×

Intro To Tdd Agile Palooza

1,054

Published on

This presentation shows the basic steps to TDD, when to integrate with team members, why TDD is hard to implement, and an example of writing tests and code using TDD.

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,054
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
38
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Intro To Tdd Agile Palooza

  1. 1. Introduc)on  to   Test-­‐Driven  Development Driving  So7ware  Design  through Programmer  Tests Chris  Sterling Technology  Consultant,  Cer)fied  Scrum  Trainer,  and  Agile  Coach Friday, February 5, 2010
  2. 2. Agenda • Test-­‐Driven  Development  (TDD) – The  “Flow” – Integra)ng  with  Team • Reasons  for  TDD • Difficul>es  with  TDD • Example  TDD  Session • Refactoring 2 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  3. 3. Ques>ons  for  You... • How  many  of  you  are  prac>cing  TDD? • What  issues  are  you  having  currently  with  TDD? 3 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  4. 4. Test-­‐Driven  Development Basic  “Flow”  and  Constructs  of  TDD 4 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  5. 5. TDD  -­‐  Basic  “Flow” 5 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  6. 6. TDD  -­‐  Basic  “Flow” Write   Failing  Test 5 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  7. 7. TDD  -­‐  Basic  “Flow” Write   Failing  Test Make  Test   Pass 5 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  8. 8. TDD  -­‐  Basic  “Flow” Write   Failing  Test Refactor  to   Make  Test   Acceptable   Design Pass 5 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  9. 9. TDD  -­‐  Basic  “Flow” Write   Failing  Test Refactor  to   Make  Test   Acceptable   Design Pass 5 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  10. 10. Steps  of  TDD  “Flow” 1. Write  a  programmer  test 2. Run  the  programmer  test  and  it  should  fail  (red  bar) 3. Write  just  enough  code  to  make  failing  test  pass 4. Run  programmer  test  successfully  (green  bar) 5. Refactor  code  to  an  acceptable  design  (green  bar) RISK:  Pushing  out  refactoring  to  add  more  code  first.   Don’t  forget  to  refactor  frequently  to  an  acceptable   design. 6 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  11. 11. Be  a  User  -­‐-­‐ “What  should  the  so^ware  do  next  for   me?” This  ques>on  helps  you  to  decide  what  the   next  programmer  test  should  model 7 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  12. 12. Test-­‐Driven  Development Integra>ng  with  Teams 8 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  13. 13. Integra>ng  with  Team 9 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  14. 14. Integra>ng  with  Team Write   Failing  Test 9 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  15. 15. Integra>ng  with  Team Make  Test   Pass Write   Failing  Test 9 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  16. 16. Integra>ng  with  Team Make  Test   Pass Write   Integrate   Failing  Test with  Team 9 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  17. 17. Integra>ng  with  Team Make  Test   Pass Write   Refactor  to   Integrate   Acceptable   Failing  Test with  Team Design 9 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  18. 18. Integra>ng  with  Team Make  Test   Pass Write   Refactor  to   Integrate   Acceptable   Failing  Test with  Team Design 9 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  19. 19. Integra>ng  with  Team Make  Test   Pass Write   Refactor  to   Integrate   Acceptable   Failing  Test with  Team Design 9 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  20. 20. Need-­‐Driven  Design 10 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  21. 21. Test-­‐Driven  Development Why  Is  TDD  Important? 11 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  22. 22. Accrual  of  Quality  Debt Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  23. 23. Break/Fix  Only  Prolongs  It Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  24. 24. Effect  of  Project  Constraints  on  Quality 14 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  25. 25. Effect  of  Project  Constraints  on  Quality 14 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  26. 26. Managing  So^ware  Debt  –  an  Overview Effect of Managing Software Debt over time is extended preservation of software’s value Higher Software Value De pr Potential for Val eciat So ue D ion o depreciation is ftw u are e to f always there so De bt discipline is essential Minimum Acceptable Value Time Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  27. 27. Acceptance  Test-­‐Driven  Development Functional Implement Requirement Functionality Execute Draft Acceptance Test Cases Acceptance Test Cases Review Results Verify Results Accepted Modify Acceptance Test Cases 16 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  28. 28. Con>nuous  Integra>on 17 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  29. 29. Test-­‐Driven  Development What  Causes  TDD  to  be  so  Difficult  to   Implement  Well? 18 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  30. 30. Impediments  to  TDD This  simple  technique  for  developing  so^ware,  when   used  in  a  disciplined  manner,  will  enable  individuals   and  teams  to  improve  so^ware  quality.  The  discipline   necessary  to  do  TDD  is  not  easily  aeainable.  Following   is  a  list  of  environmental  issues  that  lowers  chances  of   effec>vely  implemen>ng  TDD  approach. 19 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  31. 31. Schedule  Pressure Pressure  from  management  and   stakeholders  to  release  based  on  an   unreasonable  plan.  Integrity  of  the  so^ware   is  always  sacrificed  when  the  plan  is   inflexible  and  unwilling  to  incorporate   20 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  32. 32. Lack  of  Passion Lack  of  passion  for  learning  and   implemen>ng  TDD  effec>vely  on  Team.   The  amount  of  discipline  required  makes   passion  extremely  helpful. 21 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  33. 33. Insufficient  Experience Insufficient  team  member  ra>o  who  have   experience  doing  TDD  well.  When  there  is   liele  experience  on  or  coaching  for  the   team  success  is  minimal. 22 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  34. 34. Legacy  Code If  the  so^ware’s  design  is  poor  or  is  difficult  to   test  then  finding  a  star>ng  point  could  seem   impossible.  If  legacy  code  is  large  and  contains   no,  or  only  minimal,  test  coverage  then   disciplined  TDD  will  not  show  visible  results  for   some  >me. 23 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  35. 35. Introducing  TDD  Approach  Effec>vely To  successfully  adopt  TDD,  it  is  important  to   manage  these  environmental  issues.  This  could   include  managing  expecta>ons,  providing  the   Team  support  from  a  coach,  and  enabling   sufficient  learning  of  tools  and  techniques   while  working  with  an  exis>ng  code  base. 24 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  36. 36. Test-­‐Driven  Development Quick  Example 25 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  37. 37. Jieer  –  Example  TDD  Session • Fake  micro-­‐blogging  tool  named  “Jieer”  is  made  by   Seaele-­‐based  fic>>ous  company  that  focuses  on   enabling  coffee  injected  folks  to  write  short  messages   and  have  common  online  messaging  shorthand   expanded  for  easy  reading.  The  user  story  we  are   working  on  is: So  it  is  easier  to  read  their  kid’s  messages,  Mothers  want   to  automa>cally  expand  common  shorthand  nota>on • The  acceptance  criteria  for  this  user  story  are: – LOL,  AFAIK,  and  TTYL  are  expandable – Expand  lower  and  upper  case  versions  of  shorthand 26 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  38. 38. Expand  LOL  to  “laughing  out  loud” public class WhenUsersWantToExpandMessagesThatContainShorthandTest { @Test public void shouldExpandLOLToLaughingOutLoud() { JitterSession session = mock(JitterSession.class); when(session.getNextMessage()).thenReturn("Expand LOL please"); MessageExpander expander = new MessageExpander(session); assertThat(expander.getNextMessage(), equalTo("Expand laughing out loud please")); } } public class MessageExpander { public String getNextMessage() { String msg = session.getNextMessage(); return msg.replaceAll("LOL", "laughing out loud"); } 27 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  39. 39. But  wait…what  if…? • What  if  LOL  is  wrieen  in  lower  case? • What  if  it  is  wrieen  as  “Lol”?  Should  it  be  expanded?   • What  if  some  varia>on  of  LOL  is  inside  a  word? • What  if  characters  surrounding  LOL  are  symbols,  not  leeers?   Write  these  down  as  upcoming  programmer  tests  as  comments  so  I   don’t  forget  them.   // shouldExpandLOLIfLowerCase // shouldNotExpandLOLIfMixedCase // shouldNotExpandLOLIfInsideWord // shouldExpandIfSurroundingCharactersAreNotLetters 28 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  40. 40. Expand  LOL  If  Lower  Case @Test public void shouldExpandLOLIfLowerCase() { when(session.getNextMessage()).thenReturn("Expand lol please"); MessageExpander expander = new MessageExpander(session); assertThat(expander.getNextMessage(), equalTo("Expand laughing out loud please")); } This  forced  use  of  java.u1l.regex.Pa6ern  to  handle  case  insensi1vity. public String getNextMessage() { String msg = session.getNextMessage(); return Pattern.compile("LOL”, Pattern.CASE_INSENSITIVE) .matcher(msg).replaceAll("laughing out loud"); } 29 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  41. 41. Don’t  Expand  “Lol”  –  Mixed-­‐Case @Test public void shouldNotExpandLOLIfMixedCase() { String msg = "Do not expand Lol please"; when(session.getNextMessage()).thenReturn(msg); MessageExpander expander = new MessageExpander(session); assertThat(expander.getNextMessage(), equalTo(msg)); } This  forced  me  to  stop  using  Pa6ern.CASE_INSENSITIVE  flag  in   pa6ern  compila1on.  Only  use  “LOL”  or  “lol”  for  replacement   criteria. public String getNextMessage() { String msg = session.getNextMessage(); return Pattern.compile("LOL|lol").matcher(msg) .replaceAll("laughing out loud"); 30 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  42. 42. Don’t  Expand  “LOL”  If  Inside  Word @Test public void shouldNotExpandLOLIfInsideWord() { String msg = "Do not expand PLOL or LOLP or PLOLP please"; when(session.getNextMessage()).thenReturn(msg); MessageExpander expander = new MessageExpander(session); assertThat(expander.getNextMessage(), equalTo(msg)); } The  pa6ern  matching  is  now  modified  to  use  spaces  around  each   varia1on  of  valid  LOL  shorthand. return Pattern.compile("sLOLs|slols").matcher(msg) .replaceAll("laughing out loud"); 31 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  43. 43. Expand  “LOL”  If  Not  Inside  Word @Test public void shouldExpandIfSurroundingCharactersAreNotLetters() { when(session.getNextMessage()).thenReturn("Expand .lol! please"); MessageExpander expander = new MessageExpander(session); assertThat(expander.getNextMessage(), equalTo("Expand .laughing out loud! please")); } The  final  implementa1on  of  pa6ern  matching  code  looks  as  follows. return Pattern.compile("bLOLb|blolb").matcher(msg) .replaceAll("laughing out loud"); 32 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  44. 44. Test-­‐Driven  Development Refactoring 33 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  45. 45. Merciless  Refactoring • Refactoring:  a  disciplined  technique  for  restructuring  an   exis>ng  body  of  code,  altering  its  internal  structure   without  changing  its  external  behavior.*   • Merciless:  having  or  showing  no  [mercy  -­‐  showing  great   kindness  toward  the  distressed]   • Relieve  your  distressed  code  through  kindness  and   disciplined  restructuring * From http://www.refactoring.com/ 34 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  46. 46. Where  to  Start  Refactoring? • Does  this  change  directly  affect  feature  I  am  working   on? • Would  change  add  clarity  for  feature  implementa>on? • Will  change  add  automated  tests  where  there  are   none? If  “yes”  to  any  ques>on  above,  ask  following  ques>on  to   decide  if  you  should  work  on  it  now: • At  first  glance,  does  refactoring  look  like  a  large   endeavor  involving  significant  por>ons  of  the  so^ware’s   components? 35 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  47. 47. When  to  Stop  Refactoring? • Am  I  refactoring  code  not  directly  affected  by  feature? • Is  other  code  directly  affected  by  feature  I  am  working  on   that  has  not  been  refactoring  sufficiently? • If  refactoring  is  exploding  feature  es>mate  given  to   Customer  then  I  should  bring  it  up  to  Team  to  decide  how   we  should  progress • If  Team  decides  that  refactoring  can  be  absorbed  into   current  itera>on  without  affec>ng  delivery  on  our   commitments  then  con>nue  refactor • If  refactoring  affects  commitments  then  bring  it  to   Customer  for  discussion  how  to  proceed 36 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  48. 48. Automate  Tes>ng  to  Support  Refactoring • Refactoring  cannot  be  done  effec>vely  without   automated  tests  surrounding  code   • Start  by  crea>ng  automated  test  which  fails   • If  difficult  to  create  at  unit  level  look  at  automated   acceptance  tests  from  func>onal  perspec>ve • Over  >me  look  for  ways  to  create  automated  unit  tests 37 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  49. 49. Automated  Tests Application 38 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  50. 50. Automated  Tests Application New Feature 38 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  51. 51. Automated  Tests Application New Design Changes Feature 38 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  52. 52. Automated  Tests Application Automated New Design Changes Regression Test Run Feature 38 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  53. 53. Automated  Tests Application Automated New Design Changes Regression Test Run Feature 38 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  54. 54. Principles  of  Agile  So^ware  Quality • The  system  always  runs   • No  code  is  wrieen  without  a  failing  test   • Zero  post-­‐itera>on  bugs * From “Flawless Iterations” presented by Alex Pukinskis at Agile 2005 39 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  55. 55. Thank  you Ques>ons  and  Answers 40 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  56. 56. Chris  Sterling • Technology  Consultant,  Cer>fied  Scrum   Trainer  and  Agile  Coach  at  Solu>onsIQ • Consults  on  so^ware  technology  across  a   spectrum  of  industries • Consults  organiza>ons  on  Agile   development,  management,  and   enterprise  prac>ces • Founder  of  Interna>onal  Associa>on  of   So^ware  Architects  (IASA)  Puget  Sound   chapter • University  of  Washington  Lecturer:  Agile   Developer  Cer>ficate  Program • Email:  CSterling@Solu>onsIQ.com • Blog:  hep://chrissterling.gepngagile.com 41 Copyright © 2010 Sterling Barton. All rights reserved. Friday, February 5, 2010
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×