Conception émergente

604 views

Published on

Published in: Technology, News & Politics
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
604
On SlideShare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Praticien lambda Je dois à mon blog d'être ici Envie de dialogue avec les personnes intéressées par les méthodes agiles Livre mes réflexions personnelles sur mon vécu en tant qu'évangéliste de l'agilité Attend vos réflexions
  • Conception émergente

    1. 1. Le TDD et la conception émergente <ul><ul><li>Olivier AZEAU </li></ul></ul><ul><ul><li>http://agilitateur.azeau.com </li></ul></ul><ul><ul><li>21 septembre 2007 </li></ul></ul>
    2. 2. <ul><li>Le Développement Dirigé par les Tests </li></ul><ul><li>A quoi cela sert-il ? </li></ul>Le TDD
    3. 3. <ul><li>A garantir une bonne couverture de test car chaque ligne de code est une réponse à un test qui ne réussit pas. </li></ul>Le TDD <ul><li>Le Développement Dirigé par les Tests </li></ul><ul><li>A quoi cela sert-il ? </li></ul>
    4. 4. <ul><li>A garantir une bonne couverture de test car chaque ligne de code est une réponse à un test qui ne réussit pas. </li></ul>Le TDD <ul><li>Le Développement Dirigé par les Tests </li></ul><ul><li>A quoi cela sert-il ? </li></ul><ul><li>Mais aussi à construire un logiciel par étapes élémentaires car chaque introduction de test est une opportunité pour faire évoluer la conception. </li></ul>
    5. 5. La conception émergente <ul><li>Approche « traditionnelle » : on conçoit, puis on code, puis on teste. </li></ul><ul><li>Constaté sur des cycles linéaires (cascade, V, ...) mais aussi itératifs. </li></ul>
    6. 6. La conception émergente <ul><li>Approche « traditionnelle » : on conçoit, puis on code, puis on teste. </li></ul><ul><li>Constaté sur des cycles linéaires (cascade, V, ...) mais aussi itératifs. </li></ul><ul><li>Pourquoi ? </li></ul><ul><li>Pourquoi ? Force de l'habitude ? </li></ul>
    7. 7. <ul><li>Pourquoi ? Force de l'habitude ? Ingénierie du mimétisme ? </li></ul>La conception émergente <ul><li>Approche « traditionnelle » : on conçoit, puis on code, puis on teste. </li></ul><ul><li>Constaté sur des cycles linéaires (cascade, V, ...) mais aussi itératifs. </li></ul><ul><li>Pourquoi ? </li></ul><ul><li>Pourquoi ? Force de l'habitude ? </li></ul>
    8. 8. <ul><li>Pourquoi ? Force de l'habitude ? Ingénierie du mimétisme ? </li></ul>La conception émergente <ul><li>Approche « traditionnelle » : on conçoit, puis on code, puis on teste. </li></ul><ul><li>Constaté sur des cycles linéaires (cascade, V, ...) mais aussi itératifs. </li></ul><ul><li>Pourquoi ? </li></ul><ul><li>Pourquoi ? Force de l'habitude ? </li></ul><ul><li>Pourquoi inverser la démarche ? </li></ul><ul><li>Parce que c'est mieux : rien ne prouve le contraire ! </li></ul>
    9. 9. La conception émergente <ul><li>Pourquoi est-ce mieux ? </li></ul><ul><li>Diminution de la complexité à appréhender </li></ul><ul><li>La seule façon d'être vraiment agile : « Embrace Change » </li></ul>
    10. 10. La conception émergente <ul><li>Pourquoi est-ce mieux ? </li></ul><ul><li>Diminution de la complexité à appréhender </li></ul><ul><li>La seule façon d'être vraiment agile : « Embrace Change » </li></ul>Temps Coût du changement « Traditionnel » Agile
    11. 11. <ul><li>Pourquoi ne l'avoir pas fait plus tôt ? </li></ul><ul><li>Maturité des techniques </li></ul><ul><li>Maturité des outils </li></ul>La conception émergente <ul><li>Pourquoi est-ce mieux ? </li></ul><ul><li>Diminution de la complexité à appréhender </li></ul><ul><li>La seule façon d'être vraiment agile : « Embrace Change » </li></ul>
    12. 12. <ul><li>TDD, xUnit </li></ul><ul><li>« Design for testability » (objet humble, injection de dépendance...) </li></ul><ul><li>« Test double » (mock, stub, ...) </li></ul><ul><li>http://xunitpatterns.com/ (Meszaros) </li></ul><ul><li>Refactoring (Fowler) </li></ul><ul><li>« The simplest thing that could possibly work » </li></ul><ul><li>Forte cohésion et faible couplage </li></ul>Techniques de développement
    13. 13. Un exemple <ul><li>Lecture de podcast </li></ul><ul><li>1er scénario : « L'utilisateur s'abonne à un flux de podcast et visualise la liste de ses éléments. » </li></ul>HTTP URL XML LISTE
    14. 14. HTTP URL XML LISTE
    15. 15. HTTP URL XML LISTE Podcast UI XML Fetcher Podcast Subscription
    16. 16. Podcast UI XML Fetcher Podcast Subscription
    17. 17. Podcast UI XML Fetcher Podcast Subscription
    18. 18. Podcast UI XML Fetcher Podcast Subscription
    19. 19. podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); Podcast UI XML Fetcher Podcast Subscription
    20. 20. podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    21. 21. MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    22. 22. MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    23. 23. MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    24. 24. MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    25. 25. IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    26. 26. IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } interface IXmlFetcher { string URL { set ; } } class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    27. 27. IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); mocks . VerifyAllExpectationsHaveBeenMet (); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } interface IXmlFetcher { string URL { set ; } } class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    28. 28. PodcastSubscription subscription = new PodcastSubscription ( mockUI , mockFetcher ); IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); mocks . VerifyAllExpectationsHaveBeenMet (); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } interface IXmlFetcher { string URL { set ; } } class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    29. 29. PodcastSubscription subscription = new PodcastSubscription ( mockUI , mockFetcher ); IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); mocks . VerifyAllExpectationsHaveBeenMet (); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } interface IXmlFetcher { string URL { set ; } } PodcastSubscription ( IPodcastUI ui IXmlFetcher fetcher ) { ui . InputPodcastId += delegate ( object sender , PodcastId id ){ fetcher . URL = &quot;http://server/podcast.xml&quot; ; }; } class PodcastId : EventArgs { PodcastId ( string url ) {} } Podcast UI XML Fetcher Podcast Subscription
    30. 30. PodcastSubscription subscription = new PodcastSubscription ( mockUI , mockFetcher ); IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); mocks . VerifyAllExpectationsHaveBeenMet (); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } interface IXmlFetcher { string URL { set ; } } PodcastSubscription ( IPodcastUI ui IXmlFetcher fetcher ) { ui . InputPodcastId += delegate ( object sender , PodcastId id ){ fetcher . URL = &quot;http://server/podcast.xml&quot; ; }; } class PodcastId : EventArgs { PodcastId ( string url ) {} } Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast2.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast2.xml&quot; ) ); Podcast UI XML Fetcher Podcast Subscription
    31. 31. PodcastSubscription ( IPodcastUI ui IXmlFetcher fetcher ) { ui . InputPodcastId += delegate ( object sender , PodcastId id ){ fetcher . URL = id . URL ; }; } PodcastSubscription subscription = new PodcastSubscription ( mockUI , mockFetcher ); IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); mocks . VerifyAllExpectationsHaveBeenMet (); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } interface IXmlFetcher { string URL { set ; } } class PodcastId : EventArgs { PodcastId ( string url ) {} } Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast2.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast2.xml&quot; ) ); Podcast UI XML Fetcher Podcast Subscription
    32. 32. PodcastSubscription ( IPodcastUI ui IXmlFetcher fetcher ) { ui . InputPodcastId += delegate ( object sender , PodcastId id ){ fetcher . URL = id . URL ; }; } PodcastSubscription subscription = new PodcastSubscription ( mockUI , mockFetcher ); IXmlFetcher mockFetcher = mocks . NewMock < IXmlFetcher >(); MockEvent < PodcastId > podcastIdEvent = new MockEvent < PodcastId >( mockUI , &quot;InputPodcastId&quot; ); Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast.xml&quot; ) ); IPodcastUI mockUI = mocks . NewMock < IPodcastUI >(); class PodcastId : EventArgs { string url ; PodcastId ( string url ) { this . url = url ;} string URL { get { return url ;} } } mocks . VerifyAllExpectationsHaveBeenMet (); interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; } interface IXmlFetcher { string URL { set ; } } Expect . Once . On ( mockFetcher ). SetProperty ( &quot;URL&quot; ). To ( &quot;http://server/podcast2.xml&quot; ); podcastIdEvent . Raise ( new PodcastId ( &quot;http://server/podcast2.xml&quot; ) ); Podcast UI XML Fetcher Podcast Subscription
    33. 33. Podcast UI XML Fetcher Podcast Subscription
    34. 34. Podcast UI XML Fetcher Podcast Subscription
    35. 35. interface IXmlFetcher { event EventHandler < XmlResult > RetrievedXml ; string URL { set ; } } Podcast UI XML Fetcher Podcast Subscription
    36. 36. interface IPodcastUI { event EventHandler < PodcastId > InputPodcastId ; IList<PodcastItem> Items { set ; } } interface IXmlFetcher { event EventHandler < XmlResult > RetrievedXml ; string URL { set ; } } Podcast UI XML Fetcher Podcast Subscription
    37. 37. IXmlFetcher Podcast Subscription IPodcastUI
    38. 38. IXmlFetcher Podcast Subscription IPodcastUI PodcastId
    39. 39. IXmlFetcher Podcast Subscription IPodcastUI PodcastId XmlResult
    40. 40. IXmlFetcher Podcast Subscription IPodcastUI PodcastId PodcastItem XmlResult
    41. 41. IXmlFetcher Podcast Subscription IPodcastUI PodcastId PodcastItem XmlResult XmlFetcher
    42. 42. IXmlFetcher Podcast Subscription IPodcastUI PodcastId PodcastItem XmlResult PodcastUI XmlFetcher
    43. 43. IXmlFetcher Podcast Subscription IPodcastUI PodcastId PodcastItem XmlResult PodcastUI XmlFetcher Main

    ×