<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8995878145266667696</id><updated>2011-10-23T12:45:39.432+02:00</updated><category term='ruby'/><category term='C#'/><category term='Orcas'/><category term='Haskell'/><category term='LINQ'/><category term='functionalprogramming'/><category term='ddd'/><category term='Entwurfsmuster'/><category term='Lambda'/><category term='Scrum'/><category term='tdd'/><category term='Patterns'/><category term='FunktionaleProgrammierung'/><category term='.NET'/><title type='text'>JENNIUS Software</title><subtitle type='html'>Passionate about developing software.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-7012750752602719718</id><published>2011-10-21T13:56:00.001+02:00</published><updated>2011-10-21T13:58:38.991+02:00</updated><title type='text'>Short abstract of HTML 5</title><content type='html'>I've recently finished reading&amp;nbsp;&lt;a href="http://www.prohtml5.com/"&gt;Pro HTML5 Programming&lt;/a&gt;. The book includes good examples, it is easy to read, and it's a nice introduction to HTML5. Some examples&amp;nbsp;unfortunately&amp;nbsp;didn't work but I guess they were based on an older version of the HTML5 specifications which wasn't supported by my browsers&amp;nbsp;any more.&lt;br /&gt;&lt;br /&gt;Following a brief summary of the new HTML5 features ordered by my view of their importance:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;HTML5 WebSocket:&amp;nbsp;&lt;/b&gt;This is a&amp;nbsp;lightweight duplex communication channel between server and websites and it offers a faster way to send small messages back and forth. A WebSocket can just be opened once the http communication has already been established ("Upgrading the http-connection to WebSocket")&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTML5 Web Workers:&amp;nbsp;&lt;/b&gt;A WebWorker is setup by a JavaScript and executes another JavaScript in parallel. Communication to and from WebWorkers is preferably implemented using 'Cross Document Messaging' or messaging via the Web Storage.&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTML5 Web Storage:&amp;nbsp;&lt;/b&gt;Stores key/value-pairs in either a session store or a local store. The stores are isolated by their origin (e.g: www.evil.com can't access values from www.example.com). There are events published by the store which are fired when a value changes. Those events can also be used to implement messaging between websites.&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTML5 Canvas: &lt;/b&gt;A simple API to render 2D-drawings from within the browser using Java-Script. It's also possible to read and modify parts of the canvas using bitmaps.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Communication APIs:&amp;nbsp;&lt;/b&gt;'Cross Document Messaging' allows sending messages and events between parts of a website even they are not from the same origin. (which hasn't been possible due to security&amp;nbsp;concerns before). 'XMLHttpRequest Level 2' allows the same for communication to the server. It means a website originating from 'example.net' can send XMLHttpRequests to different origins like 'example.net' and 'example.com' at the same time. The import part is that both sender and receiver of 'cross messages' have to be configured accordingly otherwise the communication is not possible due to security constraints.&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTML5 Geolocation:&lt;/b&gt;&amp;nbsp;A simple API to access the browser's geographical location. The method of how the location is determined is hidden away by the API. Depending on the kind of browser and hardware the accuracy of the measurement can vary greatly.&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTML5 Audio and Video: &lt;/b&gt;Embeds audio and video natively in HTML. Defines controls to play audio and video. Audio and video editing is not included.&lt;/li&gt;&lt;li&gt;&lt;b&gt;HTML5 Forms API: &lt;/b&gt;A bunch of new html tags and attributes that provide us with better semantics and therefore enable the browser to render more advanced or different controls. (e.g a control that just accepts&amp;nbsp;E-mail addresses)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;I'm really looking forward seeing where HTML5 will take us and what frameworks and&amp;nbsp;paradigms&amp;nbsp;will evolve around it. Will websites become more like&amp;nbsp;traditional&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Rich_client"&gt;rich clients&lt;/a&gt; now?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-7012750752602719718?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/7012750752602719718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=7012750752602719718' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/7012750752602719718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/7012750752602719718'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2011/10/short-abstract-of-html-5.html' title='Short abstract of HTML 5'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-8846508271203782408</id><published>2011-07-30T16:55:00.011+02:00</published><updated>2011-08-01T08:42:54.661+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Typing effort analyzer in Ruby</title><content type='html'>&lt;span style="font-family: inherit;"&gt;I've been working on RePhraser over &lt;span style="font-family: inherit;"&gt;the course of the last 6 months. &lt;span style="line-height: 115%; mso-ansi-language: EN-GB; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: &amp;quot;Times New Roman&amp;quot;; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"&gt;RePhraser is a piece of software which aims to help professionals in writing repetitive texts quickly&lt;/span&gt;. Unfortunately&amp;nbsp;I haven't been&amp;nbsp;able to make it available to a broader audience yet mainly due to the fact that it only works&lt;/span&gt; reliably&amp;nbsp;in Internet Explorer and that&amp;nbsp;there are&amp;nbsp;still&amp;nbsp;some basic features missing. Even so, I've uploaded a short demo &lt;/span&gt;&lt;a href="http://www.youtube.com/watch?v=qwwFQ6yWG_Q"&gt;&lt;span style="font-family: inherit;"&gt;here&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: inherit;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;RePhraser&amp;nbsp;assists you by anticipating and displaying&amp;nbsp;words&amp;nbsp;while you are typing them.&amp;nbsp;Imagine you being a&amp;nbsp;physician who writes the word "immunocytochemically". You would&amp;nbsp;start to type "immu" whereas RePhraser would bring up all the words that start with "immu". There would be simple words like "immune", "immunogen" or more complicated words like the aforementioned "immunocytochemically". In fact there are a lot of words that starts with "immu".&amp;nbsp;RePhraser would be pretty useless&amp;nbsp;if&amp;nbsp;it&amp;nbsp;displayed easy words like "immune" or "immunogen" at this point&amp;nbsp;because professional writers type those words much faster than RePhraser could display them. To solve this problem RePhraser uses a typing effort model. The basic idea is to display words which are harder to type first and&amp;nbsp;to ignore&amp;nbsp;words which are easy to write. To do so RePhraser rates every word based on the &lt;/span&gt;&lt;a href="http://mkweb.bcgsc.ca/carpalx/?typing_effort"&gt;&lt;span style="font-family: inherit;"&gt;carpalx typing effort model&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: inherit;"&gt;. The&lt;/span&gt;&lt;a href="http://mkweb.bcgsc.ca/carpalx/?typing_effort"&gt;&lt;span style="font-family: inherit;"&gt; carpalx typing effort model&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: inherit;"&gt; takes account of things like weak fingers (like pinky and ring finger), travel distance of fingers, same-finger typing (e.g "uhm"), balanced hand-use vs. right-hand priority etc...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;I implemented&amp;nbsp;the carpalx typing effort model in ruby and published source code and Gem on &lt;/span&gt;&lt;a href="https://github.com/Enceradeira/teanalyzer"&gt;&lt;span style="font-family: inherit;"&gt;https://github.com/Enceradeira/teanalyzer&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: inherit;"&gt;.&amp;nbsp;The project is named Teanalyzer, which is an abbreviation of typing effort analyzer.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;What do you think about Teanalyzer?&amp;nbsp;Or are you interested in RePhraser? Please drop a line or &lt;a href="mailto:info@jennius.co.uk"&gt;contact me&lt;/a&gt;!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-8846508271203782408?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/8846508271203782408/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=8846508271203782408' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8846508271203782408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8846508271203782408'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2011/07/typing-effort-analyzer-in-ruby.html' title='Typing effort analyzer in Ruby'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-3078360920842897118</id><published>2010-03-27T20:53:00.005+01:00</published><updated>2010-03-27T21:04:45.055+01:00</updated><title type='text'>My days at QCon 2010, London</title><content type='html'>This was my first visit at a QCon-conference and I was quite excited to see some of the 'famous' speakers&amp;nbsp;in the world of software development. There were such interesting talks on the schedule that I even missed out on the talks of &lt;a href="http://qconlondon.com/london-2010/speaker/Eric+Evans"&gt;Eric Evans&lt;/a&gt; and &lt;a href="http://qconlondon.com/london-2010/speaker/Martin+Fowler"&gt;Martin Fowler&lt;/a&gt;. May be next year!&lt;br /&gt;Generally I jumped between the different tracks but&amp;nbsp;attended more than one talk&amp;nbsp;from the tracks&amp;nbsp;&lt;a href="http://qconlondon.com/london-2010/tracks/show_track.jsp?trackOID=327"&gt;Software Craftsmanship&lt;/a&gt;, &lt;a href="http://qconlondon.com/london-2010/tracks/show_track.jsp?trackOID=325"&gt;Functional programming&lt;/a&gt;&amp;nbsp;and &lt;a href="http://qconlondon.com/london-2010/tracks/show_track.jsp?trackOID=329"&gt;Irresponsible Architectures and Unusual Architects&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Following talks were my personal&amp;nbsp;highlights (based on the speaker, importance to&amp;nbsp;me, and what I learned from it):&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://qconlondon.com/london-2010/file?path=/qcon-london-2010/slides/RobertC.Martin_BadCodeCraftsmanshipEngineeringAndCertification.pdf"&gt;&lt;strong&gt;Bad Code, Craftsmanship, Engineering, and Certification&lt;/strong&gt;&lt;/a&gt; by Robert C.Martin&lt;strong&gt;.&lt;/strong&gt; Nothing new, but nethertheless a very entertaining talk. The &lt;a href="http://vimeo.com/9981123"&gt;bad code video&lt;/a&gt; was phenomenal (especially with the depressing background music). He questioned if&amp;nbsp;bad code is written because of deadlines, laziness,&amp;nbsp; boredom or even job security ('I´m the only guy that can maintain that!'). He also&amp;nbsp;suggested&amp;nbsp;to follow &lt;a href="http://commons.oreilly.com/wiki/index.php/The_Boy_Scout_Rule"&gt;The Boy Scout Rule&lt;/a&gt;: "Always leave the campground cleaner than you found it". "The only way to go fast is to go well" was another of his wisdoms. And then he 'evangelized' agile practices like TDD, pair programming, CI etc... that leads us to what he calls&amp;nbsp;'Pride of Workmanship'.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://qconlondon.com/london-2010/file?path=/qcon-london-2010/slides/DanNorth_SharpeningTheTools.pdf"&gt;&lt;strong&gt;Sharpening the Tools&lt;/strong&gt;&lt;/a&gt;&amp;nbsp;by Dan North. Good speaker and motivator. He reflected on the way how we learn things (&lt;a href="http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition"&gt;the Dreyfuss model&lt;/a&gt;) and that therefore we are in everything that we learn a 'novice', 'advanced beginner',&amp;nbsp;'competent', 'proficient' or an 'expert'. He suggested that we have always to renew our skills due to the continuous development of new and more effective techniques in the area of software development:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Practise the basics&lt;/li&gt;&lt;li&gt;Learn from other people&lt;/li&gt;&lt;li&gt;Understand trends&lt;/li&gt;&lt;li&gt;Share knowledge&lt;/li&gt;&lt;li&gt;Maintain your toolbox ('Some tools are timeless, some are disposable')&lt;/li&gt;&lt;li&gt;Learn how to learn&lt;/li&gt;&lt;/ol&gt;&lt;a href="http://qconlondon.com/london-2010/file?path=/qcon-london-2010/slides/EmilEifrem_NotOnlySQLAlternativeDataPersistenceAndNeo4J.pdf"&gt;&lt;strong&gt;Not Only SQL: Alternative Data Persistence and Neo4J&lt;/strong&gt;&lt;/a&gt; by Emil Eifrém. It was the first time that I attended a talk about this subject and I was very&amp;nbsp;curious&amp;nbsp;about it. I realised soon that it's all about 'scalability'.&amp;nbsp;Like: ´what kind of datastore to you need if you are building a twitter-like-application´. Relational databases are strong with well structured not very complex data (e.g salary-list). NoSQL-datastores are better with more dynamically defined,&amp;nbsp;complex data (e.g: persons and their different relationships to each other). I learned that this is not the end of relational databases but that there are now other techniques available when it comes to storing large amount of complex,dynamic data. I&amp;nbsp;know now that a query like 'all friends of Peter that also know Sarah'&amp;nbsp;can be much more efficient and easier be build with a NoSQL-datastore (especially &lt;a href="http://en.wikipedia.org/wiki/Graph_database"&gt;graph-DB's&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://qconlondon.com/london-2010/file?path=/qcon-london-2010/slides/JohnHughes_TheJoyOfTesting.pdf"&gt;&lt;strong&gt;The Joy of Testing&lt;/strong&gt;&lt;/a&gt; by John Hughes. A very refreshing&amp;nbsp;but a little bit&amp;nbsp;academic&amp;nbsp;talk about TDD. The key idea is to abstract test-cases to&amp;nbsp;a set of test-'properties'. Think about a number of test-cases that test a method. Wouldn't it be nice to reduce those test-cases to one&amp;nbsp;unique description that could be run by a test-runner and that this test-runner would find edge-cases that you have never thought about it? I'm not (yet) able to apply this to my daily work but I'm still thinking about it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://qconlondon.com/london-2010/file?path=/qcon-london-2010/slides/JesperBoeg_KanbanCrossingTheLinePushingTheLimitOrRediscoveringTheAgileVision.pdf"&gt;&lt;strong&gt;Kanban - Crossing the line, pushing the limit or rediscovering the agile vision?&lt;/strong&gt;&lt;/a&gt; by Jesper Boeg. A good talk given by a convinced Kanban-evangelist. It was very interesting how deep they integrate product-owner, buisness-analysts and tester into the development process ('developers helps out business-analyst to write down stories if there is a temporary bottleneck'). Sounds like 'extreme scrumming' to me! (very short full development-cycles). I really like the idea of helping out each other so that we can cope with overloaded/under-staffed testers, productowner and business-analysts.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://qconlondon.com/sfile?path=/qcon-london-2010/slides/protected/UdiDahan_CommandQueryResponsibilitySegregation.pdf"&gt;&lt;strong&gt;Command-Query Responsibility Segregation&lt;/strong&gt;&lt;/a&gt; by Udi Dahan.&amp;nbsp;Generally he was saying that displayed data (query-part) could completely be&amp;nbsp;decoupled from the persisted data&amp;nbsp;and&amp;nbsp;on the other hand updating&amp;nbsp;the persisted data (command-part)&amp;nbsp;could be done using a much more sophisticated model (e.g: a strong domain-model or a asynchronous event queue etc...).&amp;nbsp;I already knew about this style but new to me was:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It's about how we build the UI and what business-services we offer to a user. I got the impression we should display less raw-data (e.g: less data-grids) and let the software behave more intelligent.&lt;/li&gt;&lt;li&gt;We could&amp;nbsp;deliberately display stale data (e.g: display a account-list with&amp;nbsp;title 'account-balance as it was on 25.4.2010 at 14:34h'). He says that this is usually no problem to a user.&lt;/li&gt;&lt;li&gt;We could try to build&amp;nbsp;much more&amp;nbsp;valuable commands (e.g: a reservation-system that&amp;nbsp;can ´book the best seats for a group of 12 persons were no&amp;nbsp;person must sit alone' instead of letting&amp;nbsp;the user to choose the seats by itself)&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://qconlondon.com/london-2010/presentation/Scenario-Driven+Development"&gt;&lt;strong&gt;Scenario-Driven Development&lt;/strong&gt;&lt;/a&gt; by Ben Butler-Cole (Unfortunately no slides available). In his talk he was suggesting not to do integration/acceptance-testing on a 'per-story' basis. He mentioned that this could lead to brittle tests and to maintenance problems. He suggested to identify a small number of 'key-scenarios' that spam in their final version several stories. A key-scenario for a banking-application could be: 'Poor guy wants to pay a bill´ that includes the stories 'User pays bill' (that is rejected due to insufficient balance),&amp;nbsp; 'User applies for a overdraft', 'Clerk manages overdraft application', 'User pays bill' (that is not anymore rejected). Scenarios are developed incrementally and extended when a story is going to be implemented. He also showed &lt;a href="http://www.thoughtworks-studios.com/agile-test-automation"&gt;Twist&lt;/a&gt;&amp;nbsp;that was developed by Thoughtworks to support Scenario-Driven Development.&amp;nbsp;An interesting thing is that Twist puts several layer on the top of the application layer, helping to manage reusability and maintainability of the tested UI.&amp;nbsp;These layers are called Scenario-Layer (the scenarios written with Twist, Workflow-Layer (commands like ´go to homepage´) and the Application-model (abstracting the underlying technology with drivers like Selenium). The Workflow-Layer and the Application-model have to be written in Java&amp;nbsp;and enjoy therefore all advantages of a modern programming-language (refactoring,abstraction, object-orientation etc...)&lt;br /&gt;&lt;br /&gt;I also attended following less interesting talks:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Functional Approaches To Parallelism and Concurrency &lt;/li&gt;&lt;li&gt;Demystifying monads &lt;/li&gt;&lt;li&gt;Living and working with aging software &lt;/li&gt;&lt;li&gt;The Counterintuitive Web &lt;/li&gt;&lt;li&gt;Patterns for the People &lt;/li&gt;&lt;li&gt;Transactions: Over Used or Just Misunderstood?&lt;/li&gt;&lt;li&gt;Fighting Layout Bugs &lt;/li&gt;&lt;li&gt;Test-Driven Development of Asynchronous Systems&lt;/li&gt;&lt;li&gt;Data Presentation in a Web App: The Journey of a Startup&lt;/li&gt;&lt;li&gt;Death by accidental complexity &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-3078360920842897118?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/3078360920842897118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=3078360920842897118' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/3078360920842897118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/3078360920842897118'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2010/03/my-days-at-qcon-2010-london.html' title='My days at QCon 2010, London'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-2330169972071817012</id><published>2009-10-22T16:43:00.025+02:00</published><updated>2011-01-19T20:43:23.574+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='ddd'/><title type='text'>Sample Application with White,WPF,TDD and DDD</title><content type='html'>I'm currently thinking about what we could do better on a next project avoiding some technical issues that we have had in our latest project. Some of the issues were&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The &lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html"&gt;Passive View&lt;/a&gt; implementation for our Win-Form client was too costly. The design of it wasn't intuitive and straight forward at all.&lt;/li&gt;&lt;li&gt;The Passive View implementation didn't allow us to unit-test the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;UI&lt;/span&gt;. Even we were able to test the presenters we still couldn't test the event- and data binding automatically . &lt;/li&gt;&lt;li&gt;Our initial plan to do acceptance- and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;integrationtesting&lt;/span&gt; with &lt;a href="http://www.automatedqa.com/products/testcomplete/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;TestComplete&lt;/span&gt;&lt;/a&gt; failed. No tests have ever been written with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;TestComplete&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Our testing-suite runs too slow. The whole suite was too slow and even running one single test took too much time.&lt;/li&gt;&lt;li&gt;We struggled with &lt;a href="http://domaindrivendesign.org/node/88"&gt;Aggregates&lt;/a&gt; and domain logic leaked sometimes into the presentation layers.&lt;/li&gt;&lt;li&gt;The application is too slow. This was caused due the fact that we couldn't react appropriately when we were forced to move our 2-tier implementation to a 3-tier implementation. &lt;/li&gt;&lt;/ol&gt;I've recently written a sample application to find answers to some of those problems. You can download the application from this &lt;a href="http://www.2shared.com/file/vdtAcuva/OrderExploration.html"&gt;site&lt;/a&gt; (Click 'Save file to your PC' at the end of the site).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I'm going to explain my thoughts in detail maybe later, but the most interesting points in the sample application are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;WPF&lt;/span&gt;&lt;/a&gt;+&lt;a href="http://www.codeplex.com/white"&gt;White&lt;/a&gt;:&lt;/strong&gt; White allows testing the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;UI&lt;/span&gt; right from inside the unit-test runner. Following some basic principals it allows to script the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;UI&lt;/span&gt; right from the c#-code. But I used White just to Unit-Test the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;UI&lt;/span&gt; and to write some basic integration tests. I don't believe that one should use White to do more than that otherwise he might get some serious maintenance issues. For details see&lt;strong&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;OrderExploration&lt;/span&gt;.Test\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;UnitTest&lt;/span&gt;\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Ui&lt;/span&gt; &lt;/strong&gt;and &lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;OrderExploration&lt;/span&gt;.Test\Integration&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://en.wikipedia.org/wiki/Acceptance_testing"&gt;Acceptance-Testing&lt;/a&gt;: &lt;/strong&gt;I think acceptance-testing frameworks are a weak point of the .net-world. Either they require a lot of infrastructure (like &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;wiki's&lt;/span&gt;) or they can't be used by "none &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;technical's&lt;/span&gt;". &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;&lt;a href="http://nbehave.org/"&gt;NBehave&lt;/a&gt;&lt;/span&gt; is useless because it can't be used by "none technical's" and it doesn't produce readable code at all (That statement is maybe wrong with Version 0.4, but I didn't check). &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;FitNess&lt;/span&gt; is far too complicated for a small project like the sample application. I tried &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;StoryTeller&lt;/span&gt; as well, but there is not a lot of documentation available yet, so I gave up. So why not using pure old &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;nunit&lt;/span&gt;-tests if there are no "none &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;technical's&lt;/span&gt;"? For details see &lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;OrderExploration&lt;/span&gt;.Test\Acceptance&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://dddstepbystep.com/wikis/ddd/persistence-ignorance.aspx"&gt;Persistence-Ignorance&lt;/a&gt;: &lt;/strong&gt;There is just one test that hits the database (see &lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;OrderExploration&lt;/span&gt;.Test\Integration&lt;/strong&gt;). All other tests (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;UI&lt;/span&gt;, unit &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;und&lt;/span&gt; acceptance) run against stubs. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Test-Setups: &lt;/strong&gt;To setup Unit- Acceptance- and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;Integrationtest&lt;/span&gt; differently I used &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;SetupFixtures&lt;/span&gt; (I didn't know them before!). Lookout for classes with name "&lt;a href="http://www.nunit.org/index.php?p=setupFixture&amp;amp;r=2.4"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;SetupFixture&lt;/span&gt;&lt;/a&gt;"&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;CQS&lt;/span&gt; (Command-Query &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;Seperation&lt;/span&gt;) &lt;/strong&gt;&lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2009/10/08/the-catalogue-metaphor-and-command-query-seperation-architectures.aspx"&gt;&lt;strong&gt;inspired by a Ian Cooper&lt;/strong&gt;&lt;/a&gt;: I tried to separate querying data (mainly for displaying on view) and commanding (mainly for updating on aggregates). I'm not sure if I really got it right! For an example see method &lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;DataService&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;GetOrders&lt;/span&gt;()&lt;/strong&gt; that queries data right from the database and see &lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;OrderService&lt;/span&gt;.Submit()&lt;/strong&gt; that writes changes through the aggregate to the database.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Aggregates&lt;/strong&gt;: See the class Order that defines an Aggregate-Root. I tried to build an expressive aggregate by separating the aggregate from its persisted structure (see class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;OrderRow&lt;/span&gt;) and its displayed structure (see class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;OrderDetailData&lt;/span&gt;). If there is an interest I would like to discuss that decision later. For now see method Order.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;AddTag&lt;/span&gt;() and think about: 1.) If the class Order were directly bound to the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;UI&lt;/span&gt;, how would you handle the fact that the user can add/remove tags several time but just the last state should be persisted and logged in the history. 2.) If the class Order were persisted directly, how would you handle the fact that tags are persisted as strings? (see Order.Tags in the database-scheme)&lt;/li&gt;&lt;li&gt;and &lt;a href="http://structuremap.sourceforge.net/Default.htm"&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;StructureMap&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt; and &lt;strong&gt;&lt;a href="http://www.codeplex.com/AutoMapper"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;AutoMapper&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt; ... of course!&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;White is cool and helps to (Unit)-test &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;UI&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Persistence Ignorance can be implemented and helps to make Unit-/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;UI&lt;/span&gt;-/Acceptance tests much faster&lt;/li&gt;&lt;li&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;CQS&lt;/span&gt; (Command-Query-Separation), &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;ViewModels&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;DomainModel&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;PersistenceModel&lt;/span&gt; add another layer of indirection that can help to solve tricky problems quite &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;easly&lt;/span&gt;. However, these indirections can be a huge overkill for simple applications. I have no doubts that it's worth to have &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;ViewModels&lt;/span&gt; (including all kind of MVP,&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;MVC&lt;/span&gt;) but I'm not sure when it's worth to separate &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;DomainModel&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;PersistenceModel&lt;/span&gt;. In the sample application, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;DDD&lt;/span&gt; (e.g Repository-Pattern) helped me to answer that question per Aggregate. In the sample application the Aggregate Order has a separated &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;DomainModel&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;PersistenceModel&lt;/span&gt;. For the other Aggregates &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;DomainModel&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;PersistenceModel&lt;/span&gt; are the same. Any thoughts about that?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-2330169972071817012?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/2330169972071817012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=2330169972071817012' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2330169972071817012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2330169972071817012'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2009/10/sampleapplication-with-whitewpftdd-and.html' title='Sample Application with White,WPF,TDD and DDD'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-5847853701635784606</id><published>2009-08-03T21:28:00.003+02:00</published><updated>2009-08-03T21:54:58.014+02:00</updated><title type='text'>IObservable ... it's so beautiful</title><content type='html'>I've just watched &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Brian-Beckman-and-Erik-Meijer-Inside-the-NET-Reactive-Framework-Rx/"&gt;Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx)&lt;/a&gt; and it's again a great work of Erik, Wes and their team.&lt;br /&gt;&lt;br /&gt;It's a petty that I couldn't understand all that formalism but i enjoyed it like art and i'm impressed about the beauty and completness of their solution. That's the first mind-blowing feature of .NET 4.0!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-5847853701635784606?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/5847853701635784606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=5847853701635784606' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5847853701635784606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5847853701635784606'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2009/08/iobservable-its-so-beautiful.html' title='IObservable ... it&apos;s so beautiful'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-9080563593736143981</id><published>2009-07-26T20:51:00.005+02:00</published><updated>2009-07-27T22:12:27.086+02:00</updated><title type='text'>Object Role Stereotypes</title><content type='html'>I had a short discussions with my college Jürg last week about that classes in object oriented design (especially DDD or &lt;a href="http://www.wirfs-brock.com/PDFs/A%20Brief%20Tour%20of%20RDD%20in%202004.pdf"&gt;RDD&lt;/a&gt;) can be classified regarding their responsibility and behaviour. Neither could I remember the name for that concept nor any of those classifications. Jürg mentioned that this is like stereotypes in UML. I looked it up now and he wasn't wrong. They are called &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc721605.aspx"&gt;'Object Role Stereotypes'&lt;/a&gt;. Not that Object Role Stereotypes are defined by the UML specification but one could use stereotypes in UML to classify classes by their Object Role Stereotype&lt;strong&gt;. &lt;/strong&gt;Here are the stereotypes that I found:&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Controller&lt;/strong&gt; – Controls application execution. Makes decisions and delegates to other classes. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Service Provider&lt;/strong&gt; – Provides a service to other classes. Performs a calculation, computation, or executes business rules. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Interfacer&lt;/strong&gt; – Communicates actions to other layers or systems. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Information Holder&lt;/strong&gt; – Holds facts. Domain classes. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Structurer &lt;/strong&gt;– Maintains relationships between other classes&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-9080563593736143981?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/9080563593736143981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=9080563593736143981' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/9080563593736143981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/9080563593736143981'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2009/07/object-role-stereotypes.html' title='Object Role Stereotypes'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-5174435411096982383</id><published>2009-03-15T17:04:00.006+01:00</published><updated>2009-03-15T17:29:09.671+01:00</updated><title type='text'>How to get the console output working with NBehave 0.4 and the ReSharper Testrunner</title><content type='html'>When working with the latest build of NBehave 0.4 you may notice that there is no output written to the ReSharper Testrunner Output anymore.&lt;br /&gt;&lt;br /&gt;Here is how I did workaround the problem. I derived the specs from the following class and every thing was fine again:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public class SpecBaseWithConsoleOutput: SpecBase&lt;br /&gt;{&lt;br /&gt;  private EventHandler&amp;lt;EventArgs&amp;lt;MessageEventData&amp;gt;&amp;gt; addedHandler;&lt;br /&gt;  private EventHandler&amp;lt;EventArgs&amp;lt;Scenario&amp;gt;&amp;gt; scenarioCreatedHandler;&lt;br /&gt;  private EventHandler&amp;lt;EventArgs&amp;lt;Story&amp;gt;&amp;gt; storyCreatedHandler;&lt;br /&gt;  public override void MainSetup()&lt;br /&gt;  {&lt;br /&gt;    base.MainSetup();&lt;br /&gt;    addedHandler = (o, a) =&amp;gt; Console.WriteLine(a.EventData.Message);&lt;br /&gt;    scenarioCreatedHandler = (o, a) =&amp;gt; Console.WriteLine(a.EventData.Title);&lt;br /&gt;    storyCreatedHandler = (o, a) =&amp;gt; Console.WriteLine(a.EventData.Title);&lt;br /&gt;    Story.MessageAdded += addedHandler;&lt;br /&gt;    Story.ScenarioCreated += scenarioCreatedHandler;&lt;br /&gt;    Story.StoryCreated += storyCreatedHandler;&lt;br /&gt;  }&lt;br /&gt;  public override void MainTeardown()&lt;br /&gt;  {&lt;br /&gt;    Story.MessageAdded -= addedHandler;&lt;br /&gt;    Story.ScenarioCreated -= scenarioCreatedHandler;&lt;br /&gt;    Story.StoryCreated -= storyCreatedHandler;&lt;br /&gt;    base.MainTeardown();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-5174435411096982383?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/5174435411096982383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=5174435411096982383' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5174435411096982383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5174435411096982383'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2009/03/how-to-get-console-output-working-with.html' title='How to get the console output working with NBehave 0.4 and the ReSharper Testrunner'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-8418020510320517068</id><published>2009-01-24T11:27:00.009+01:00</published><updated>2009-01-24T12:08:04.868+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Implementing and testing mapping code with AutoMapper</title><content type='html'>&lt;a href="http://enceradeira.blogspot.com/2008/07/tdd-design-and-testability.html"&gt;I was thinking some months ago&lt;/a&gt; that it would be great to have a property mapper that eliminates tedious mapping code . I'm very happy that Jimmy Bogard and his team just have published a framework called &lt;a href="http://www.codeplex.com/AutoMapper"&gt;AutoMapper&lt;/a&gt; that resolves that issue. I haven't tested it yet but the idea looks promising.&lt;br /&gt;&lt;br /&gt;Why would I use AutoMapper?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;In order to implement better encapsulation and layering with less amount of coding&lt;/li&gt;&lt;li&gt;In order to unit-test mapping code using a simple 'Mapper.AssertConfigurationIsValid()'&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-8418020510320517068?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/8418020510320517068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=8418020510320517068' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8418020510320517068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8418020510320517068'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2009/01/implementing-and-testing-mapping-code.html' title='Implementing and testing mapping code with AutoMapper'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-1477175550344930918</id><published>2009-01-11T09:54:00.002+01:00</published><updated>2009-01-13T21:04:55.601+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>TypeMockAutoMocker on CodePlex</title><content type='html'>I' ve just uploaded the TypeMockAutoMocker to &lt;a href="http://www.codeplex.com/typemockautomocker"&gt;http://www.codeplex.com/typemockautomocker&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;How to use it:&lt;br /&gt;1.) &lt;a href="http://www.codeplex.com/typemockautomocker/Release/ProjectReleases.aspx?ReleaseId=21614"&gt;Download&lt;/a&gt; TypeMockAutoMocker.dll&lt;br /&gt;2.) Copy it to your project and set an assembly reference to it&lt;br /&gt;2.) Set 'Copy local = true' on your TypeMock.dll&lt;br /&gt;3.) Have fun (see &lt;a href="http://enceradeira.blogspot.com/2009/01/automocking-container-with-typemock.html"&gt;Link&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;StructureMap 2.5.1 and TypeMock 5.1.2 ist the only tested configuration at the moment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-1477175550344930918?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/1477175550344930918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=1477175550344930918' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1477175550344930918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1477175550344930918'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2009/01/typemockautomocker-on-codeplex.html' title='TypeMockAutoMocker on CodePlex'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-6964880132047870022</id><published>2009-01-02T08:20:00.031+01:00</published><updated>2009-01-03T11:31:36.708+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>AutoMocking Container with TypeMock Isolator</title><content type='html'>I have implemented an AutoMocking container for the Isolator inspired by an &lt;a href="http://www.dimecasts.net/Casts/CastDetails/62"&gt;Introduction to the AutoMocking container in StructureMap&lt;/a&gt;, the fact that our test setups usually are pretty messy and &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/02/09/automocker-in-structuremap-2-5.aspx"&gt;Jeremy's claim that TypeMock users probably don't care about dependency injection&lt;/a&gt;. But why do I want to use DI (Dependency Injection) in conjunctions with TypeMock? I don't want to fight a 'religious war' based on that question, but here is what I think:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;TypeMock without DI lacks an explicit boundary that defines what the class under tests is and which classes are mocks or stubs. This is about &lt;a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;solid design&lt;/a&gt; and to isolate parts of the software in a structured manner. It’s true that you can mock everything with TypeMock but this is just about mocking and not about software design. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;DI with another mocking framework than TypeMock is like .NET without System.Reflection. I don't like to use System.Reflection but sometimes it's just the right thing. It’s the same with TypeMock. If everything (own code, legacy-code, external libraries etc.) had a &lt;a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;solid design&lt;/a&gt; you wouldn't need it but sometime it makes the life so much easier.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Example without Dependency Injection&lt;/strong&gt;&lt;br /&gt;There is the class under test called ValidationViewPresenter and it has following dependencies:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_hcGoxuElMbw/SV80cEzHi8I/AAAAAAAAADY/mN0X7F_HNwM/s1600-h/ClassDiagram1.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5287002144485379010" style="WIDTH: 400px; CURSOR: hand; HEIGHT: 236px" alt="" src="http://1.bp.blogspot.com/_hcGoxuElMbw/SV80cEzHi8I/AAAAAAAAADY/mN0X7F_HNwM/s400/ClassDiagram1.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A a test without DI could look like:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;[Test]&lt;br /&gt;public void CanValidateCreditCardNumber()&lt;br /&gt;{&lt;br /&gt;  // Arrange&lt;br /&gt;  var viewMock = Isolate.Fake.Instance&amp;lt;ValidationView&amp;gt;();&lt;br /&gt;  var customerServiceMock = Isolate.Fake.Instance&amp;lt;CustomerService&amp;gt;();&lt;br /&gt;  var creditCardServiceMock = Isolate.Fake.Instance&amp;lt;CreditcardService&amp;gt;();&lt;br /&gt;  var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};&lt;br /&gt;&lt;br /&gt;  // Mock the (hidden) dependencies&lt;br /&gt;  Isolate.Swap.NextInstance&amp;lt;ValidationView&amp;gt;().With(viewMock);&lt;br /&gt;  Isolate.Swap.NextInstance&amp;lt;CustomerService&amp;gt;().With(customerServiceMock);&lt;br /&gt;  Isolate.Swap.NextInstance&amp;lt;CreditcardService&amp;gt;().With(creditCardServiceMock);&lt;br /&gt;  // Mock the calls to the dependencies&lt;br /&gt;  Isolate.WhenCalled(()=&gt;viewMock.CustomerNr).WillReturn(56);&lt;br /&gt;  Isolate.WhenCalled(() =&gt; customerServiceMock.GetCustomer(56)).WillReturn(customer56);&lt;br /&gt;  Isolate.WhenCalled(()=&gt; creditCardServiceMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);&lt;br /&gt;&lt;br /&gt;  // Act&lt;br /&gt;&lt;pre style="BACKGROUND-COLOR: #a9f5a9"&gt;  var presenter = new ValidationViewPresenter();&lt;/pre&gt;&lt;br /&gt;  presenter.ValidateCreditCardOfCustomer();&lt;br /&gt;  // Assert&lt;br /&gt;  Isolate.Verify.WasCalledWithExactArguments(() =&gt; viewMock.IsValid = true);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Example with Dependency Injection&lt;/strong&gt;&lt;br /&gt;After introducing constructor injection it looks like:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;[Test]&lt;br /&gt;public void CanValidateCreditCardNumber()&lt;br /&gt;{&lt;br /&gt;  // Arrange&lt;br /&gt;  var viewMock = Isolate.Fake.Instance&amp;lt;ValidationView&amp;gt;();&lt;br /&gt;  var customerServiceMock = Isolate.Fake.Instance&amp;lt;CustomerService&amp;gt;();&lt;br /&gt;  var creditCardServiceMock = Isolate.Fake.Instance&amp;lt;CreditcardService&amp;gt;();&lt;br /&gt;  var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};&lt;br /&gt;  // Inject dependencies manually&lt;br /&gt;&lt;pre style="BACKGROUND-COLOR: #a9f5a9"&gt;  var presenter = new ValidationViewPresenter(viewMock, customerServiceMock, creditCardServiceMock);&lt;/pre&gt;&lt;br /&gt;  Isolate.WhenCalled(()=&gt; viewMock.CustomerNr).WillReturn(56);&lt;br /&gt;  Isolate.WhenCalled(() =&gt; customerServiceMock.GetCustomer(56)).WillReturn(customer56);&lt;br /&gt;  Isolate.WhenCalled(() =&gt; creditCardServiceMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);&lt;br /&gt;&lt;br /&gt;  // Act&lt;br /&gt;  presenter.ValidateCreditCardOfCustomer();&lt;br /&gt;&lt;br /&gt;  // Assert&lt;br /&gt;  Isolate.Verify.WasCalledWithExactArguments(() =&gt; viewMock.IsValid = true);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Example with Automocking Container&lt;/strong&gt;&lt;br /&gt;Let's eliminate the explicit constructor injection by introducing the TypeMockAutoMocker now:&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;[Test]&lt;br /&gt;public void CanValidateCreditCardNumber()&lt;br /&gt;{&lt;br /&gt;  // Arrange&lt;br /&gt;  var customer56 = new Customer {CreditCardNr = "5500 0001 0001 0001"};&lt;br /&gt;&lt;pre style="BACKGROUND-COLOR: #a9f5a9"&gt;  var presenterMocker = new TypeMockAutoMocker&amp;lt;ValidationViewPresenter&amp;gt;(MockMode.AAA);&lt;/pre&gt;&lt;br /&gt;  var viewMock = presenterMocker.Get&amp;lt;IValidationView&amp;gt;();&lt;br /&gt;  var customerServiceMock = presenterMocker.Get&amp;lt;ICustomerService&amp;gt;();&lt;br /&gt;  var creditCardServcieMock = presenterMocker.Get&amp;lt;ICreditCardService&amp;gt;();&lt;br /&gt;&lt;br /&gt;  Isolate.WhenCalled(() =&gt; viewMock.CustomerNr).WillReturn(56);&lt;br /&gt;  Isolate.WhenCalled(() =&gt; customerServiceMock.GetCustomer(56)).WillReturn(customer56);&lt;br /&gt;  Isolate.WhenCalled(() =&gt; creditCardServcieMock.ValidateCreditCard("5500 0001 0001 0001")).WillReturn(true);&lt;br /&gt;&lt;br /&gt;  // Act&lt;br /&gt;  presenterMocker.ClassUnderTest.ValidateCreditCardOfCustomer();&lt;br /&gt;&lt;br /&gt;  // Assert&lt;br /&gt;  Isolate.Verify.WasCalledWithExactArguments(() =&gt; viewMock.IsValid = true);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;As you can see the AutoMocking container couldn’t eliminate a lot of complexity. This is due to the fact that the test itself is complex and there are a number of non-default preconditions.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;A better example with AutoMocking Container &lt;/strong&gt;&lt;br /&gt;Following code tests the same method but with different preconditions again. But this time we can rely on the default behavior that was setup by the AutoMocking container. This means that all involved and not explicitly mocked interfaces or classes do have a default behavior.&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;[Test]&lt;br /&gt;public void CanHandleNotExistingCustomer()&lt;br /&gt;{&lt;br /&gt;  // Arrange&lt;br /&gt;&lt;pre style="BACKGROUND-COLOR: #a9f5a9"&gt;  var presenterMocker = new TypeMockAutoMocker&amp;lt;ValidationViewPresenter&amp;gt;(MockMode.AAA);&lt;/pre&gt;&lt;br /&gt;  var viewMock = presenterMocker.Get&amp;lt;IValidationView&amp;gt;();&lt;br /&gt;  Isolate.WhenCalled(() =&gt; viewMock.CustomerNr).WillReturn(56);&lt;br /&gt;&lt;br /&gt;  // Act&lt;br /&gt;  presenterMocker.ClassUnderTest.ValidateCreditCardOfCustomer();&lt;br /&gt;&lt;br /&gt;  // Assert&lt;br /&gt;  Isolate.Verify.WasCalledWithExactArguments(() =&gt; viewMock.IsValid = false);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br /&gt;There is a big chance that you can get lost using TypeMock and StructureMap in conjunction. The problem is that there are too many ways how they can be combined. However I hope that the TypeMockAutoMocker could help in a way that it's defining a common pattern for how to setup the tests and how to inject the mocks. Remember always:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Depended classes are instantiated by the AutoMocker automatically.&lt;br /&gt;&lt;li&gt;Depended interfaces and abstract classes are instantiated as mocks. These mocks do have a default behaviour where every method can be called.&lt;br /&gt;&lt;li&gt;Depended concrete classes are instantiated by calling its greediest constructor. They are not mocked.&lt;br /&gt;&lt;li&gt;To change the default behaviour you can use Inject() to register your own mock to the AutoMocker. It's how you can setup a mock manually.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Sound’s like ‘&lt;a href="http://en.wikipedia.org/wiki/Convention_over_Configuration"&gt;convention over configuration’&lt;/a&gt;. And that makes life definitely easier.&lt;/p&gt;&lt;pre&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-6964880132047870022?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/6964880132047870022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=6964880132047870022' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/6964880132047870022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/6964880132047870022'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2009/01/automocking-container-with-typemock.html' title='AutoMocking Container with TypeMock Isolator'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_hcGoxuElMbw/SV80cEzHi8I/AAAAAAAAADY/mN0X7F_HNwM/s72-c/ClassDiagram1.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-7684999433180564897</id><published>2008-12-14T12:29:00.014+01:00</published><updated>2008-12-28T17:49:25.260+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scrum'/><title type='text'>A Look Back at Our Scrum implementation</title><content type='html'>I've been working at my current project for one year now and we are 'nearly done' with our first major release. I know that saying 'nearly done' has a little bit of a bad smell in the agile community but we couldn't do everything perfectly. But generally speaking, we did it pretty well and I'm happy how we could eliminate and master the difficulties of the project with &lt;a href="http://en.wikipedia.org/wiki/Scrum_(development)"&gt;scrum&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We had the following situation at the beginning of the project:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A list of requirements in an excel sheet. The list summarized all the thoughts, requirements and promises in an informal way. &lt;/li&gt;&lt;li&gt;There was a file containing drawings, print-outs from the former legacy system, or other artefacts for each requirement. &lt;/li&gt;&lt;li&gt;The project was embedded in a much larger project, which was driven by Hermes. Hermes is a heavy weight project management process, commonly used by governmental organisations in Switzerland. &lt;/li&gt;&lt;li&gt;Our team consisting out of 6 software developers was hired to implement the software. We proposed to implement scrum and the customer agreed on that. &lt;/li&gt;&lt;li&gt;A contract with a fixed price that was signed a long time before the developers got involved&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It was not easy to push scrum from the development into the larger project organisation. There was a good support for our ideas as long there was no organizational change required. Fortunately we could find a pretty good product owner, but we never have had a scrum master. The role of the scrum master was poorly fulfilled by me as a developer.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What worked well?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A lot of things worked great and I'm sure that the project would have failed without an &lt;a href="http://agilemanifesto.org/"&gt;agile&lt;/a&gt; approach. Here is what has worked well (see &lt;a href="http://www.scrumalliance.org/articles/39-glossary-of-scrum-terms"&gt;glossary&lt;/a&gt; for details on scrum terminology): &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.extremeprogramming.org/rules/userstories.html"&gt;User-Stories&lt;/a&gt;: After we had transformed the informal requirement list into user stories it was relatively easy to estimate it without knowing the details of each story. Even they were written by us developers it was better than working with the initial list.&lt;/li&gt;&lt;li&gt;Productbacklog: It gave us a very important planning tool, helping us to focus on the near future and driving the development sprint by sprint.&lt;/li&gt;&lt;li&gt;Sprints: The sprints helped us a lot to get the team and the customer focused on the tasks that needs to be done. Without focusing on the sprints and forgetting a little bit about the whole, we could never have done it.&lt;/li&gt;&lt;li&gt;Sprintplanning: Without this meeting we wouldn't have any chance to know what to implement in detail. The customer was surprised at the beginning that he had do discuss every detail of its initial requirement list again in the sprint planning.&lt;/li&gt;&lt;li&gt;Sprintreview: It was often the only opportunity to present our achievements and we always have had valuable feedback from the customer and the future users. Customer and users could get used to our development velocity and that took a lot of pressure away.&lt;/li&gt;&lt;li&gt;Adoption: The product owner discovered during the first two sprints that he needs to be better prepared for the sprint meetings. He started to consolidate the different opinions in additional meetings prior to the sprint planning.&lt;/li&gt;&lt;li&gt;Team forming: Event just two out of six developers have worked together before we never had major problems.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;What were the problems? &lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Scrummaster / Productowner: The roles were never officially assigned to persons, because the customer was confused in relation to the existing roles and responsibilities (project manager, solution architect and so on). There was also no budget available for 'non-programming' tasks.&lt;/li&gt;&lt;li&gt;Importance of the Productbacklog: The Productbacklog was built by the developers and was never owned by the product owner! Once it was initially built up it was used by the management to plan the whole year front up! Development was driven by the Productbacklog, but not testing, acceptance and fulfilment of the contract.&lt;/li&gt;&lt;li&gt;Testing: We couldn’t get things DONE. As the customer didn't test we started to do more functional and system testing. But after one year we do not have any story officially accepted by the customer. But due to the sprint-reviews I'm pretty confident that the customers will accept it after some minor changes.&lt;/li&gt;&lt;li&gt;Sprint-Retrospectives: the meeting was always held by the team but not attended by the product owner, nor attended by another representative of the management. Therefore just team internal impediments could be addressed and resolved. No organizational impediments were resolved.&lt;/li&gt;&lt;li&gt;Meetings: Due to the fact that the whole process was not coached by a scrum master, the meetings usually were ineffective and lasted too long. I, as developer and interim scrum master, was too involved to act as a coach for both the team and the customer.&lt;/li&gt;&lt;li&gt;Responsibility: There were few developers in our team that couldn't follow the process at all. They were not able to catch up the information at the sprint planning nor did they take the responsibility to fulfil the tasks they assigned themselves. We lost a lot of our performance here as senior team members had to coach them. Those weaker developers could not catch up as every thing went far too fast for them. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Conclusion&lt;br /&gt;&lt;/strong&gt;I'm still saying that agile development is the best practice I know. In my career as a software developer I sat too many times in my office trying to imagine how I could fulfil some requirements that I didn't understand. Today we have a simple process that brings customer and team together and that's much better for everybody. I'm thinking agile development is a process for people that want to take responsibility. If you don't have people that take responsibility you might be better to follow more heavy weight processes were every thing is predetermined and fixed. But everything you can't foresee will cost you a lot of money! It will cost you much more than the salaries of a good scrum master and good developers.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-7684999433180564897?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/7684999433180564897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=7684999433180564897' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/7684999433180564897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/7684999433180564897'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2008/12/look-back-at-our-scrum-implementation.html' title='A Look Back at Our Scrum implementation'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-2231731073839147300</id><published>2008-10-16T13:20:00.032+02:00</published><updated>2008-10-16T23:20:21.080+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Reflecting about how we implement aggregates</title><content type='html'>&lt;strong&gt;How we implement aggregates&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Since the beginning of my current project we tried to apply the ideas of structuring our business-logic into &lt;a href="http://domaindrivendesign.org/discussion/messageboardarchive/Aggregates.html"&gt;aggregates&lt;/a&gt;. We started to implement the aggregates using the following guidelines:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;define an aggregate root and implement it as a public class&lt;/li&gt;&lt;li&gt;define the internal classes of an aggregate and implement it as a public class&lt;/li&gt;&lt;li&gt;implement a repository that can query and return aggregate roots of this class&lt;/li&gt;&lt;li&gt;try to avoid accessing the internals (like traversing from aggregate root to an internal class) from outside the aggregate&lt;/li&gt;&lt;li&gt;put as much as possible of the business-logic into the aggregate root&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Following this rules we had some sort of guidelines about where to locate the business-logic and when to implement a repository. I think it was worth to have the aggregates. It was a valuable concept when we had to change our application from a 2-tier to a 3-tier architecture.&lt;/p&gt;&lt;p&gt;Nevertheless we always had following problems with aggregates:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Most of the time we had code in the presentation-layer that accessed the internals of an aggregate. It appeared often in case where there was an one-to-one data binding. For instance, in a master-detail view, where the master was the aggregate root an the detail an internal entity of the aggregate. (e.g. editing invoice and invoice position)&lt;/li&gt;&lt;li&gt;There were relations on the data model that do not comply the aggregate rules. In such a case we often had a nice definition of an aggregate, however there was sometimes a nasty dependency. It happend that an internal entity was depending on another entity in another aggregate. We agreed that this is not bad and that it can be abstracted to a dependency between the two involved aggregates. &lt;/li&gt;&lt;/ul&gt;And what happened:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Since the internals could be accessed, the business-logic begun to spread out into the presentation layer. It's impossible always to have the discipline to comply the aggregate rules and all of us violated it from time to time.&lt;/li&gt;&lt;li&gt;We didn't centralize the creational-logic. The test code is often a mess and it deals with setting-up the aggregates as well the internals of an aggregate.&lt;/li&gt;&lt;li&gt;A &lt;a href="http://www.ndepend.com/"&gt;NDepend&lt;/a&gt;-analyse revealed that our business-logic assembly will be a serious maintenance problem (&lt;a href="http://www.hanselman.com/blog/content/binary/NDepend%20metrics%20placemats%201.1.pdf"&gt;'Zone of pain'&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Why is our business-logic in the zone of pain?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;We generally get closer to the '&lt;a href="http://www.hanselman.com/blog/content/binary/NDepend%20metrics%20placemats%201.1.pdf"&gt;zone of pain&lt;/a&gt;' (see link for details), when a high number of types in an assembly:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;are more concrete than abstract (see Abstractness in the formula)&lt;/li&gt;&lt;li&gt;are used a lot by other assemblies (see Ca in the formula)&lt;/li&gt;&lt;li&gt;do not depend on other types (see Ce in the formula)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Since I can't see any value in implementing business-logic abstract (1.) and our business-logic already depends on a small number of types in other assemblies (2.) the only variable would be to reduce the number of types that are used by other assemblies (3.).&lt;/p&gt;&lt;p&gt;&lt;strong&gt;How could we do it different?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;We could try to better encapsulate the internals of an aggregate avoiding the problems described above. That means, not allowing to access any internals by another type than the aggregate root.  This increases the afferent coupling of the aggregate root, on the other hand eliminates the afferent coupling of the internals. The afferent coupling of the business logic assembly itself would then decrease.&lt;/p&gt;&lt;p&gt;Therefore I transformed one of our aggregates from something like that&lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;// File Invoice.cs&lt;br /&gt;public class Invoice&lt;br /&gt;{&lt;br /&gt;  public EntitySet&amp;lt;InvoicePosition&amp;gt; Positions { get; set; }&lt;br /&gt;}&lt;br /&gt;public class InvoicePosition&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;to&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;// File Invoice.cs&lt;br /&gt;public partial class Invoice&lt;br /&gt;{&lt;br /&gt;  private EntitySet&amp;lt;Invoice.InvoicePosition&amp;gt; Positions { get; set; }&lt;br /&gt;}&lt;br /&gt;// File InvoicePosition.cs&lt;br /&gt;public partial class Invoice&lt;br /&gt;{&lt;br /&gt;  private class InvoicePosition&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;After completing the refactoring and changing some logic in the presentation layer I got the following code metrics:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The assembly containing the business logic moved a little bit away from the zone of pain (from D=0.577 to 0.575). This is still bad, however the refactoring had a positive effect.&lt;/li&gt;&lt;li&gt;The type-rank for the refactored aggregate root increased from 10.7 to 12. Ca (Afferent coupling) increased from 62 to 66. That means, it got a more important part of the business logic.&lt;/li&gt;&lt;li&gt;The CC (cyclomatic complexity) for the aggregate root increased from 38 to 77, while CC decreased generally for the presentation layer (e.g. in one case from 26 to 16). That means that we put complexity into the business logic. It's a good thing since the complexity generally is easier to test and therefore to maintain in the business logic. It was also possible to eliminate duplicated business logic found in the presentation layer.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;Testability and Unittests&lt;/strong&gt;&lt;/p&gt;As the internals are completely hidden from outside now I test the refactored aggregate with state-based&lt;a href="http://de.wikipedia.org/wiki/Black-Box-Test"&gt; black-box tests&lt;/a&gt;. I think that's a reasonable way to do it since the test setup do not depend anymore on the implementation details of an aggregate. I'm not sure if this should be a general testing strategy for aggregates. I think there are more complex cases, where white-box tests would still be needed. The following pictures shows on the left, the test-code before the refactoring and on the right, the test-code after:&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_hcGoxuElMbw/SPdKNEXAVpI/AAAAAAAAACg/1R4I7B5-x0I/s1600-h/TestExample.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5257752678347331218" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" height="200" alt="" src="http://2.bp.blogspot.com/_hcGoxuElMbw/SPdKNEXAVpI/AAAAAAAAACg/1R4I7B5-x0I/s400/TestExample.JPG" width="600" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-2231731073839147300?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/2231731073839147300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=2231731073839147300' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2231731073839147300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2231731073839147300'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2008/10/reflecting-about-how-we-implement.html' title='Reflecting about how we implement aggregates'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_hcGoxuElMbw/SPdKNEXAVpI/AAAAAAAAACg/1R4I7B5-x0I/s72-c/TestExample.JPG' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-4460797754145127655</id><published>2008-07-14T21:18:00.007+02:00</published><updated>2008-07-20T19:43:18.391+02:00</updated><title type='text'>TDD, Design and Testability</title><content type='html'>After &lt;a href="http://www.youtube.com/watch?v=r5xPEhSGYS4"&gt;being on holiday&lt;/a&gt; for a while and being pretty busy at work I want to talk about an upcoming issue at my current project. The issues are&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Presenter-Logic (&lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html"&gt;Passiv View&lt;/a&gt;) is hard to test. It costs a lot of effort and it's difficult to be done right.&lt;/li&gt;&lt;li&gt;There is code that is not worth being tested. We shouldn't test that code just to have the test coverage increased.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;As a &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; advocate I'm trying to find out what's about those two issues above:&lt;/p&gt;&lt;strong&gt;1.&lt;/strong&gt;&lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html"&gt;&lt;strong&gt;Passiv View&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; is hard to test. &lt;/strong&gt;&lt;br /&gt;Let see an example:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public void EditDienstAbwesenheit()&lt;br /&gt;{&lt;br /&gt;  var abwesenheit = View.SelectedDienstAbwesenheit;  // get selected item from view&lt;br /&gt;  if (abwesenheit != null)  // if user as selected something&lt;br /&gt;  {&lt;br /&gt;    IModalDialog dialog;&lt;br /&gt;    if(abwesenheit is SpitalAufenthalt)  // decide what type of item is selected&lt;br /&gt;    {  // create a modal dialog for this item type&lt;br /&gt;      var presenter = _viewBuilder.Create(_unitOfWork,typeof(ISpitalaufenthaltbearbeitenDialog));&lt;br /&gt;      dialog = presenter.View;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {  // creat a modal dialog for the other item type&lt;br /&gt;      var presenter = _viewBuilder.Create(_unitOfWork,typeof(IAbwesenheitbearbeitenDialog));&lt;br /&gt;      dialog = presenter.View;&lt;br /&gt;    }&lt;br /&gt;    if (Shell.ShowInModalWorkspace(View, dialog) != DialogResult.OK) // display the modal dialog&lt;br /&gt;    {&lt;br /&gt;        _unitOfWork.Refresh(abwesenheit);  // reload data the might have been modified&lt;br /&gt;    }&lt;br /&gt;    UpdateView();  // show the modification on the view&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We all know that the more dependencies and responsibilities a method has the more is it hard to test. This is like that because each dependency needs a &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;mock or stub &lt;/a&gt;and each responsibility needs a test-assertion to verify it. The example above has following responsibilities:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Get the users selection&lt;/li&gt;&lt;li&gt;Decide about the next dialog to be shown&lt;/li&gt;&lt;li&gt;Create the dialog &lt;/li&gt;&lt;li&gt;Open the dialog in the shell&lt;/li&gt;&lt;li&gt;Reload to rollback modifications of the dialog&lt;/li&gt;&lt;li&gt;Present the changes to the users&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To accomplish that tasks we need:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;a View to get the users input&lt;/li&gt;&lt;li&gt;a Model (called 'abwesenheit') that represent the users input&lt;/li&gt;&lt;li&gt;a ViewBuilder to create a Dialog&lt;/li&gt;&lt;li&gt;a Shell to display the Dialog&lt;/li&gt;&lt;li&gt;a UnitOfWork to rollback the modifications&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So what? Is it a test-problem or a design-problem? I strongly believe that code that can't be tested is poorly designed. The most obvious is that we violate the &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;Single Responsiblity Principle &lt;/a&gt;(SRP). Could we split the responsibilities to find methods or even classes to separate the different concerns? &lt;/p&gt;&lt;p&gt;Lets try:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Get the users selection -&gt; &lt;em&gt;Lets keep it where it is&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Decide about the next dialog to be shown -&gt;&lt;strong&gt; &lt;/strong&gt;&lt;em&gt;Lets put it into a separate method&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Create the dialog -&gt;&lt;strong&gt; &lt;/strong&gt;&lt;em&gt;Lets delegate it to another object as creation and displaying a dialog is often used in an application (e.g Application controller)&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Open the dialog in the shell -&gt; &lt;em&gt;move it to the Application controller&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Reload to undo modifications -&gt;&lt;strong&gt; &lt;/strong&gt;&lt;em&gt;That's wrong here. The dialogs are responsible not to modify data in case they are cancelled!&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Present the changes to the users -&gt;&lt;em&gt; Lets keep it where it is&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;And after that minor refactoring:&lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public void EditDienstAbwesenheit()&lt;br /&gt;{&lt;br /&gt;    var abwesenheit = View.SelectedDienstAbwesenheit;&lt;br /&gt;    if (abwesenheit != null)&lt;br /&gt;    {&lt;br /&gt;      CreateEditDialog(abwesenheit);&lt;br /&gt;      UpdateView();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;public void CreateEditDialog(DienstAbwesenheit abwesenheit)&lt;br /&gt;{&lt;br /&gt;  if(abwesenheit is SpitalAufenthalt)&lt;br /&gt;  {&lt;br /&gt;    _applicationController.ShowInModalWorkSpace(_unitOfWork,typeof(ISpitalAufenthaltBearbeitenDialog));&lt;br /&gt;        }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    _applicationController.ShowInModalWorkSpace(_unitOfWork,typeof(IAbwesenheitBearbeitenDialog));&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So is that better? I think yes. In terms of Unit-Testing we reduced responsibility and dependency per unit (method) and we got a cleaner more expressive design.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2. There is code that is not worth being tested&lt;/strong&gt;&lt;br /&gt;Lets see following example:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public class Person&lt;br /&gt;{&lt;br /&gt;  public string FamilyName { get; set; }&lt;br /&gt;  public string Name { get; set; }&lt;br /&gt;  public string Age { get; set; }&lt;br /&gt;}&lt;br /&gt;public class Address&lt;br /&gt;{&lt;br /&gt;  public string Code { get; set; }&lt;br /&gt;  public string Country { get; set; }&lt;br /&gt;  public string Street { get; set; }&lt;br /&gt;}&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Model&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;public class PersonRow&lt;br /&gt;{&lt;br /&gt;  public PersonRow(Address address, Person person)&lt;br /&gt;  {&lt;br /&gt;    _address = address;&lt;br /&gt;    _person = person;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private readonly Person _person;&lt;br /&gt;  private readonly Address _address;&lt;br /&gt;&lt;br /&gt;  public string FamilyName&lt;br /&gt;  {&lt;br /&gt;    get { return _person.FamilyName; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public string Name&lt;br /&gt;  {&lt;br /&gt;    get { return _person.Name; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public string Age&lt;br /&gt;  {&lt;br /&gt;    get { return _person.Age; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public string Code&lt;br /&gt;  {&lt;br /&gt;    get { return _address.Code; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public string Country&lt;br /&gt;  {&lt;br /&gt;    get { return _address.Country; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public string Street&lt;br /&gt;  {&lt;br /&gt;    get { return _address.Street; }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Is it worth to test that each getter returns the right value? When is it worth to test a piece of code? I could think of following answers:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It's worth if something can go wrong&lt;/li&gt;&lt;li&gt;It's worth if I don't need to put a lot of effort to test it&lt;/li&gt;&lt;li&gt;It's worth if it's likely to be refactored in future&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The problem with the example above is that little can go wrong (except the mapping) and that the effort is too high to test it. On the other hand as a TDD advocate I'm a little bit annoyed that this little stupid class should lower our test coverage. So what is the way out? &lt;/p&gt;&lt;ul&gt;&lt;li&gt;If this class were not necessary there shouldn't go anything wrong&lt;/li&gt;&lt;li&gt;If we could reduce the lines of code, less could go wrong and less needs to be tested&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So let's try to introduce a mapper to externalize the mapping:&lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public class Person&lt;br /&gt;{&lt;br /&gt;  public string FamilyName { get; set; }&lt;br /&gt;  public string Name { get; set; }&lt;br /&gt;  public string Age { get; set; }&lt;br /&gt;}&lt;br /&gt;public class Address&lt;br /&gt;{&lt;br /&gt;  public string Code { get; set; }&lt;br /&gt;  public string Country { get; set; }&lt;br /&gt;  public string Street { get; set; }&lt;br /&gt;}&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Model&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;public class PersonRow&lt;br /&gt;{&lt;br /&gt;  public string PersonFamilyName { get; set; }&lt;br /&gt;  public string PersonName { get; set; }&lt;br /&gt;  public string PersonAge { get; set; }&lt;br /&gt;  public string AddressCode { get; set; }&lt;br /&gt;  public string AddressCountry { get; set; }&lt;br /&gt;  public string AssressStreet { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void DoTheMapping()&lt;br /&gt;{&lt;br /&gt;  var person = new Person();&lt;br /&gt;  var address = new Address();&lt;br /&gt;  var row = new PersonRow();&lt;br /&gt;  PropertyMapper.To(row).From(person).From(address).Execute();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The idea is to eliminate all the boring mappings to a specialized class PropertyMapper. The PropertyMapper would map the values from person and address to the row combining Classname and Propertyname. Furthermore the method Execute() would throw an exception in case any property of the PersonRow was not initialized with a value. My observations are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The PropertyMapper is difficult to implement, but I think after 10 mappings i have already my return on investment&lt;/li&gt;&lt;li&gt;Execute() is self-validating, therefore this code can also be run under test&lt;/li&gt;&lt;li&gt;I split the responsibilities into two classes (PersonRow and PropertyMapper) and I got testability&lt;/li&gt;&lt;li&gt;The example should be extended to support two way mappings&lt;/li&gt;&lt;li&gt;Is that too much? &lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-4460797754145127655?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/4460797754145127655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=4460797754145127655' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4460797754145127655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4460797754145127655'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2008/07/tdd-design-and-testability.html' title='TDD, Design and Testability'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-809702042906402532</id><published>2008-03-21T17:21:00.007+01:00</published><updated>2008-03-21T19:07:46.746+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Some thoughts about C# 3.0</title><content type='html'>We have been using the new C#3.0-features for two months and its quite interesting that our code looks in some parts like Jeremy describes in &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/03/14/c-3-is-like-a-moped.aspx"&gt;C#3.0 is like a moped&lt;/a&gt;. I wouldn't like to miss the new features and I won't stop using them but I'm thinking it's getting too much.&lt;br /&gt;&lt;br /&gt;It makes me feel that C# already had it's best time and there should be something new. Where is the new microsoft-ruby-language? C# was a better Java (I mean the language not the community) but where is now the better ruby?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-809702042906402532?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/809702042906402532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=809702042906402532' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/809702042906402532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/809702042906402532'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2008/03/some-thoughts-about-c-30.html' title='Some thoughts about C# 3.0'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-264366448950778874</id><published>2008-01-13T08:29:00.000+01:00</published><updated>2008-01-13T14:28:11.334+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='functionalprogramming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>Behind the scences of LINQ</title><content type='html'>I always knew that &lt;a href="http://en.wikipedia.org/wiki/LINQ"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;LINQ&lt;/span&gt;&lt;/a&gt; was founded on the idea of &lt;a href="http://en.wikipedia.org/wiki/Monad_%28functional_programming%29"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;monads&lt;/span&gt;&lt;/a&gt; but even trying hard I couldn't understand how &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;LINQ&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;monads&lt;/span&gt; are related to each other.&lt;br /&gt;&lt;br /&gt;But &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;fortunately&lt;/span&gt; there is Wes &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;Deyer&lt;/span&gt; and he describes in &lt;a href="http://blogs.msdn.com/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx"&gt;The Marvels of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Monads&lt;/span&gt;&lt;/a&gt; what I always wanted to know. It's a pity that &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;LINQ&lt;/span&gt; was always described and documented as query language rather than as a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;monad&lt;/span&gt; extensions. When I look to the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;msdn&lt;/span&gt;-documentation there is no hint that I could implement &lt;a href="http://msdn2.microsoft.com/en-us/library/bb394939.aspx#standardqueryops_topic4"&gt;query operators&lt;/a&gt; on other types than &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;IEnumerable&lt;/span&gt;&lt;t&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;IQueryable&lt;/span&gt;&lt;t&gt;.&lt;br /&gt;&lt;br /&gt;But that's exactly what Wes is doing. He sees a more general &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_12"&gt;concept&lt;/span&gt; and he shows a way to implement the query operators on any type. In fact this is for me a huge step and leads us to a new level of abstraction where &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;LINQ&lt;/span&gt; (as a list-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;monad&lt;/span&gt;) seems to be a specific case of a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;monad&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;My preferred way to use LINQ was the &lt;a href="http://msdn2.microsoft.com/de-de/library/bb397947.aspx"&gt;method syntax&lt;/a&gt; as I thought this is the more general case. But now, after knowing that the query syntax is something like a monad extension I start to like it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-264366448950778874?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/264366448950778874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=264366448950778874' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/264366448950778874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/264366448950778874'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2008/01/behind-scences-of-linq.html' title='Behind the scences of LINQ'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-4227910835388093382</id><published>2007-12-29T14:46:00.000+01:00</published><updated>2007-12-29T16:01:03.353+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Playing around with NBehave</title><content type='html'>&lt;a href="http://enceradeira.blogspot.com/2007/12/evaluating-dependency-injection.html"&gt;As I said recently&lt;/a&gt; I'm still exploring tdd and its capabilities. The next evolutionary step could be &lt;a href="http://en.wikipedia.org/wiki/Behavior_driven_development"&gt;bdd&lt;/a&gt;. Therefore I downloaded &lt;a href="http://nbehave.org/"&gt;NBehave&lt;/a&gt; and I tried to write one story with it. &lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html"&gt;Passive View&lt;/a&gt; is my preferred playground and thats how it goes with NBehave and &lt;a href="http://www.typemock.com/"&gt;TypeMock.NET&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;First the declaration of the View, the Presenter and a Service-Gateway that is used by the Presenter to retrieve some information.&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;protected IView _view;&lt;br /&gt;protected Presenter _presenter;&lt;br /&gt;protected EventHandler _updateRequestedEvent;&lt;br /&gt;protected IServiceGateway _serviceGatway;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The setup of the this objects is not showed here. It simples instantiates mocks for the View and the ServiceGateway and injects it into the Presenter using &lt;a href="http://martinfowler.com/articles/injection.html"&gt;Constructor-Injection&lt;/a&gt;. The _updateRequestedEvent is a mocked event on the view and is also used later in the example.&lt;/p&gt;&lt;p&gt;First I have to specify a story. This is done like that: &lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;[TestFixtureSetUp]&lt;br /&gt;public void FixtureSetup()&lt;br /&gt;{&lt;br /&gt;    _getCurrentTimeStory = new Story("Getting the current service time");&lt;br /&gt;    _getCurrentTimeStory.AsA("User").IWant("to update the displayed current time")                &lt;br /&gt;                        .SoThat("I can see what time is on the serivce side");&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;And that's one scenario that came in my mind:&lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;[Test]&lt;br /&gt;public void HelloNTServiceIsNotAvailable()&lt;br /&gt;{&lt;br /&gt;      using (RecordExpectations recorder = RecorderManager.StartRecording())&lt;br /&gt;      {&lt;br /&gt;          _view.ShowMessageBox("The Service is currently not available");&lt;br /&gt;          recorder.CheckArguments();&lt;br /&gt;      }&lt;br /&gt;      _getCurrentTimeStory.WithScenario("Service is not available")&lt;br /&gt;           .Given("the Service returns an exception", new Exception("Error"), e =&gt;&lt;br /&gt;              {&lt;br /&gt;                 using (RecordExpectations recorder = RecorderManager.StartRecording))&lt;br /&gt;                 {&lt;br /&gt;                    recorder.ExpectAndThrow(_serviceGatway.GetTime(), e);&lt;br /&gt;                 }&lt;br /&gt;              })&lt;br /&gt;           .When("I update the current time", () =&gt; _updateRequestedEvent(this, EventArgs.Empty))&lt;br /&gt;           .Then("a message box should display", "The Service is currently not available", m =&gt;&lt;br /&gt;              {&lt;br /&gt;                   MockManager.Verify();&lt;br /&gt;              })&lt;br /&gt;        ;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Looks quite chaotic and a developer not used to NUnit,TypeMock and NBehave might not understand it at first glance. I also think the combination of NUnit,TypeMock and NBehave is a little bit strange as they do not integrate very well. Maybe there is another way how to combine those frameworks?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;But what I like is the overall structure that it gives to the tests and the readable test output that can be interpreted by a &lt;a href="http://www.scrumforteamsystem.com/ProcessGuidance/Roles/ProductOwner.html"&gt;product owner&lt;/a&gt;. Here are now the scenario above and another scenario that I could present to him:&lt;/p&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Story: Getting the current service time&lt;br /&gt;&lt;br /&gt;Narrative:&lt;br /&gt;As a User&lt;br /&gt;I want to update the displayed current time&lt;br /&gt;So that I can see what time is on the serivce side&lt;br /&gt;&lt;br /&gt;Scenario 1: Service is not available&lt;br /&gt;Given the Service returns an exception: System.Exception: Error&lt;br /&gt;When I update the current time&lt;br /&gt;Then a message box should display: The Service is currently not available&lt;br /&gt;&lt;br /&gt;Scenario 2: Service is available&lt;br /&gt;Given the Service returns the time: 01.01.2000 12:24:23&lt;br /&gt;When I update the current time&lt;br /&gt;Then the label on the view should display: 12:24&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-4227910835388093382?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/4227910835388093382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=4227910835388093382' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4227910835388093382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4227910835388093382'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/12/playing-around-with-nbehave.html' title='Playing around with NBehave'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-5367483274276068852</id><published>2007-12-16T18:04:00.000+01:00</published><updated>2007-12-29T14:50:38.604+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Evaluating a dependency injection framework</title><content type='html'>I heard the first time about &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;tdd&lt;/a&gt; in the year 2002 when a colleague of mine introduced me to a tool called 'NUnit'. I found tdd very helpful from the beginning and I was always one of them that pushed that paradigm and mindset. I learned like a lot of the other tdd enthusiasts, that 'test first' is good, that 'test isolation' is really necessary, that a 'mocking framework' helps a lot, and that it's all about a good design. On this journey I'm now at a point where I question: &lt;strong&gt;could a 'dependency injection framework' help?&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;That is what I tried to find out today and what this post is about. I wrote a simple application including: &lt;ul&gt;&lt;li&gt;a &lt;a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation"&gt;wpf client&lt;/a&gt; with one window called Window1&lt;/li&gt;&lt;li&gt;a &lt;a href="http://en.wikipedia.org/wiki/Windows_Communication_Foundation"&gt;wcf service&lt;/a&gt; called Service with one Methode GetDate() that returns the current date and time&lt;/li&gt;&lt;li&gt;one assembly testing the wpf-presentation and wcf-service (just unit-tests)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Introducing a DI-Framework&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;One trying to write tests in such an environment knows that integrating the real wpf- and wcf-environment into the tests is a bad idea. Instead it's better to &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;stub and mock&lt;/a&gt; those environments to get easier, more stable, and faster tests. This means we usually want a test-configuration where the most external dependencies (like wpf or wcf) are mocks or stubs. On the other hand we want to have a configuration on a deployed system that utilizes the real dependencies. So it's something about configuration and that's where the DI-frameworks come into play. &lt;/p&gt;&lt;p&gt;I decided to give Jeremy's &lt;a href="http://structuremap.sourceforge.net/Default.htm"&gt;StructureMap&lt;/a&gt; a try because it doesn't look so overloaded like &lt;a href="http://www.springframework.net/"&gt;Sprint.NET&lt;/a&gt; or &lt;a href="http://www.castleproject.org/container/index.html"&gt;Windsor&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;Following code shows my wcf-service IService that I include in the presentation-layer as a Service-Gateway (see also &lt;a href="http://martinfowler.com/eaaCatalog/serviceStub.html"&gt;ServiceStub-Pattern&lt;/a&gt;): &lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;&lt;br /&gt;    [ServiceContract]&lt;br /&gt;    public interface IService&lt;br /&gt;    {&lt;br /&gt;        [OperationContract]&lt;br /&gt;        DateTime GetTime();&lt;br /&gt;    }&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// Gateway to intercept for testing&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    public interface IServiceGateway : IService&lt;br /&gt;    {&lt;br /&gt;        void Close();&lt;br /&gt;    }&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// Real gateway using the wcf generated ServiceClient class&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    public class ServiceGateway : IServiceGateway&lt;br /&gt;    {&lt;br /&gt;        private readonly ServiceClient _service;&lt;br /&gt;&lt;br /&gt;        public ServiceGateway()&lt;br /&gt;        {&lt;br /&gt;            _service = new ServiceClient();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Close()&lt;br /&gt;        {&lt;br /&gt;            _service.Close();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public DateTime GetTime()&lt;br /&gt;        {&lt;br /&gt;            return _service.GetTime();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    /// &amp;lt;summary&amp;gt;&lt;br /&gt;    /// Stub for testing&lt;br /&gt;    /// &amp;lt;/summary&amp;gt;&lt;br /&gt;    public class ServiceGatewayStub : IServiceGateway&lt;br /&gt;    {&lt;br /&gt;        public void Close()&lt;br /&gt;        {&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public DateTime GetTime()&lt;br /&gt;        {&lt;br /&gt;            return new DateTime(2000, 1, 1, 12, 34, 55, 12);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;strong&gt;Step 1:&lt;/strong&gt;&lt;br /&gt;Using the following code to resolve the reference to the external wcf-service&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;IServiceGateway gateway = ObjectFactory.GetInstance&amp;lt;IServiceGateway&amp;gt;()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;and using the following configuration for the tests&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;&amp;lt;StructureMap&amp;gt;&lt;br /&gt;  &amp;lt;DefaultInstance PluginType="HelloNTPresentation.IServiceGateway,HelloNTPresentation" PluggedType="HelloNTService.ServiceGatewayStub,HelloNTTests"  Scope="Singleton"/&amp;gt;&lt;br /&gt;&amp;lt;/StructureMap&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;I could wire the code during the tests to the ServiceGatewayStub instead of the real ServiceGateway.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 2:&lt;/strong&gt;&lt;br /&gt;I didn't like that because it meant that we have to setup a configuration for the real (not test) environment like:&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;&amp;lt;StructureMap&amp;gt;&lt;br /&gt;  &amp;lt;DefaultInstance PluginType="HelloNTPresentation.IServiceGateway,HelloNTPresentation" PluggedType="HelloNTPresentation.ServiceGateway,HelloNTPresentation"  Scope="Singleton"/&amp;gt;&lt;br /&gt;&amp;lt;/StructureMap&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;After I have had read &lt;a href="http://www.ayende.com/Blog/archive/2007/10/20/Building-an-IoC-container-in-15-lines-of-code.aspx"&gt;how to build an IoC container in 15 lines of code&lt;/a&gt; I thought that DI can't be so difficult and I tried to build my own DI-framework. I liked very much that I could configure the DI in the code now and eliminate the file-based configuration:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;      ObjectFactory.Register&amp;lt;IServiceGateway&amp;gt;(() =&amp;gt; new ServiceGatewayStub());&lt;br /&gt;      IServiceGateway gateway = ObjectFactory.Create&amp;lt;IServiceGateway&amp;gt;();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;All tests were green and I was happy to start the refactored sample application first time after. But there was big surprise when it crashed. I had forgotten to configure DI for the wcf-service and wpf-service. But where should I put that configuration? Both of them run in some kind of hosted environment and I wasn't able to find a nice place to put that configuration-code. So I realized that it's a little bit harder than I thought to write an own DI-Framework.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Step 3:&lt;/strong&gt;&lt;br /&gt;Back to StructureMap I found a way to minimize the file-based configuration. The solution was to use the attributes PluginFamily and Pluggable that define default behaviour. In this case the class ServiceGateway is the default implementation of IServiceGateway and there is no need to configure it for the wcf-service and the wpf-client anymore.&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;    [ServiceContract]&lt;br /&gt;    public interface IService&lt;br /&gt;    {&lt;br /&gt;        [OperationContract]&lt;br /&gt;        DateTime GetTime();&lt;br /&gt;    }&lt;br /&gt;    [PluginFamily("ServiceGateway")]&lt;br /&gt;    public interface IServiceGateway : IService&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;    [Pluggable("ServiceGateway")]&lt;br /&gt;    public class ServiceGateway : IServiceGateway&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;strong&gt;Step 4: &lt;/strong&gt;&lt;br /&gt;Now let's have a look to following the &lt;a href="http://martinfowler.com/eaaDev/PassiveScreen.html"&gt;presenter&lt;/a&gt; (presenter is what is responsible for the presentation-logic):&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;    public class Presenter: IDisposable&lt;br /&gt;    {&lt;br /&gt;        readonly IView _view;&lt;br /&gt;        readonly IServiceGateway _service;&lt;br /&gt;&lt;br /&gt;        public Presenter(IView view, IServiceGateway service)&lt;br /&gt;        {&lt;br /&gt;            _view = view;&lt;br /&gt;            _service = service;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;That presenter shows all internal dependencies on its constructor. This enables us to use &lt;a href="http://martinfowler.com/articles/injection.html"&gt;constructor injection&lt;/a&gt; when writing tests with a Mock-Framework (e.g. &lt;a href="http://www.typemock.com/"&gt;TypeMock&lt;/a&gt;)&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;     _serviceGatway = RecorderManager.CreateMockedObject&amp;lt;IServiceGateway&amp;gt;();&lt;br /&gt;     _view = RecorderManager.CreateMockedObject&amp;lt;IView&amp;gt;();&lt;br /&gt;     _presenter = new Presenter(_view, _serviceGatway);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;But what's about the others that don't want to bother about providing those dependencies to the constructor? And that's where the DI-framework gets really valueable because it enables us to instantiate concrete classes without providing the needed arguments to the constructor. Following code is from the wpf-client and shows how this is done:&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;    Presenter presenter = ObjectFactory.FillDependencies&amp;lt;Presenter&amp;gt;();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Just for completeness, I have to mention how I configured IView:&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;    [PluginFamily("Window1")]&lt;br /&gt;    public interface IView&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;    [Pluggable("Window1")]&lt;br /&gt;    public partial class Window1 : Window, IView&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I always used constructor injection but with a DI-framework it gets easier because the client code doesn't need to manage the dependencies anymore. &lt;/li&gt;&lt;li&gt;I like StructureMap because it looks simple and it works.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-5367483274276068852?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/5367483274276068852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=5367483274276068852' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5367483274276068852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5367483274276068852'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/12/evaluating-dependency-injection.html' title='Evaluating a dependency injection framework'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-7027106782574864986</id><published>2007-12-11T21:07:00.000+01:00</published><updated>2007-12-11T21:53:08.544+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Orcas'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Offline data synchronization</title><content type='html'>I wrote a few days before that it looked like I would get involved in a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;SOA&lt;/span&gt;-project. Today it looks like I will get involved in another project! This new project could have following technical characteristics:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;said to be a rich-client-project &lt;/li&gt;&lt;li&gt;support for offline disconnected scenarios (offline agents)&lt;/li&gt;&lt;li&gt;distributed application (&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;Internet&lt;/span&gt;, intranet or some kind of private network)&lt;/li&gt;&lt;li&gt;integration with a &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;backend&lt;/span&gt; system (no idea what kind of interface that would be)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Sounds interesting .... So I bought yesterday &lt;a href="http://books.google.ch/books?id=fWTHHwAACAAJ&amp;amp;dq=Pro+WPF+in+2008"&gt;something about &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;WPF&lt;/span&gt;&lt;/a&gt; to update myself with 'state of the art rich client development'.&lt;/p&gt;&lt;p&gt;Maybe the new &lt;a href="http://msdn2.microsoft.com/en-us/sync/bb736752.aspx"&gt;Microsoft &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Synch&lt;/span&gt; Framework &lt;/a&gt;could be interesting in that context too. I watched &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=347021"&gt;this &lt;/a&gt;and it looks promising. I have to admit that I hate that kind of presentations but it looks that it's &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;flexible&lt;/span&gt; and can be extended. I'm not yet sure about that but at least the synch-runtime can be instantiated in a object-oriented manner and that's always a good sign. Would be great if it could be connected to a &lt;a href="http://en.wikipedia.org/wiki/Service_%28systems_architecture%29"&gt;service &lt;/a&gt;instead of a database.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-7027106782574864986?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/7027106782574864986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=7027106782574864986' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/7027106782574864986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/7027106782574864986'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/12/offline-data-synchronization.html' title='Offline data synchronization'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-8902196054646574190</id><published>2007-12-09T17:11:00.000+01:00</published><updated>2007-12-09T19:51:06.220+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>WCF puts all together</title><content type='html'>I was supposed to get involved into a &lt;a href="http://en.wikipedia.org/wiki/Service-oriented_architecture"&gt;SOA&lt;/a&gt;-project therefore I started to read about &lt;a href="http://en.wikipedia.org/wiki/Windows_Communication_Foundation"&gt;WCF&lt;/a&gt;. In the meanwhile it turned out that I might not be involved in that project, however I kept on doing my reading on this issue. I went through the following two books:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://books.google.ch/books?id=fDykmoWpjzEC&amp;amp;dq=pro+wcf&amp;amp;pg=PP1&amp;amp;ots=XV8TVpcdAr&amp;amp;sig=GOpAv6CEJUBusNCHU1iXI-q9i84&amp;amp;prev=http://www.google.ch/search?hl=de&amp;amp;q=PRO+WCF&amp;amp;sa=X&amp;amp;oi=print&amp;amp;ct=title&amp;amp;cad=one-book-with-thumbnail"&gt;Pro WCF Practical Microsoft SOA Implementation&lt;/a&gt; was a good introduction with a lot of code and examples. I liked it as a brief introduction into how WCF 'feels like'. But I switched to the other book soon after since I got more interested in the overall concepts than in the details.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I liked &lt;a href="http://books.google.ch/books?id=DW2ldput788C&amp;amp;printsec=frontcover&amp;amp;dq=Programming+WCF+Services&amp;amp;sig=hfwpB4MTqSOLYTl4FAviSh_RFZo"&gt;Programming WCF Services&lt;/a&gt; because it talks in more details about advanced stuff like Instance Management, Faults, Transactions, Concurrency and Security.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Below is what I think about WCF: I think theres is nothing new but that all comes together in a nice consistent way. WCF helps much if an application is more than a monolithic web or rich-client application. I'd like to mention two personal highlights:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Hosting:&lt;/strong&gt; An WCF service can be hosted inprocess, as a &lt;a href="http://en.wikipedia.org/wiki/Windows_service"&gt;windows-service&lt;/a&gt;, as a console-application or on the &lt;a href="http://en.wikipedia.org/wiki/Internet_Information_Services"&gt;IIS&lt;/a&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;.NET Integration: &lt;/strong&gt;Full integration with standard .NET mechanisms like the &lt;a href="http://msdn2.microsoft.com/de-de/library/system.security.aspx"&gt;System.Security&lt;/a&gt;, &lt;a href="http://msdn2.microsoft.com/de-de/library/system.transactions(VS.80).aspx"&gt;System.Transaction&lt;/a&gt;, &lt;a href="http://msdn2.microsoft.com/en-gb/library/system.threading(VS.80).aspx"&gt;System.Threading&lt;/a&gt;-Namespaces. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-8902196054646574190?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/8902196054646574190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=8902196054646574190' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8902196054646574190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8902196054646574190'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/12/wcf-puts-all-together.html' title='WCF puts all together'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-2598992676048307993</id><published>2007-12-01T17:30:00.000+01:00</published><updated>2007-12-02T09:07:00.847+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>excpetion handling could be easy</title><content type='html'>We have been doing a major &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;refactoring&lt;/span&gt; in our project trying to get rid of the legacy exception handling. As we went through our code we had some good laughs (we shouldn't have &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;laughed&lt;/span&gt; as we still have to maintain that for a long time) and it was &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;obvious&lt;/span&gt; that some developers had no clue about how to deal with exceptions or were too lazy to implement a more sophisticated handling. It seemed that some developers didn't miss any &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;opportunity&lt;/span&gt; to get rid of that nasty exceptions. It &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;seemed&lt;/span&gt; that we were fighting a .NET-bug called 'Exception'.&lt;br /&gt;&lt;br /&gt;We also had a lot of discussons about exceptions, especially because we wanted to eliminate &lt;a href="http://grabbagoft.blogspot.com/2007/06/swallowing-exceptions-is-hazardous-to.html"&gt;exception swallowing&lt;/a&gt; but not to change the user experience! Our product manager stated that it's better to have an obscure behaviour that the users knows than a new fancy error dialog that indicates problems at the root. (Users don't like &lt;a href="http://en.wikipedia.org/wiki/Fail-fast"&gt;fail fast&lt;/a&gt;!)&lt;br /&gt;&lt;br /&gt;I didn't want to talk about that stuff but I have just come across some similar thoughts:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://grabbagoft.blogspot.com/2007/11/stop-madness.html"&gt;http://grabbagoft.blogspot.com/2007/11/stop-madness.html&lt;/a&gt; (see Try Catch Publish Swallow)&lt;br /&gt;&lt;a href="http://grabbagoft.blogspot.com/2007/06/swallowing-exceptions-is-hazardous-to.html"&gt;http://grabbagoft.blogspot.com/2007/06/swallowing-exceptions-is-hazardous-to.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://grabbagoft.blogspot.com/2007/06/re-throwing-exceptions.html"&gt;http://grabbagoft.blogspot.com/2007/06/re-throwing-exceptions.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-2598992676048307993?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/2598992676048307993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=2598992676048307993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2598992676048307993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2598992676048307993'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/12/excpetion-handling-could-be-easy.html' title='excpetion handling could be easy'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-6232358122422535216</id><published>2007-11-27T21:41:00.000+01:00</published><updated>2007-12-09T18:20:29.527+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>consistency, integrity  and exceptions</title><content type='html'>I was blaming myself today talking about consistency and integrity without remembering the exact definitions of it. I just remembered that there are some interesting differences between them. What I meant was a definition like &lt;a href="http://en.wikipedia.org/wiki/Data_consistency"&gt;Consistency&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Data_integrity"&gt;Integrity&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My point was that exception handling and especially the concept of &lt;a href="http://en.wikipedia.org/wiki/Design_by_contract"&gt;design by contract&lt;/a&gt; could be seen in a similar context. I tried to argue that violating a &lt;a href="http://en.wikipedia.org/wiki/Design_by_contract"&gt;design by contract&lt;/a&gt;-rule(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;pre&lt;/span&gt;/post/invariance) is like violating the 'programs internal consistency'.&lt;br /&gt;&lt;br /&gt;But as &lt;a href="http://en.wikipedia.org/wiki/Data_consistency"&gt;Consistency&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Data_integrity"&gt;Integrity&lt;/a&gt; is just clearly defined in the context of data it seems that my &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;derivation&lt;/span&gt; doesn't make sense.&lt;br /&gt;&lt;br /&gt;In personally would say a 'program consistency' is maintained as long it's internal state doesn't contain any contradictions. Furthermore a 'program integrity' is maintained as long as the programs internal state does reproduce all related external state correctly.&lt;br /&gt;&lt;br /&gt;Following that definition one could say that 'program consistency' can be checked by the &lt;a href="http://en.wikipedia.org/wiki/Design_by_contract"&gt;design by contract&lt;/a&gt;-technique but 'program integrity' cannot. 'program integrity' cannot be checked at all by a program.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-6232358122422535216?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/6232358122422535216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=6232358122422535216' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/6232358122422535216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/6232358122422535216'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/11/consistency-integrity-and-exceptions.html' title='consistency, integrity  and exceptions'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-101897707852434555</id><published>2007-11-20T19:30:00.000+01:00</published><updated>2007-11-20T21:06:00.764+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Orcas'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Expresso - Regextool and others</title><content type='html'>I used &lt;a href="http://www.ultrapico.com/Expresso.htm"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Expresso&lt;/span&gt; &lt;/a&gt;first time today and I liked it much more than the &lt;a href="http://sourceforge.net/projects/regulator/"&gt;Regulator&lt;/a&gt; that I've used up to now . The '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Regex&lt;/span&gt; Analyzer'-View and the 'Search Result'-View display the &lt;a href="http://en.wikipedia.org/wiki/Regex"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Regex&lt;/span&gt; &lt;/a&gt;and the matches as a tree and this helps me a lot in understanding &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Regex's&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I've always wanted to mention that I'm using a visual &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;studion&lt;/span&gt; &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;plugin&lt;/span&gt; named &lt;a href="http://weblogs.asp.net/gmilano/archive/2006/05/10/446010.aspx"&gt;Cool Commands&lt;/a&gt;. I'm using just one command of it: 'Collapse All Projects' . It collapses my 20 projects in a solution with one click! Will the &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/11/19/visual-studio-2008-and-net-3-5-released.aspx"&gt;brand-new visual studio 2008 support &lt;/a&gt;that out of the box?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-101897707852434555?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/101897707852434555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=101897707852434555' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/101897707852434555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/101897707852434555'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/11/expresso-regextool-and-others.html' title='Expresso - Regextool and others'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-4456116917011954161</id><published>2007-11-11T16:47:00.000+01:00</published><updated>2007-11-11T20:27:26.829+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scrum'/><title type='text'>Scrum and xp from the trenches</title><content type='html'>I've just finished reading &lt;a href="http://www.infoq.com/minibooks/scrum-xp-from-the-trenches"&gt;Scrum and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;xp&lt;/span&gt; from the trenches&lt;/a&gt;. To see that everybody trying to adapt Scrum is running into the same kind of problems perks me up. Scrum like its written in the books is quite dogmatic but this book gives some good pragmatic advices.&lt;br /&gt;&lt;br /&gt;Two remarks about what I've read related to the project I'm currently working on:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;We are trying to adapt a simple estimation method where we compare the complexity of use-cases choosing a number from 1,2,3,5,8,13 ... One use-cases is randomly &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;chosen&lt;/span&gt; as a 'reference use-case' and all other use-cases are estimated by comparing it with the 'reference use-case'. Estimating use-cases is a &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;reoccurring&lt;/span&gt; activity in our project and the problem is that every team member has always to remember a 'reference use-case' in its details to be able to give an estimate to another use-case. Using that method we had a kind of 'currency' to determine the real value in time (how many hours is one point?). Calculating 'Total Points in a Sprint' * 'currency' gives us the total amount of working hour of the team in a Sprint. &lt;/li&gt;&lt;li&gt;Maybe we should switch over to a system where 1 Point is '1 ideal programming day'. We could still use an exponentially growing number like 0.25, 0,5, 1,2,3,5,8,13... to &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;address&lt;/span&gt; the growing uncertainty. The drawback is that we might have to deal now with number less than 1 but on the other hand it gives us a better feeling on how much work is related to one certain number. Furthermore our 'currency' gets a 'focus factor' and that's easier to understand by managers and &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;addresses&lt;/span&gt; directly the question why we cannot deliver as fast as in an 'ideal &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;environment&lt;/span&gt;'. I guess comparing use-cases according to their complexity is a good choice for a single 'planning-meeting'. However in our case where we estimate a small number of use-cases monthly, it's better to pin the points to '1 ideal programming day'.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-4456116917011954161?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/4456116917011954161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=4456116917011954161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4456116917011954161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4456116917011954161'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/11/scrum-and-xp-from-trenches.html' title='Scrum and xp from the trenches'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-1716973276260259326</id><published>2007-10-28T15:45:00.000+01:00</published><updated>2007-11-17T21:02:34.810+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entwurfsmuster'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Patterns 4 - Domain Driven Design</title><content type='html'>Im vorläufig letzten Beitrag zu Patterns möchte ich einige Patterns aus dem Buch &lt;a href="http://books.google.ch/books?id=7dlaMs0SECsC&amp;amp;pg=PP1&amp;amp;dq=domain+driven+design+evans&amp;amp;sig=DLWQHppoZ3eQzc3cc25w1J8TRTA"&gt;Domain Driven Design&lt;/a&gt; von Evans auflisten. Leider sind die Patterns nicht Online verfügbar, doch gehört dieses Buch sowieso zur Pflichtlektüre wenn mit &lt;a href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt;'s gearbeitet wird. Wer es weniger theorietisch mag und sehe möchte wie sich das Arbeiten mit DDD 'anfühlt' dem sei &lt;a href="http://books.google.com/books?id=RZXGAAAACAAJ&amp;amp;dq=domain+driven+design&amp;amp;hl=de"&gt;Applying Domain-Driven-Design and Pattern &lt;/a&gt;von Nilson empfohlen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Supple Design&lt;/strong&gt;&lt;br /&gt;Unter dieser Überschrift sind Patterns enthalten welche die Absicht und Wirkung von Code möglichst transparent darstellen lassen sollen. Idee ist dass die Struktur des Code die Funktionalität möglich klar darstellt.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Side-Effect-Free-Functions&lt;/strong&gt;: Mit diesem Pattern können, auch in Kombination mit unveränderbaren 'Value Objects', einfach verständliche und testbare Funktionen realisiert werden. Für das Verständnis und das Testen müssen nur Inputparameter und der Resultatwert der Methode berücksichtigt werden da keine &lt;a href="http://en.wikipedia.org/wiki/Side_effect_%28computer_science%29"&gt;Seiteneffekte &lt;/a&gt;vorhanden sind. Weiter wird empfohlen Commands (Methoden welche beobachtbaren Zustand verändern) in sehr einfache Operationen zu gliedern welche keine Domäneninformationen retournieren.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Assertions: &lt;/strong&gt;Im Code sollen &lt;a href="http://en.wikipedia.org/wiki/Design_By_Contract"&gt;Pre-/Postcondition und Invarianzen&lt;/a&gt; definiert werden. Damit sollen auch Seiteneffekte explizit spezifiziert werden damit für das Verständnis einer Methode nicht alle Ausführungspfade analysiert werden müssen.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Intention-Revealing Interfaces: &lt;/strong&gt;Hier gehts es darum dass Klassen- und Methodenamen gefunden werden welche die Funktionalität und Verantwortlichkeit klar ausdrücken. Es sollte nicht nötigt sein dass daneben noch dokumentiert werden muss, unter welchen Umständen eine Klasse und Methode wie funktioniert. Auch sollten im Namen Begriffe aus der 'Ubiquitous Language' auftauchen.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Standalone Classes: &lt;/strong&gt;Gelingt es eine völlig losgelöste Klasse, ohne Abhängigkeiten auf andere Klassen zu entwickeln, reduziert man die konzeptionelle Komplexität massgeblich. Lose Kopplung kann eingesetzt werden um die Komplexität von Code zu reduzieren.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Closure of Operations: &lt;/strong&gt;Dieses Konzept hält uns an Operationen wie mathematische Operationen aufzubauen da diese ein einfaches Konzept ist. Dabei sollen Eingabeparameter und Rückgabwert vom gleichen Typ sein.  Ein solches Interface ermöglicht das Zusammenbauen von komplexeren Operationen aus einfacheren Primitiven.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Specification: &lt;/strong&gt;Ein Value Object welches als &lt;a href="http://en.wikipedia.org/wiki/Predicate_%28computer_programming%29"&gt;Predicate&lt;/a&gt; bestimmt ob ein anderes Objekt ein bestimmtes Kriterium erfüllt.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ubiquitous Language: &lt;/strong&gt;Dabei sollen Begriff und Konzepte aus der Problemdomäne von den Entwicklern übernommen werden. Diese Begriff und Konzepte haben ein starken Einfluss auf den Design und sind einer der wichtigsten Treiber für den Design.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Building Blocks&lt;/strong&gt;&lt;br /&gt;Hier haben wir Patterns welche unter DDD häufig vorkommen.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Layered Architecture: &lt;/strong&gt;Schlägt vor im allg. eine Applikation in Presentation, Application, Domain und Infrastruktur Layer zu schichten. Dies ermöglicht einen ausdrucksstarken Domainlayer zu erhalten da dieser nicht mit Anzeige-, Speicher-oder Berechtigungsaufgaben usw. überladen wird. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Entities und Value Objects: &lt;/strong&gt;Wichtige Konzepte zum Unterscheiden von Klassen mit Identitäten (z.B: eine Person mit einer ID) und Klassen deren Identität durch die Werte der Klasse bestimmt ist (z.B eine Farbe identifizierbar durch ihre &lt;a href="http://en.wikipedia.org/wiki/Rgb"&gt;RGB-Werten&lt;/a&gt;). Es wird empfohlen Value Objects als unveränderbare Klassen zu designen.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Modules&lt;/strong&gt;: Gibt Anleitunng nach welchen Aspekten Code modularisiert werden sollten. Dabei sollte auf geringe Kopplung und hohe Kohäsion geachtet werden. Modulnamen sollten Teil der Ubiquitous Language werden. "If your model is telling a story, the Modules are chapters".&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Services&lt;/strong&gt;: Im allg. sollte für jeden Service gelten: 1.) Die Operation auf dem Service ist Teil des Domänenkonzept welches aber nicht als Entitiy oder Value Object ausgedrückt werden kann. 2.) Die Service-Schnittstelle nimmt Bezug auf das Domänenmodell. 3.) Die Operation ist zustandslos. Desweitern kann ein Service in verschiedenen Schichten realisiert werden (&lt;strong&gt;Application-, Domain-, Infrastructure-Service&lt;/strong&gt;) wobei sich die Verantwortlichkeiten je nach Schicht stark unterscheiden können.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Factories&lt;/strong&gt;: Erzeugt in einer Operation ein konsistentes Objekt oder Aggregate (Invarianzen müssen erfüllt sein). Dieses Pattern wird wichtig sobald ein Objekt nicht mehr mit einem einfachen Konstruktoraufruf erzeugt und in einen konsistenen Zustand überführt werden kann.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Repositories&lt;/strong&gt;: Lädt Objekte oder Aggregates von einem tieferen Infrastrukturlayer in den Speicher (z.B von der Datenbank) und erzeugt die Illusion dass die Objekte immer im Speicher vorhanden sind. Repositories werden spezifisch für Klassen von Objekten und Aggregates realisiert und zeigen auf ihren Schnittstellen die Designentscheidung bezüglich Objektzugriff.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Aggregates&lt;/strong&gt;: Damit werden eine Anzahl von Entities oder Value Objects logisch gruppiert um die Kopplung zwischen Teilen des Modells zu reduzieren. Pro Aggregate wird eine Klasse als Aggregate-Root definiert und der Zugriff auf das Aggregate darf nur noch über diesen Root erfolgen.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Strategic Design&lt;/strong&gt;&lt;br /&gt;Hier sind Patterns aufgelistet welche helfen in einem grösseren, komplexen System das Domänenmodell und verschiedene Teile davon herauszubilden.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Core Domain: &lt;/strong&gt;Definiert die wichtigste Domain in einem Projekt. Für diese wird mit grosser Sorgfalt das Modell gefunden und ständig verfeinert. Jegliche Art von Entscheidungen können nun so gefällt werden dass es zuerst der Core Domain zu Gute kommt. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Generic Subdomain&lt;/strong&gt;: Eine Subdomain ist nicht der Hauptgrund weshalb eine Software entwickelt wird, doch ist die Subdomain (z.B ein Zeitzonen-Modell) eine wichtige Unterstützung der Core Domain. Solche Domänen sollten aus der Core Domain gelöst werden um diese nicht unnötig komplex zu machen. Auch können Generic Subdomain häufiger als Core Domains wiederverwendet oder auch eingekauft werden. Vor und Nachteile beim Einkaufen von Sumdomänen sind in diesem Kapitel auch erläutert.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Domain Vision Statement&lt;/strong&gt;: Schlägt vor dass die Coredomäne und ihr Wert zu Projektbeginn beschrieben wird um dem Entwicklungsteam eine gemeinsame Richtung zu geben.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Segregated Core: &lt;/strong&gt;Beschreibt den Vorgang wie aus einem System ohne Core Domain eine solche gebildet werden kann.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Large-Scale Structure&lt;/strong&gt; ist ein Kapitel in welche einige Patterns enthalten sind welche helfen ein Struktur für grosse Systeme zu finden.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Maintaining Model Integrity &lt;/strong&gt;beschreibt Ansätze wie Modelle zwischen unterschiedlichen Systemen synchron gehalten werden oder wie mit den Unterschieden umgegangen werden kann.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-1716973276260259326?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/1716973276260259326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=1716973276260259326' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1716973276260259326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1716973276260259326'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/10/patterns-4-domain-driven-design.html' title='Patterns 4 - Domain Driven Design'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-8850311786501593507</id><published>2007-10-18T09:24:00.000+02:00</published><updated>2007-10-19T13:10:35.326+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entwurfsmuster'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Patterns 3 - Enterprise Application Architecture</title><content type='html'>Wie der Titel dem geneigten Leser andeutet möchte ich in diesem Beitrag das Standardwerk &lt;a href="http://martinfowler.com/books.html"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt;, kurz EAP, von Martin Fowler zitieren. Im Gegensatz zu den &lt;a href="http://enceradeira.blogspot.com/2007/09/patterns-1-gang-of-four.html"&gt;GoF-Patterns&lt;/a&gt; aus meinem ersten Beitrag zu Patterns sind die EAP-Patterns recht spezifisch mit einer Anwendung verbunden. Im folgenden werde ich eine Auswahl von Patterns aus dem Buch auflisten indem ich die Zusammenfassung aus dem Buch pro Pattern zitieren und wo es für mein Verständis wichtig war habe ich noch Kommentare hinzugefügt. Für Details sei an das Buch verwiesen. Nicht erwähnte Patterns sind nicht weniger wichtig, doch haben sie in meinem Umfeld weniger Bedeutung da die Problemstellung nicht vorhanden ist oder ich diese bis heute durch ein Framework lösen lies.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Domain Logic Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt;:&lt;em&gt; 'An object model of the domain that incorporates both behavior and data.'&lt;/em&gt; Wegen &lt;a href="http://domaindrivendesign.org/"&gt;Domain Driven Design&lt;/a&gt; ist dieses Pattern für mich ein Muss.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/serviceLayer.html"&gt;Service Layer:&lt;/a&gt;&lt;em&gt; 'Defines an application's boundary with a layer of services that establishes a set of available operations and coordinates the application's response in each operation.' &lt;/em&gt;Für den Service Layer gibt es die Variation 'Domain Facade' und 'Operation Script'. Da ich den &lt;a href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt;-Ansatz bevorzuge habe ich hier auch eine Bevorzugung für die 'Domain Facade'. Die Eigenschaften eines einzelnen Service hat Evans auch &lt;a href="http://books.google.ch/books?id=7dlaMs0SECsC&amp;amp;pg=PA106&amp;amp;dq=evans+services+%22domain+driven+design%22&amp;amp;sig=VCithHdD-bmhby4yTKzI2gUAzs0#PPA104,M1"&gt;hier &lt;/a&gt;beschrieben.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Data Source Architectural Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/activeRecord.html"&gt;Active Record&lt;/a&gt;: &lt;em&gt;'An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.'&lt;/em&gt; Dieses Pattern kann zu einer Vereinfachung in der Implementation eines &lt;a href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt; führen indem die Datenbankstruktur und die Domain Model-Stuktur gleich gehalten werden.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt;:&lt;em&gt; 'A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.'&lt;/em&gt; Im Gegensatz zum &lt;a href="http://martinfowler.com/eaaCatalog/activeRecord.html"&gt;Active Record&lt;/a&gt; wird das Mapping hier in den Data Mapper ausgelagert. Der Data Mapper wird in der Regel nicht selbst implementiert da dies ein komplexes Unterfangen ist (z.B kann für ein objekte-relationales Mapping &lt;a href="http://en.wikipedia.org/wiki/NHibernate"&gt;NHibernate&lt;/a&gt; verwendet werden). Auch wird ein Data Mapper oft zusammen mit einem &lt;a href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt; verwendet. (siehe auch &lt;a href="http://martinfowler.com/eaaCatalog/mapper.html"&gt;Mapper&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;OR Behavioral Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/unitOfWork.html"&gt;Unit of Work&lt;/a&gt;: &lt;em&gt;'Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.' &lt;/em&gt;Unit of Work sollte in der Regel zusammen mit einem &lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt; implementiert werden.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/identityMap.html"&gt;Identity Map&lt;/a&gt;: 'Ensures that each object gets loaded only once by keeping every loaded object in a map. Looks up objects using the map when referring to them. ' Identity Map muss im Zusammenhang mit einem &lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt; implementiert werden.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/lazyLoad.html"&gt;Lazy Load&lt;/a&gt;: &lt;em&gt;'An object that doesn't contain all of the data you need but knows how to get it.' &lt;/em&gt;Wichtiges Pattern in Zusammenhang mit &lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt; und &lt;a href="http://martinfowler.com/eaaCatalog/domainModel.html"&gt;Domain Model&lt;/a&gt; um zu steuern wann welche Daten von einer Datenquelle geladen werden.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;OR Metadata Mapping Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/queryObject.html"&gt;Query Object&lt;/a&gt;: &lt;em&gt;'An object that represents a database query.'&lt;/em&gt; Das &lt;a href="http://martinfowler.com/apsupp/spec.pdf"&gt;Specification Pattern&lt;/a&gt; ist mit Query Object verwandt. Der Unterschied ist dass das Query Object auf technischer Ebene ein Query beschreibt. Das Specification Pattern selbst kann Begriffe aus der &lt;a href="http://c2.com/cgi/wiki?UbiquitousLanguage"&gt;ubiquitous Language&lt;/a&gt; verwenden und bilden und ist Teil der Geschäftslogik.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/repository.html"&gt;Repository:&lt;/a&gt; &lt;em&gt;'Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects'. &lt;/em&gt;Ich war hier immer unsicher was der Unterschied zwischen einem Repository und einer Factory ist. Aber in &lt;a href="http://books.google.ch/books?id=7dlaMs0SECsC&amp;amp;dq=%22domain+driven+design%22+evans&amp;amp;pg=PP1&amp;amp;ots=ukHQ2XVat2&amp;amp;sig=YzGi7AEjzAvIbYS5paJ7O928VVs&amp;amp;prev=http://www.google.ch/search%3Fhl%3Dde%26q%3D%2522Domain%2BDriven%2BDesign%2522%2BEvans%26meta%3D&amp;amp;sa=X&amp;amp;oi=print&amp;amp;ct=title&amp;amp;cad=one-book-with-thumbnail#PPP1,M1"&gt;Domain Driven Design&lt;/a&gt; von Evans wird klar definiert: 'The Factory makes new objects; the Repository finds old objects' und in &lt;a href="http://books.google.com/books?id=RZXGAAAACAAJ&amp;amp;dq=applying+domain+driven+design"&gt;Applying Domain-Driven Design and Patterns&lt;/a&gt; wird dargestellt dass das Repository für die Persistierung von neu erzeugten Objekten zuständig ist. Ein Repository befindet sich auf einer höheren Ebene als ein &lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt; indem es &lt;a href="http://martinfowler.com/eaaCatalog/queryObject.html"&gt;Query Object&lt;/a&gt; oder &lt;a href="http://martinfowler.com/apsupp/spec.pdf"&gt;Specifications&lt;/a&gt; auswertet und Objekte mit Hilfe eines &lt;a href="http://martinfowler.com/eaaCatalog/dataMapper.html"&gt;Data Mapper&lt;/a&gt; erzeugt.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Web Presentation Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/modelViewController.html"&gt;Model View Controller:&lt;/a&gt; '&lt;em&gt;Splits user interface interaction into three distinct roles. (View, Controller, Model).' &lt;/em&gt;Siehe auch &lt;a href="http://enceradeira.blogspot.com/2007/06/model-view-presenter-mvp-und-seine.html"&gt;MVP&lt;/a&gt; unter welche das Pattern weiter verfeinert dargstellt wird.&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/pageController.html"&gt;Page Controller:&lt;/a&gt;&lt;em&gt; 'An object that handles a request for a specific page or action on a Web site'. &lt;/em&gt;Ich sehe im Page Controller eine Anpassung des &lt;a href="http://martinfowler.com/eaaCatalog/modelViewController.html"&gt;Model View Controller&lt;/a&gt; an das Web-Umfeld wo es die View einmal auf dem Client als HTML-Seite und einmal auf dem Server als Server-Seite gibt. Dies ist auf jeden Fall der Grund weshalb im Unterschied zum &lt;a href="http://martinfowler.com/eaaCatalog/modelViewController.html"&gt;Model View Controller&lt;/a&gt; die View keine Abhängigkeit auf den Page Controller hat. Die clientseitige HTML-Seite hat nämlich eine Abhängigkeit auf den Page-Controller indem diese Web-Requests übermittelt.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/frontController.html"&gt;Front Controller:&lt;/a&gt; &lt;em&gt;'A controller that handles all requests for a Web site'&lt;/em&gt;. Der Controller instanziert abhängig vom Request &lt;a href="http://www.dofactory.com/Patterns/PatternCommand.aspx"&gt;Commandos&lt;/a&gt; welche die weiteren Verarbeitungen vornehmen.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/templateView.html"&gt;Template View:&lt;/a&gt; &lt;em&gt;'Renders information into HTML by embedding markers in an HTML page.' &lt;/em&gt;Das ist wie eine &lt;a href="http://en.wikipedia.org/wiki/Active_Server_Pages"&gt;ASP&lt;/a&gt;-Serverseite.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/applicationController.html"&gt;Application Controller&lt;/a&gt;: &lt;em&gt;'A centralized point for handling screen navigation and the flow of an application'.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Distribution Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/remoteFacade.html"&gt;Remote Facade&lt;/a&gt;:&lt;em&gt; 'Provides a coarse-grained facade on fine-grained objects to improve efficiency over a network.'&lt;/em&gt; Wichtig ist, als Unterschied zum &lt;a href="http://martinfowler.com/eaaCatalog/serviceLayer.html"&gt;Service Layer&lt;/a&gt;, dass die Remote Facade grob-strukturierte Methoden aufweist.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/dataTransferObject.html"&gt;Data Transfer Object&lt;/a&gt;: &lt;em&gt;'An object that carries data between processes in order to reduce the number of method calls.' &lt;/em&gt;Kann zusammen mit &lt;a href="http://martinfowler.com/eaaCatalog/remoteFacade.html"&gt;Remote Facade&lt;/a&gt; zur Datenübertragung verwendet werden. In .NET werden so oft DataSet's oder XML-Serialisierte Objekte als DTO über Webservices verwendet.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Offline Concurrency Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/optimisticOfflineLock.html"&gt;Optimisitc Offline Lock&lt;/a&gt;: &lt;em&gt;'Prevents conflicts between concurrent business transactions by detecting a conflict and rolling back the transaction.' &lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/pessimisticOfflineLock.html"&gt;Pessimistic Offline Lock:&lt;/a&gt; &lt;em&gt;'Prevents conflicts between concurrent business transactions by allowing only one business transaction at a time to access data.' &lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/coarseGrainedLock.html"&gt;Coarse-Grained Lock:&lt;/a&gt; '&lt;em&gt;Locks a set of related objects with a single lock'. &lt;/em&gt;Damit verwaltet ein &lt;a href="http://martinfowler.com/eaaCatalog/optimisticOfflineLock.html"&gt;Optimisitc Offline Lock&lt;/a&gt; oder ein &lt;a href="http://martinfowler.com/eaaCatalog/pessimisticOfflineLock.html"&gt;Pessimistic Offline Lock&lt;/a&gt; die Locks auf höherer Ebene (z.B: &lt;a href="http://safari.oreilly.com/0321268202/app02lev1sec2"&gt;Aggregate&lt;/a&gt;) um den Lockingaufwand zu verringern und die Konsistenzsicherheit zu erhöhen.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/implicitLock.html"&gt;Implicit Lock:&lt;/a&gt; &lt;em&gt;'Allows framework or layer supertype code to acquire offline locks.' &lt;/em&gt;Stellt sicher dass das Locking implizit ist und somit vom Client-Code weder vergessen noch umgangen werden kann.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Session State Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/clientSessionState.html"&gt;Client Session State:&lt;/a&gt; &lt;em&gt;'Stores session state on the client.' &lt;/em&gt;Wird z.B von &lt;a href="http://de.wikipedia.org/wiki/ASP.NET"&gt;ASP.NET&lt;/a&gt;-Seiten als ViewState implementiert. Kann aber auch für alle Arten von Sessions verwendet werden.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/serverSessionState.html"&gt;Server Session State:&lt;/a&gt; &lt;em&gt;'Keeps the session state on a server system in a serialized form'.&lt;/em&gt; Wird z.B von &lt;a href="http://de.wikipedia.org/wiki/ASP.NET"&gt;ASP.NET&lt;/a&gt;-Seiten auf dem System.Web.HttpContext.Session -Property implementiert.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/databaseSessionState.html"&gt;Database Session State:&lt;/a&gt; &lt;em&gt;'Stores session data as committed data in the database.'&lt;/em&gt; Kann bei &lt;a href="http://de.wikipedia.org/wiki/ASP.NET"&gt;ASP.NET&lt;/a&gt; via Konfiguration für den &lt;a href="http://martinfowler.com/eaaCatalog/serverSessionState.html"&gt;Server Session State&lt;/a&gt; eingeschaltet werden.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Base Patterns&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/gateway.html"&gt;Gateway&lt;/a&gt;: &lt;em&gt;'An object that encapsulates access to an external system or resource.'&lt;/em&gt; Vereinfacht ein komplexes externes Inteface und stellt evtl. die Basis zur Verfügung um einen &lt;a href="http://martinfowler.com/eaaCatalog/serviceStub.html"&gt;Service Stub&lt;/a&gt; anlegen zu können. Noch ein paar Erklärungen: Ein Gateway wird für externe Komponenten geschrieben während eine &lt;a href="http://www.dofactory.com/Patterns/PatternFacade.aspx"&gt;Facade&lt;/a&gt; von einer externen Komponente zur Verfügung gestellt wird. Ein &lt;a href="http://www.dofactory.com/Patterns/PatternAdapter.aspx"&gt;Adapter&lt;/a&gt; wiederum ist eine technische Möglichkeit wie ein Gateway umgesetzt werden kann.&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/mapper.html"&gt;Mapper&lt;/a&gt;: &lt;em&gt;'An object that sets up a communication between two independent objects.' &lt;/em&gt;Ist komplexer zu implementieren als ein &lt;a href="http://martinfowler.com/eaaCatalog/gateway.html"&gt;Gateway&lt;/a&gt;. Der Mapper kann als Zwischenschicht gesehen werden welche die zwei angrenzenden Schichten aufeinander abbildet. Beide angrenzenden Schichten bleiben dabei unabhängig und nur der Mapper hat eine Abhängigkeit auf diese.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/layerSupertype.html"&gt;&lt;em&gt;Layer Supertype&lt;/em&gt;&lt;/a&gt;&lt;em&gt;: 'A type that acts as the supertype for all types in its layer.' &lt;/em&gt;Mag ich persönlich nicht da dadurch schnell das &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;Single Responsibility Prinzip&lt;/a&gt; verletzt wird. (z.B Domain Model hat Subertype für Persistenz).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/separatedInterface.html"&gt;Separated Interface&lt;/a&gt;: &lt;em&gt;'Defines an interface in a separate package from its implementation.' &lt;/em&gt;Die Konfiguration der konkreten Instanz (welche das Interface implementiert) kann danach von einem dritten, von beiden Packages abhängigen Komponente oder per &lt;a href="http://martinfowler.com/eaaCatalog/plugin.html"&gt;Plugin&lt;/a&gt; zur Laufzeit erfolgen.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/registry.html"&gt;Registry&lt;/a&gt;: &lt;em&gt;'A well-known object that other objects can use to find common objects and services.'&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/plugin.html"&gt;Plugin:&lt;/a&gt; &lt;em&gt;'Links classes during configuration rather than compilation.'&lt;/em&gt; Dafür gibts heute eine Anzahl Frameworks (z.B Spring.NET). Plugin wird häufig auch im Zusammenhang mit dem &lt;a href="http://www.objectmentor.com/resources/articles/dip.pdf"&gt;Dependency Inversion Principle&lt;/a&gt; und &lt;a href="http://martinfowler.com/eaaCatalog/separatedInterface.html"&gt;Separated Interface&lt;/a&gt; verwendet.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/serviceStub.html"&gt;Service Stub&lt;/a&gt;: &lt;em&gt;'Removes dependence upon problematic services during testing.'&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/recordSet.html"&gt;Record Set&lt;/a&gt;: &lt;em&gt;'An in-memory representation of tabular data.'&lt;/em&gt; = DataSet in .NET&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-8850311786501593507?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/8850311786501593507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=8850311786501593507' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8850311786501593507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/8850311786501593507'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/10/patterns-3-enterprise-application.html' title='Patterns 3 - Enterprise Application Architecture'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-6972811455332428058</id><published>2007-10-14T11:48:00.001+02:00</published><updated>2007-10-22T18:09:31.714+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entwurfsmuster'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Patterns 2 - Prinzipen</title><content type='html'>Im zweiten Beitrag zu Patterns möchte ich einige &lt;a href="http://de.wikipedia.org/wiki/Prinzip"&gt;Prinzpien&lt;/a&gt; ansprechen welche helfen einen ausgereiften und qualtitativ guten Softwaredesign zu finden. Diesen Prinzipien zu folgen ist nicht immer ganz einfach, aber sie machen schlussendlich den Unterschied zwischen einer längerfristig wartbaren und qualtitativ hochstehenden Software und einem &lt;a href="http://de.wikipedia.org/wiki/Hack"&gt;Hack &lt;/a&gt;aus.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://c2.com/cgi/wiki?DontRepeatYourself"&gt;&lt;strong&gt;&lt;em&gt;DRY&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;: &lt;em&gt;Das Prinzip '&lt;strong&gt;D&lt;/strong&gt;on't &lt;strong&gt;r&lt;/strong&gt;epeat &lt;strong&gt;y&lt;/strong&gt;ourself' besagt dass in der Programmierung keine Duplikationen und Redundanzen enthalten sein sollen. Dies gilt für den Programmcode, für Datenbankdefinitionen usw... Das befolgen dieses Prinzips erhöht die Wiederverwendung von Programmcode enorm und ist Ausdruck einer sauberen Programmierung schlechthin.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Law_of_Demeter"&gt;&lt;em&gt;&lt;strong&gt;Law of Demeter&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;strong&gt;: &lt;/strong&gt;&lt;em&gt;Vereinfacht gesagt definiert das Gesetz von Demeter die Regel 'Sprich nur mit deinen engsten Freunden'. Damit wird erreicht dass eine Klasse sich nur an das nächste Umfeld koppelt (die engsten Freunde) und nichts über die Struktur des weiteren Umfelds wissen muss. Das Gesetz definiert formal für die Methode M auf dem Objekt o:&lt;/em&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;o.M() -&gt; darf auf Methoden von o zugreifen (z.B mit this.X())&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;o.M(a) -&gt; darf auf Methoden von a zugreifen (z.B mit a.X())&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;0.M() -&gt; darf auf Methoden von selbst erzeugten Objekten zugreifen (z.B a = new A() wird in der Methode M() angelegt, dann darf o.M() -&gt; a.X() aufrufen)&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;o.M() -&gt; darf auf Methoden von direkt aggregierten Objekten zugreifen(z.B a = new A() wird im Konstruktor angelegt, dann darf o.M() -&gt; a.X() aufrufen)&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;&lt;em&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Open&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Close&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Principle&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;: &lt;em&gt;Das Prinzip verlangt dass eine Softwarekomponente (Module, Klasse, Methode usw...) erweitert werden kann ohne dass die Komponente in ihrer inneren Struktur angepasst werden muss. Der Sinn dahinter ist dass eine Komponente ihre Verantwortlichkeit (&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;gemäß&lt;/span&gt; &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Single&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;Responsibilty&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Principle&lt;/span&gt;&lt;/a&gt; sollte da nur eine sein) erfüllt ohne sich um die entsprechenden Variationen kümmern zu müssen. Für die Variation sollte die Komponente aber entsprechende &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_7"&gt;Erweiterungpunkte&lt;/span&gt; mittels Delegation an &lt;a href="http://en.wikipedia.org/wiki/Abstract_class"&gt;Abstrakte Interfaces&lt;/a&gt; oder Vererbung durch &lt;a href="http://en.wikipedia.org/wiki/Abstract_method"&gt;Abstrakte Methoden&lt;/a&gt; gegen &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;aussen&lt;/span&gt; zur Verfügung stellen. Auf der anderen Seite sollte die Komponente auch ihre interne Struktur gegen &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;aussen&lt;/span&gt; verbergen. Dies ermöglicht dass die Komponente ihre Implementation ändern kann, ohne dass Erweiterung und Variationen davon betroffen wären.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;&lt;em&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;Single&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;Responsibilty&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;Principle&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; &lt;em&gt;Das Prinzip besagt, dass ein Komponente (Module, Klasse, Methode usw..) genau eine Verantwortlichkeit haben soll. Eine &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;Komponente&lt;/span&gt; sei somit nur anzupassen, wenn bezüglich dieser Verantwortlichkeit die Anforderungen ändern. Um dies erreichen zu können müssen folgende wechselwirkenden Aspekte betrachtet werden.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;Es sollte eine hohe &lt;a href="http://en.wikipedia.org/wiki/Cohesion_%28computer_science%29"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;Kohäsion&lt;/span&gt;&lt;/a&gt; erreicht werden. Eine Komponente hat ein hohe &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;Kohäsion&lt;/span&gt; falls sie eine &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;wohldefinierte&lt;/span&gt; Aufgabe &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;abschliessend&lt;/span&gt; und vollständig löst (siehe auch &lt;a href="http://de.wikipedia.org/wiki/Koh%C3%A4sion_%28Informatik%29"&gt;Link&lt;/a&gt;)&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Durch &lt;a href="http://en.wikipedia.org/wiki/Coupling_%28computer_science%29"&gt;lose Kopplung&lt;/a&gt; sollen Komponenten über ein wohldefinierte und möglichst kleine Schnittstelle miteinander verbunden werden&lt;/em&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Mit &lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns"&gt;Separation &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;of&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;Concerns&lt;/span&gt;&lt;/a&gt; sollen die Verantwortlichkeiten in einer Software systematisch aufgeteilt werden. Dabei werden die Verantwortlichkeiten eindeutig an ein Module, Klasse oder Methode übergeben. &lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;em&gt;&lt;a href="http://www.objectmentor.com/resources/articles/lsp.pdf"&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;Liskov&lt;/span&gt; Substitution &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;Principle&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;: &lt;/strong&gt;&lt;/em&gt;&lt;em&gt;"Methoden welche Basisklassen (auch Abstrakte Klassen oder Interfaces) als Parameter haben müssen diese Objekte benutzen können ohne die konkrete Klasse zu kennen". Dies bedeutet für die Überschreibung einer Methode oder die Implementierung einer Methode aus einem Interface:&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;Vorbedingung dürfen nicht verschärft werden&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Nachbedingungen dürfen nicht abgeschwächt werden&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Es dürfen nur Klassen von &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;Exceptions&lt;/span&gt; geworfen werden welche auch von der Basis-Methode geworfen werden oder als mögliche Exception dort dokumentiert wurde. Es dürfen auch Ableitungen von diesen &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;Exceptions&lt;/span&gt; geworfen werden&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;em&gt;Eine Verletzung des &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;Liskov&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;Subsitution&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;Principle&lt;/span&gt; führt zu einer schlecht funktionierenden Umsetzung des &lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;Open&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;Close&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;Principle&lt;/span&gt;&lt;/a&gt; da sich die Erweiterung instabil verhalten wird. &lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.objectmentor.com/resources/articles/dip.pdf"&gt;&lt;em&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;Dependency&lt;/span&gt; Inversion &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;Principle&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; &lt;em&gt;Das Prinzip hat zum Ziel einen flexiblen und somit wartbaren Design zu finden. Die Regeln besagen:&lt;/em&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;em&gt;Übergeordnete Komponenten (Module, Klasse, Methode usw...) und untergeordnete Komponenten sollten nicht direkt voneinander abhängig sein. Beide sollten nur von Abstraktionen abhängig sein.&lt;/em&gt;&lt;/li&gt;&lt;li&gt;&lt;em&gt;Abstraktionen sollten nicht von den Details abhängig sein. Details sollten von den Abstraktionen abhängig sein.&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;em&gt;Das Prinzip ist auch für den &lt;a href="http://de.wikipedia.org/wiki/Testgetriebene_Entwicklung"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;TDD&lt;/span&gt;&lt;/a&gt; Entwicklungsansatz enorm wichtig, da dadurch das &lt;a href="http://de.wikipedia.org/wiki/Mock-Objekt"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;mocken&lt;/span&gt;&lt;/a&gt; und &lt;a href="http://de.wikipedia.org/wiki/Stub_%28Programmierung%29"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;stubben&lt;/span&gt;&lt;/a&gt; von untergeordneten Modulen ermöglicht wird. So gesehen stellt &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;TDD&lt;/span&gt; einen flexible Design sicher, da der übergeordnete Code im &lt;a href="http://en.wikipedia.org/wiki/Unit_test"&gt;Unitest&lt;/a&gt; mit &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;Mocks&lt;/span&gt; und &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;Stubs&lt;/span&gt; und in der laufenden Applikation mit den konkreten untergeordneten Modulen arbeitet.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Noch was vergessen?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-6972811455332428058?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/6972811455332428058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=6972811455332428058' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/6972811455332428058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/6972811455332428058'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/10/patterns-2-prinzipen.html' title='Patterns 2 - Prinzipen'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-1448522298193524416</id><published>2007-09-24T19:46:00.000+02:00</published><updated>2007-10-14T14:28:16.652+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entwurfsmuster'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Patterns 1 - Gang of Four</title><content type='html'>Seit ich mich mit Entwurfsmuster, oder eben Patterns wie ich normalerweise sage, beschäftige haben sich einzelne Steine zu einem grösseren Mosaik zusammengefunden. Das Mosaik hat noch viele Lücken, aber ich möche hier alle mir wichtig erscheinenden und von mir verstandenen Patterns zusammenfassen. Dies ist mein aktuelles "Weltbild" des objektorientierten Software-Designs. Noch ein Wort zu meiner Welt. Meine Welt ist die der grösseren datenzentrierten Geschäftsanwendungen, mit einer Rich-Client Benutzeroberfläche.&lt;br /&gt;&lt;br /&gt;In der Folge möchte ich in mehreren Beiträge diese Patterns auflisten und zusammenstellen. In einem ersten Beitrag gehts es um die &lt;a href="http://www.dofactory.com/Patterns/Patterns.aspx"&gt;'Gang of Four - Patterns' &lt;/a&gt;welche eine Ansammlung von systemnahen, technisch orientierten Patterns darstellen.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternAbstract.aspx"&gt;&lt;strong&gt;Abstract Factory&lt;/strong&gt;&lt;/a&gt;: Erzeugt eine Familie von Objekte unterschiedlicher Typen ohne dass man bei der Benutzung gegen eine konkrete Familie programmiert. Als Beispiel dient hier eine IDbFactory welche IConnection, ITransaction für den Datenbankzugriff erstellt. IDbFactory kann nun konkrete für SQL-Server oder Oracle implementiert werden ohne dass es für den Benutzer von IDbFactory einen Unterschied ausmacht.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternBuilder.aspx"&gt;&lt;strong&gt;Builder&lt;/strong&gt;&lt;/a&gt;: Abstrahiert den Konstruktionsprozess für komplexe Objekte. Falls erforderlich kann der Konstruktionsprozess für andere Typen wiederverwendet werden. So kann zum Beispiel das abstrakte Erstellen einer Rechnung mit einer Anzahl Rechnungspositionen mit einem abstrakten Builder realisiert werden. Als Varianten für konkrete Builder wäre ein &lt;a href="http://de.wikipedia.org/wiki/Kreditor"&gt;KreditorenrechnungsBuilder&lt;/a&gt; und ein &lt;a href="http://de.wikipedia.org/wiki/Debitor"&gt;DebitorenrechnungsBuilder&lt;/a&gt; möglich&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternFactory.aspx"&gt;&lt;strong&gt;Factory Method&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Erzeugt ein Objekt wobei die implementierende Subclass über den konkreten Typ des erzeugten Objekts entscheidet. Ist mit dem Abstract Factory-Pattern dadurch verwandt, dass dort eine Familie von Objekten und hier nur ein Objekt erzeugt wird.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternSingleton.aspx"&gt;&lt;em&gt;&lt;strong&gt;Singleton&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; &lt;em&gt;Stellt sicher, dass eine Klasse nur einmal instanziert ist und global zugegriffen werden kann. Damit kann zum Beispiel eine Infastrukturdienst wie die Protokollierung einfach für alle Programmstellen zugreiffbar gemacht werden. Das Pattern sollte aber sehr bedacht eingesetzt werden, da man sich damit sehr&lt;/em&gt; &lt;em&gt;einfache versteckte Abhängigkeiten baut, welche die Flexibiltät und Wartbarkeit von Programmcode stark einschränken.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternAdapter.aspx"&gt;&lt;em&gt;&lt;strong&gt;Adapter&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt;:&lt;/strong&gt; Ermöglicht den Zugriff auf eine Klasse via ein Interface welches die Klasse selbst aber nicht unterstützt. Als Beispiel könnte man damit in einer &lt;a href="http://www.microsoft.com/germany/msdn/library/net/windowsforms/WindowsForms20.mspx"&gt;Windows.Forms&lt;/a&gt;-Anwendung Controls über eine Interface IControl ansprechen obwohl die Windows.Forms-Library kein solches Interface unterstützt. Ein ControlAdapter würde dann Control auf IControl adaptieren.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternComposite.aspx"&gt;&lt;em&gt;&lt;strong&gt;Composite&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt;:&lt;/strong&gt; Ist eine Datenstruktur in Form eines Baumes mit Vater-Kind-Beziehungen. Jeder Knoten im Baum ist wieder ein Composite mit weiteren enthaltenen Composites oder dann ein Leaf (Blatt) ohne weiteren Composites.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternDecorator.aspx"&gt;&lt;em&gt;&lt;strong&gt;Decorater&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt;:&lt;/strong&gt; Damit kann zur Laufzeit ein Objekt dynamisch erweitert werden. Bestehende Methoden können erweitert werden und auf dem Decorater können neue Funktionalitäten für das Objekt realisiert werden. Als Beispiel könnte man damit eine Klasse Strassenverbindung abhängig von der Strassensituation als GesperrteStrasse oder als StrasseMitStau instanzieren was dann das Verhalten der Strassenverbindung zur Laufzeit beeinflusst.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternChain.aspx"&gt;&lt;em&gt;&lt;strong&gt;Chain of responsibilty&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt;:&lt;/strong&gt; Ermöglicht dass eine Anforderung oder eine Meldung von einer Anzahl Objekten verarbeitet werden kann, wobei jedes Objekt eine spezifische Aufgabe wahrnimmt und die Meldung an ein nächstes weiterleitet. Als Beispiel kann das Verarbeiten einer Meldung in verschiedenen Schritten angesehen werden: 'Dekomprimieren der Meldung' -&gt; 'Authentizität der Meldung prüfen' -&gt; 'Meldung interpretieren' usw....&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternCommand.aspx"&gt;&lt;em&gt;&lt;strong&gt;Command&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;strong&gt;:&lt;/strong&gt; Bildet eine Anfrage an ein Objekt ab und erlaubt damit Transport, Protokollierung, Persistierung usw. der Anfrage. Zum Beispiel kann damit ein Command in einer Queue gespeichert und zu einem späteren Zeitpunkt ausgeführt werden.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternState.aspx"&gt;&lt;em&gt;&lt;strong&gt;State&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Ermöglicht einem Objekt sein Verhalten abhängig von einem Zustand zu ändern. Die Implementation des Verhalten wird an den State delegiert.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternStrategy.aspx"&gt;&lt;em&gt;&lt;strong&gt;Strategy&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Kapselt einen Algorithmus in einer Klasse und ermöglicht damit eine allgemeine Verarbeitung mit spezifischen Strategien zu parametriesieren. So könnte damit die Berechnung einer Strassenverbindung mit der 'KuerzesterWegStrategie' oder mit der 'SchnellsterWegStrategie' parametrisiert werden. Der darunterliegende Berechnungsalgorithmus ist somit unabhängig und kann mit verschiedenen Strategien kombiniert werden.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternTemplate.aspx"&gt;&lt;em&gt;&lt;strong&gt;Template Method&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Kapselt Teile eines Algorithmus in Methoden und erlaubt Subklassen diese Teile zu implementieren. Somit realisiert eine Basisklasse das Grundgerüst eines Algorithmus und die Subklassen können einzelne Verarbeitungsschritte verfeinern.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-1448522298193524416?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/1448522298193524416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=1448522298193524416' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1448522298193524416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1448522298193524416'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/09/patterns-1-gang-of-four.html' title='Patterns 1 - Gang of Four'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-4374739037069279295</id><published>2007-09-09T13:32:00.000+02:00</published><updated>2007-10-14T12:13:50.674+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='FunktionaleProgrammierung'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>IO und funktionale Programmierung in C#</title><content type='html'>&lt;strong&gt;Zusammenfassung&lt;/strong&gt;&lt;br /&gt;Das seiteneffektfreie Programmieren ist in der funktionalen Programmierung ein wichtiger Grundsatz, welcher in der imperativen Programmierung (z.B C#) oft vernachlässigt wird obwohl dadurch höhere Nachvollziehbarkeit, Wiederverwendbarkeit und Testbarkeit erreicht werden kann. Im folgenden wird Anhand eines Beispiels gezeigt wie eine Konsolenausgabe seiteneffektfrei realisiert werden kann.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Einleitung&lt;/strong&gt;&lt;br /&gt;In der funktionalen Programmierung werden Seiteneffekte und Zustände wie der Teufel das Weihwasser gescheut. Leicht passiert es dass durch Seiteneffekte Methoden und Klassen, bei entsprechend ungeeignetem Design, ein &lt;a href="http://de.wikipedia.org/wiki/Nichtdeterminismus"&gt;nicht deterministisches &lt;/a&gt;Verhalten zeigen, was Zuverlässigkeit, Stabilität und Fehleranalyse von Programmen umgemein behindert. IO-Operationen können als Beispiel für Funktionalitäten dienen welche gezwungenermassen Seiteneffekte aufweisen.&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;string line = System.Console.ReadLine();&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Wartet das Programm im Methodenaufruf ReadLine() auf eine Benutzereingabe, so ist nicht sicher ob der Aufruf jemals einen Wert zurückliefert (z.B falls der Benutzer am Bildschirm eingeschlafen ist und somit keine Eingabe macht). Weiter liefert der Aufruf ReadLine() bei jedem Aufruf unter Umständen einen anderen Wert zurück, obwohl aus Sicht des Programmes nichts geändert hat. Dieses Verhalten ist in der imperativen Programmierung (C#) normal, in der funktionalen Programmierung aber verpönnt da in dem darunterliegenden mathematischen Verständnis der Programmierung kein Platz für &lt;a href="http://de.wikipedia.org/wiki/Nichtdeterminismus"&gt;Nichtdeterminismus&lt;/a&gt; und Zufall ist. Auch die Methode System.Console.WriteLine() macht aus mathematischer Sicht wenig Sinn da sie keinen Rückgabewert hat und den Zustand des Programmes nicht verändert.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Beispiel&lt;/strong&gt;&lt;br /&gt;Wie könnte man nun die Seiteneffekte für folgendes Beispiel beheben?&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    int index = 0;&lt;br /&gt;    var numbers = new int[] { 1, 3, 7, 10 };&lt;br /&gt;    foreach (var number in numbers)&lt;br /&gt;    {&lt;br /&gt;        System.Console.WriteLine("Index {0}: {1}", index++, number);&lt;br /&gt;    }&lt;br /&gt;    System.Console.ReadLine();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Lösung&lt;/strong&gt;&lt;br /&gt;&lt;p&gt;Die Seiteneffekte können zwar nicht ganz eliminiert werden da eine Ausgabe auf die Console nun mal erwünscht ist. Die Idee ist es den Seiteneffekt an eine unkritische Stelle zu verschieben und den Zustand der gewünschten Ausgabe explizit abzubilden (wie dies ein &lt;a href="http://en.wikipedia.org/wiki/Monads_in_functional_programming"&gt;Monad &lt;/a&gt;in der funktionalen Programmierung macht). &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    System.Console.Write(&lt;br /&gt;        new int[]{1,3,7,10}&lt;br /&gt;            .Select( (number,index)=&amp;gt; string.Format("Index {0}: {1}{2}", index,number,Environment.NewLine))&lt;br /&gt;                .Aggregate( (lines,line) =&amp;gt; lines + line));&lt;br /&gt;    System.Console.ReadLine();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;Unter Verwendung von &lt;a href="http://en.wikipedia.org/wiki/Language_Integrated_Query"&gt;LINQ&lt;/a&gt; wird mit Select und string.Format() jedes Listenelement in eine Ausgabenzeile projiziert. Danach werden alle Zeilen mit Aggregate und 'lines + line' in einen einzigen String aggregiert welcher am Schluss auf die Konsole ausgegeben werden kann.&lt;br /&gt;&lt;br /&gt;Da unsere Funktion nun die Ausgabe explizit abbildet, können wir Tests schreiben und prüfen ob die Ausgabe korrekt ist:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;[TestMethod]&lt;br /&gt;public void TestOutput()&lt;br /&gt;{&lt;br /&gt;    string output = new int[]{1,3,7,10}&lt;br /&gt;                    .Select( (number,index)=&amp;gt; string.Format("Index {0}: {1}{2}", index,number,Environment.NewLine))&lt;br /&gt;                        .Aggregate( (lines,line) =&amp;gt; lines + line);&lt;br /&gt;    Assert.AreEqual( "Index 0: 1" + Environment.NewLine +&lt;br /&gt;                     "Index 1: 3" + Environment.NewLine +&lt;br /&gt;                     "Index 2: 7" + Environment.NewLine +&lt;br /&gt;                     "Index 3: 10" + Environment.NewLine , output);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-4374739037069279295?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/4374739037069279295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=4374739037069279295' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4374739037069279295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4374739037069279295'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/09/io-und-funktionale-programmierung-in-c.html' title='IO und funktionale Programmierung in C#'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-5384105445464920274</id><published>2007-08-26T11:21:00.000+02:00</published><updated>2007-10-14T12:13:25.477+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='FunktionaleProgrammierung'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>C# 3.0 vs. Haskell und das 'Countdown-Problem'</title><content type='html'>In &lt;a href="http://www.amazon.de/Programming-Haskell-Graham-Hutton/dp/0521692695"&gt;'Programming in Haskell' &lt;/a&gt;wird eine Lösung für das Countdown-Problem in Haskell vorgestellt. Im folgenden wurde diese Lösung in C# 3.0 übersetzt und der Unterschied zwischen Haskell und C# 3.0 analysiert.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Das Countdown Problem&lt;/strong&gt;&lt;br /&gt;Das Countdown Problem lautet wie folgt: Gegeben seien eine Folge positiver ganzer Zahlen, die Quellzahlen, und eine positive ganze Zahl, die Zielzahl. Gesucht wird ein arithmetischer Ausdruck, in dem jede der Quellzahlen höchstens einmal auftritt und der als Ergebnis die Zielzahl liefert. Als Operatoren können in dem Ausdruck +, -, * und / verwendet werden, wobei jedes Zwischenergebnis ebenfalls eine positive ganze Zahl sein muss. Zum Beispiel löst für die Quellzahlen [1; 3; 7; 10; 25; 50] und die Zielzahl 765 der Ausdruck (1 + 50) * (25 - 10) das Problem. [Referenz: &lt;a href="http://www.mathematik.uni-marburg.de/~loogen/Lehre/ws06/Konzepte/Uebungen/u6.pdf"&gt;http://www.mathematik.uni-marburg.de/~loogen/Lehre/ws06/Konzepte/Uebungen/u6.pdf&lt;/a&gt;]&lt;br /&gt;&lt;p&gt;Unter diesem &lt;a href="http://www.mediafire.com/?9xzokzguzg1"&gt;Link &lt;/a&gt;kann die Lösung in C# heruntergeladen werden.&lt;br /&gt;Die C#-Lösung unterscheidet sich zu der Haskell-Lösung vorallem dadurch, dass in C# objektorientierte Konstrukte eingeführt wurden. Nachfolgend eine Auflistung der Haskell-Features welche nur erschwert in C# abgebildet werden konnten&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Recursive_type"&gt;&lt;strong&gt;Rekursive Typen &lt;/strong&gt;&lt;/a&gt;wurden als Klassenhierarchien abgebildet. Folgender Haskell-Code&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;data Expr = Val Int  App Op Expr Expr&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;wurde in C# zu&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public interface IExpression{}&lt;br /&gt;public struct Value : IExpression&lt;br /&gt;{&lt;br /&gt;    public Value(int value){}&lt;br /&gt;}&lt;br /&gt;public abstract class Operation : IExpression&lt;br /&gt;{&lt;br /&gt;    protected Operation(IExpression l, IExpression r){}&lt;br /&gt;}&lt;br /&gt;public class Add : Operation&lt;br /&gt;{&lt;br /&gt;    public Add(IExpression l, IExpression r) : base(l, r) { }&lt;br /&gt;}&lt;br /&gt;public class Sub : Operation&lt;br /&gt;{&lt;br /&gt;    public Sub(IExpression l, IExpression r) : base(l, r) { }&lt;br /&gt;}&lt;br /&gt;public class Mul : Operation&lt;br /&gt;{&lt;br /&gt;    public Mul(IExpression l, IExpression r) : base(l, r) { }&lt;br /&gt;}&lt;br /&gt;public class Div : Operation&lt;br /&gt;{&lt;br /&gt;    public Div(IExpression l, IExpression r) : base(l, r) { }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Während der Haskellausdruck an &lt;a href="http://de.wikipedia.org/wiki/Produktionsregel"&gt;Produktionsregeln&lt;/a&gt; erinneren und somit eine &lt;a href="http://martinfowler.com/bliki/DomainSpecificLanguage.html"&gt;internal DSL&lt;/a&gt; bilden, fehlt in C# 3.0 eine solche Möglichkeit. In C# wurde der dieser Ausdruck als ein Expression-Tree abgebildet. Die Anwendung des rekursiven Typs sieht in Haskell wie folgt aus:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;evaluate( App Add( Val 2 ) ( Val 3 ))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;während in C# der Expression-Tree wie folgt instanziert und evaluiert würde:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;new Add(new Value(2), new Value(3)).Eval();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Das Problem an der objektorientierten Lösung in C# ist, dass in der Anwendung immer Objekte erzeugt werden müssen. Dies verlangt das Schlüsselwort 'new' welches im Gegensatz zum Haskell-Beispiel, den Ausdruck verschleiert. Auch ein &lt;a href="http://martinfowler.com/bliki/FluentInterface.html"&gt;FluentInterface &lt;/a&gt;bringt in diesem Fall nichts, da damit keine Ausdrücke verschachtelt werden könnten.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://en.wikipedia.org/wiki/Lazy_evaluation"&gt;Lazy-Evaluation&lt;/a&gt;&lt;/strong&gt; wird für die Lösung des Countdown-Problem benötigt, ansonsten alle Lösungskandidaten am Anfang der Berechnung in den Speicher geladen werden müssten. Lazy-Evaluation ermöglicht die Berechnungsfunktionen so zu kaskadieren, dass nur immer die gerade benötigten Resultat ermittelt werden und dass nicht mehr benötigte Zwischenresultat sofort im Speicher freigegeben werden können.&lt;br /&gt;Während in Haskell diesbezüglich keine Vorkehrungen nötig sind muss in C# explizit jede Berechnung und Berechnungsschlaufe über IEnumerable erfolgen. Verwendet man &lt;a href="http://de.wikipedia.org/wiki/LINQ"&gt;LINQ&lt;/a&gt; und &lt;a href="http://en.wikipedia.org/wiki/Extension_method"&gt;Extension-Methods&lt;/a&gt; so können alle Haskell-Lösungen in die entsprechende LINQ-Lösung übersetzt werden. Aus der Haskell-Funktion&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;&lt;br /&gt;solutions :: [Int] -&amp;gt; Int -&amp;gt; [Expr]&lt;br /&gt;solutions ns n = [e  ns' &amp;lt;- choises ns,&lt;br /&gt;                      e &amp;lt;- exprs ns',&lt;br /&gt;                      evaluate e == [n]]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;wird in C# 3.0 zu&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public static IEnumerable&amp;lt;IExpression&amp;gt; GetSolutions(IEnumerable&amp;lt;int&amp;gt; values, int result)&lt;br /&gt;{&lt;br /&gt;    return values.Choises().SelectMany(choise =&amp;gt; choise.Exprs()).Where( exp =&amp;gt; exp.IsValid() &amp;amp;&amp;amp; exp.Eval() == result);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="http://en.wikibooks.org/wiki/Haskell/Pattern_matching"&gt;Pattern-Matching&lt;/a&gt;&lt;/strong&gt; ist ein Konstrukt um die Komplexität pro Funktion oder Methode zu reduzieren. Die Haskell-Funktion&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;perms :: [a] -&amp;gt; [[a]]&lt;br /&gt;perms []     = [[]]&lt;br /&gt;perms (x:xs) = concat (map (interleave x)(perms xs))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;behandelt den Fall der leeren Liste und den Fall der nicht leeren Liste in zwei getrennten Funktionsimplementionen. Da C# Pattern-Matching nicht kennt müssen dort die beiden Fälle in der Methodenimplementation durch eine if-Anweisung explizit behandelt werden:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public static IEnumerable&amp;lt;IEnumerable&amp;lt;int&amp;gt;&amp;gt; Perms(this IEnumerable&amp;lt;int&amp;gt; list)&lt;br /&gt;{&lt;br /&gt;    if (list.Count() == 0)&lt;br /&gt;    {&lt;br /&gt;        return new int[][] { new int[] { } };&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        return list.Skip(1).Perms().SelectMany(subList =&amp;gt; subList.Interleave(list.First()));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Listen&lt;/strong&gt; sind in Haskell tief in die Sprache eingebettet. Folgendes Beispiel&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;perms :: [a] -&amp;gt; [[a]]&lt;br /&gt;perms []     = [[]]&lt;br /&gt;perms (x:xs) = concat (map (interleave x)(perms xs))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;ist im starken Kontrast mit C# 3.0:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;public static IEnumerable&amp;lt;IEnumerable&amp;lt;int&amp;gt;&amp;gt; Perms(this IEnumerable&amp;lt;int&amp;gt; list)&lt;br /&gt;{&lt;br /&gt;     if (list.Count() == 0)&lt;br /&gt;     {&lt;br /&gt;         return new int[][] { new int[] { } };&lt;br /&gt;     }&lt;br /&gt;     else&lt;br /&gt;     {&lt;br /&gt;         return list.Skip(1).Perms().SelectMany(subList =&amp;gt; subList.Interleave(list.First()));&lt;br /&gt;     }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Folgendes kann beobachtet werden:&lt;br /&gt;- x in Haskell entspricht list.First() in C#&lt;br /&gt;- xs in Haskell entspricht list.Skip(1) in C#&lt;br /&gt;&lt;br /&gt;Listen haben unter C# einen langen Leidensweg hinter sich:&lt;br /&gt;- .NET 1.0 kennt untypisierten Listen aus &lt;a href="http://msdn2.microsoft.com/en-us/library/system.collections.aspx"&gt;System.Collections&lt;/a&gt;&lt;br /&gt;- .NET 2.0 unterstützte typisierte Listen aus &lt;a href="http://msdn2.microsoft.com/en-us/library/system.collections.generic.aspx"&gt;System.Collections.Generic&lt;/a&gt;&lt;br /&gt;- ab Visual Studio 2008 wird nun LINQ eingeführt&lt;br /&gt;&lt;br /&gt;LINQ ist grossartig doch leider kommt es sehr spät. Eine grosse Erneuerung ist die Erkenntnis dass man anstellen von Listen nun mit IEnumerable's arbeitet. Während Listen (z.B List&lt;t&gt;) in .NET die Eigenschaft der &lt;a href="http://en.wikipedia.org/wiki/Eager_evaluation"&gt;Eager Evaluation&lt;/a&gt; haben, wird mit IEnumerable &lt;a href="http://en.wikipedia.org/wiki/Lazy_evaluation"&gt;Lazy-Evaluation&lt;/a&gt; erreicht (siehe auch oben). Leider muss man sich in Zukunft immer explizit für 'Eager' oder 'Lazy'-Evaluation entscheiden und es wird immer einen konzeptionellen Bruch zwischen den beiden Ansätzen geben. Die Verwendung von IEnumerable (Lazy-Evaluation) ist auf jeden Fall der Verwendung von IList,ICollection usw. (Eager-Evaluation) vorzuziehen.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;strong&gt;Zusammenfassung&lt;/strong&gt;&lt;br /&gt;Mit C# 3.0 lassen sich einige Konzepte aus der funktionalen Programmierung anwenden. Diese Konzepte sind allerdings in einer funktionalen Sprache wie Haskell eleganter umgesetzt. Dagegen steht im Kontrast dass in Haksell objektorientierte Konzepte fehlen, welche vorallem für den Bau von grossen und komplexen Softwaresystemen benötigt werden (z.B &lt;a href="http://en.wikipedia.org/wiki/Abstract_data_type"&gt;Abstrakte Datentypen&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-5384105445464920274?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/5384105445464920274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=5384105445464920274' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5384105445464920274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/5384105445464920274'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/08/c-30-vs-haskell-und-das-countdown.html' title='C# 3.0 vs. Haskell und das &apos;Countdown-Problem&apos;'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-2191944663000168254</id><published>2007-08-17T17:51:00.001+02:00</published><updated>2007-10-14T12:08:41.020+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Domain-Driven Design von Eric Evans. Kapitel 1-2</title><content type='html'>Nachfolgend fasse ich die Kapitel 1-2 vom Buch &lt;a href="http://www.informit.com/store/product.aspx?isbn=0321125215"&gt;Domain-Driven Design&lt;/a&gt; von Eric Evans aus meiner Sicht zusammen. Folende Patterns zeigten für mich neue Aspekte auf und werden meine Arbeit in Zukunft beeinflussen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Layered Architecture:&lt;/strong&gt; In diesem Kapitel werden die verschiedenen Schichten wie 'Infrastructure Layer', 'Domain Layer', 'Application Layer' und 'Presentation Layer' konkret im Zusammenhang mit Domain-Driven Design beschrieben. In Kombination mit dem Pattern &lt;a href="http://enceradeira.blogspot.com/2007/06/model-view-presenter-mvp-und-seine.html"&gt;Model-View-Presenter&lt;/a&gt; habe ich nun eine Idee, wie ein Model darin aufgebaut werden könnte.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Modules:&lt;/strong&gt; Das Kapitel zeigt mir auf, dass bei der Auftrennung von Modules (Namespaces,Assemblies) eher Grenzen zu wählen sind welche in der Fachdomäne auch vorhanden sind. So macht es zum Beispiel eher Sinn anhand von Begriffen wie 'Kundenverwaltung' oder 'Rechnungmodul' Module aufzuteilen, als anhand von Begriffen wie 'DomainLogic', 'DataServices' usw. Die führt dazu dass die Module eine geringe Kopplung aufweisen und eine abgeschlossene Einheit bilden.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aggregates:&lt;/strong&gt; Das Pattern hilft durch seine Regeln das Domänenmodell auf einfache Art und Weise übersichtlich und somit auch wartbar und einfach verständlich zu halten. Hätte ich früher noch über Module nachgedacht um die Kopplung zwischen Teilen des Domänenmodels zu reduzieren, geht das nun mit Aggregates deutlich einfacher und flexibler. Mir hatte immer eine Element im Design gefehlt wo spezielle Verantwortlichkeiten wie z.B Validierung und Konsistenzprüfung untergebracht werden konnten. Dies kann nun einfach im Domänenmodell selbst im Aggregateroot untergebracht werden. Allerdings habe ich auch schon gesehen, dass im Aggregateroot Infrastrukturdienste wie die Persistierung untergebracht wurden. Hier muss man sich aber strikte an die Verantwortlichkeiten des Domänenmodells und somit eines Aggregates erinnern und nur Domänenlogik implementieren.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Factories und Repositories:&lt;/strong&gt; In beiden Kapitel wird konkret erläutert was die Verantwortlichkeiten von Factories und Repositories sind. Während Factories für das Erstellen von neuen Objekte und neuen Aggregates zuständig sind, behandeln Repositories das Auffinden und Instanzieren von persistierten Objekten und Aggregates. Mir werden diese Kapitel in Zukunft helfen, unabhängig von dem unterliegenden Datenzugriffsmechanismus einen einheitlichen, objektorientierten Design für die Persistenzschicht zu finden.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-2191944663000168254?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/2191944663000168254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=2191944663000168254' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2191944663000168254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/2191944663000168254'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/08/domain-driven-design-von-eric-evans.html' title='Domain-Driven Design von Eric Evans. Kapitel 1-2'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-1079398982534351217</id><published>2007-07-29T12:59:00.000+02:00</published><updated>2007-10-14T12:12:29.507+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FunktionaleProgrammierung'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Programming in Haskell (durch die C#-Brille gesehen)</title><content type='html'>Während des letzten Monats habe ich das Buch &lt;a href="http://www.amazon.de/Programming-Haskell-Graham-Hutton/dp/0521692695"&gt;'Programming in Haskell' &lt;/a&gt;durchgearbeitet. Es hat mir einen guten Einblick in die Welt der funktionalen Programmierung ermöglicht. Obwohl ich mir nicht die Zeit nahm jedes Beispiel und jede Übung bis ins letzte Detail zu verstehen, habe ich doch einige Konzepte verstanden welche meine Arbeit als Softwareentwickler in Zukunft beeinflussen werden. Folgende Punkte waren für mich neu und haben mich beeindruckt:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Abstraktion auf Ebene von einzelnen Funktionen und Operationen&lt;/strong&gt;&lt;br /&gt;Folgender C#-Code berechnet die laufende Summe über einen Array von Integers:&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt; public static int[] GetLaufendeSumme(int[] values)&lt;br /&gt; {&lt;br /&gt;    int[] summierung = new int[values.Count()];&lt;br /&gt;    int sum = 0;&lt;br /&gt;    for( int i=0; i&amp;lt;values.Count(); i++ )&lt;br /&gt;    {&lt;br /&gt;       sum = values[i] + sum;&lt;br /&gt;       summierung[i] = sum;&lt;br /&gt;    }&lt;br /&gt;    return summierung;&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In Haskell habe ich nun mit Hilfe der Funktion &lt;a href="http://www.zvon.org/other/haskell/Outputglobal/index.html"&gt;foldl &lt;/a&gt;folgende Lösung gefunden:&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;getLaufendeSumme :: [Int]-&amp;gt;[Int]&lt;br /&gt;getLaufendeSumme = foldl (&lt;br /&gt;                    \summen wert -&amp;gt; case summen of&lt;br /&gt;                         []        -&amp;gt; [wert]&lt;br /&gt;                         otherwise -&amp;gt; summen++[wert + last summen] ) []&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Da &lt;a href="http://www.zvon.org/other/haskell/Outputglobal/index.html"&gt;foldl&lt;/a&gt; das Iterieren und Berechnen von neuen Werten aufgrund der iterierten Werten abstrahiert ist der Haskellcode im Vergleich zum C#-Beispiel ausdruckstärker. &lt;a href="http://www.zvon.org/other/haskell/Outputglobal/index.html"&gt;foldl&lt;/a&gt; ist somit ein Pattern welches in ähnlichen Situation wieder angewendet werden kann. Im Gegensatz zu einer for-Schleife in C# ist mit &lt;a href="http://www.zvon.org/other/haskell/Outputglobal/index.html"&gt;foldl&lt;/a&gt; die Absicht und das Funktionieren des Codes klar.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Lazy Evaluation&lt;/strong&gt;&lt;br /&gt;Mit Layz Evaluation sorgt der Intepreter dafür, dass ein Ausdruck erst dann ausgewertet wird wenn der Wert des Ausdrucks benötigt wird. Bei Haskell werden alle Ausdrücke standardmässig mit 'Lazy Evaluation' aufgelöst. Nur Dank dieser Technik ist es möglich mit unendlichen Listen zu arbeiten. Im folgenden Bespiel definiert die Funktion fibs alle Fibonacci-Zahlen. Mit der Funktion fibGT kann dann die erste Fibonacci-Zahl, welche grösser als ein bestimmter Wert ist, gefunden werden.&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;fibs :: [Integer]&lt;br /&gt;fibs = [0,1]++[ a+b  (a,b) &amp;lt;- zip fibs (tail fibs) ]&lt;br /&gt;&lt;br /&gt;fibGT :: Integer -&amp;gt; Integer&lt;br /&gt;fibGT n = head (dropWhile (\a-&amp;gt;a&amp;lt;n) fibs)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Bei C# werden standardmässig alle Ausdrücke sofort evaluiert und das Arbeiten mit z.B unendlichen Listen ist nur durch die explitzite Verwendung eines Iterators (IEnumerable, IEnumerator, etc.) möglich.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Pattern Matching&lt;/strong&gt;&lt;br /&gt;'Pattern Matching' hilft dabei, eine Funktion für verschiedene Fälle getrennt zu implementieren. So entscheidet der Haskell-Interpreter aufgrund der Argumente welche Funktionsimplementation für den aktuellen Fall herbeigezogen werden muss. So sind zum Bespiel folgende Funktionsdefinitionen für sumInt und sumInt2 gleichwertig:&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;sumInt :: [Integer] -&amp;gt; Integer&lt;br /&gt;sumInt (n:ms) = n + sumInt ms&lt;br /&gt;sumInt [] = 0&lt;br /&gt;&lt;br /&gt;sumInt2 :: [Integer] -&amp;gt; Integer&lt;br /&gt;sumInt2 ns = if ns == [] then 0&lt;br /&gt;             else (head ns) + sumInt2 (tail ns)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Während in der Funktion sumInt für den Fall '(n:ms)' und den Fall '[]' zwei Implementationen gemacht wurden, wird in der Funktion sumInt2 alles innerhalb einer Implementation mit Hilfe von if-Entscheidungen behandelt.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;&lt;a href="http://de.wikipedia.org/wiki/Induktion_(Denken)"&gt;Induktives Denken&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;Folgender Haskell-Code berechnet die &lt;a href="http://de.wikipedia.org/wiki/Fibonacci-Folge"&gt;Fibonacci-Zahlen &lt;/a&gt;(0,1,1,2,3,5,8,13,21...)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="BORDER-RIGHT: #999999 1px dashed; PADDING-RIGHT: 5px; BORDER-TOP: #999999 1px dashed; PADDING-LEFT: 5px; FONT-SIZE: 12px; PADDING-BOTTOM: 5px; OVERFLOW: auto; BORDER-LEFT: #999999 1px dashed; WIDTH: 100%; COLOR: #000000; LINE-HEIGHT: 14px; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dashed; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; BACKGROUND-COLOR: #eee"&gt;&lt;code&gt;fibs :: [Integer]&lt;br /&gt;fibs = [0,1]++[ a+b  (a,b) &amp;lt;- zip fibs (tail fibs) ]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Mich fasziniert an dieser Lösung, dass der Code nicht 'imperativ' als Anweisung verstanden werden kann. Der Haskell-Code oben lässt mich folgendes denken:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;fibs liefert mir alle &lt;a href="http://de.wikipedia.org/wiki/Fibonacci-Folge"&gt;Fibonacci-Zahlen&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Die Fibonacci-Zahlen beginnen mit 0 und 1&lt;/li&gt;&lt;li&gt;Die weiteren Zahlen berechne ich indem ich die Fibonacci-Reihe mit der um eins verschobenen Fibonacci-Reihe pro Zahl kombinieren und pro Kombination die Zahlen zusammenzähle.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Für mich ist diese Denkweise ungewohnt, da die Definition der Funktion fibs davon ausgeht dass fibs (bereits) die korrekten Fibonacci-Zahlen zurückliefert. Auch hat die Funktion deklarativen Charakter. Es werden nämlich nur die Berechnungsregeln beschrieben. Wie und wann welche Berechnung erfolgt ist nicht ersichtlich.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-1079398982534351217?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/1079398982534351217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=1079398982534351217' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1079398982534351217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/1079398982534351217'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/07/programming-in-haskell-durch-die-c.html' title='Programming in Haskell (durch die C#-Brille gesehen)'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-4223233764422119438</id><published>2007-06-09T16:47:00.001+02:00</published><updated>2007-10-14T12:11:27.533+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Entwurfsmuster'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Model-View-Presenter (MVP) und seine Geschmacksrichtungen</title><content type='html'>Neulich hat &lt;a href="http://codebetter.com/blogs/jeremy.miller/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Jeremy&lt;/span&gt; D. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Miller&lt;/span&gt;&lt;/a&gt; in seinem Blog die verschiedenen Ausprägungen des &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Model&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;View&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Presenter&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;Patterns&lt;/span&gt; erörtert. Hier ein kurze Zusammenfassung dessen was mir wichtig erscheint:&lt;br /&gt;&lt;br /&gt;Dem &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;MVP&lt;/span&gt; liegen im allgemeinen folgende Definitionen zu Grunde:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;Model&lt;/span&gt; &lt;/strong&gt;ist eine Abbildung dessen was dargestellt wird.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;View&lt;/span&gt;&lt;/strong&gt; ist die Darstellung.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;Presenter&lt;/span&gt;&lt;/strong&gt; bringt das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Model&lt;/span&gt; auf der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;View&lt;/span&gt; zur Darstellung und aktualisiert das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;Model&lt;/span&gt; aufgrund von Benutzereingaben.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.martinfowler.com/eaaDev/AutonomousView.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;The&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;Autonomous&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;View&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;Das '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;Anti&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;Pattern&lt;/span&gt;'. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;Model&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;View&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;Presenter&lt;/span&gt; sind in einer Klasse vereint.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.martinfowler.com/eaaDev/SupervisingPresenter.html"&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;Supervising&lt;/span&gt; Controller&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;Presenter&lt;/span&gt;: &lt;/strong&gt;Übergibt das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;Model&lt;/span&gt; (oder Teile davon) der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;View&lt;/span&gt; zur Darstellung. Der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;Presenter&lt;/span&gt; wird von der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;View&lt;/span&gt; aufgerufen um auf Benutzereingaben zu reagieren.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;View&lt;/span&gt;:&lt;/strong&gt; bringt das vom &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;Presenter&lt;/span&gt; an die &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;View&lt;/span&gt; übergebenen &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;Model&lt;/span&gt; zur Darstellung (z.B mit Databinding). Leitet Benutzereingaben an den &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;Presenter&lt;/span&gt; weiter.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Die &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;View&lt;/span&gt; ist somit direkt vom Modell abhängig.&lt;/p&gt;&lt;strong&gt;&lt;a href="http://www.martinfowler.com/eaaDev/PassiveScreen.html"&gt;Passive &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;View&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;Presenter&lt;/span&gt;&lt;/strong&gt;: Kapselt das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;Model&lt;/span&gt; gegenüber der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;View&lt;/span&gt;. Übernimmt das Databinding indem die dargestellten Werte (nicht das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;Model&lt;/span&gt;) explizit der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;View&lt;/span&gt; zur Darstellung übergeben werden. Der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;Presenter&lt;/span&gt; wird von der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;View&lt;/span&gt; aufgerufen um auf Benutzereingaben zu reagieren.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;View&lt;/span&gt;&lt;/strong&gt;: Stellt die vom &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;Presenter&lt;/span&gt; übermittelten Werte dar und leitet Benutzereingaben an den &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;Presenter&lt;/span&gt; weiter.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Gegenüber dem &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;Supervising&lt;/span&gt; Controller Pattern hängt die &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;View&lt;/span&gt; hier nicht vom &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;Modell&lt;/span&gt; ab.&lt;/p&gt;&lt;a href="http://www.martinfowler.com/eaaDev/PresentationModel.html"&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;Presentation&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;Model&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;Presentation&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;Model&lt;/span&gt;: &lt;/strong&gt;Das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;Model&lt;/span&gt; und der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;Presenter&lt;/span&gt; sind hier zusammengeführt. Das Presentation Model zeigt gegenüber der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;View&lt;/span&gt; die darzustellenden Werte und reagiert falls ein solcher Wert verändert wird. Das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;Presentation&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_55"&gt;Model&lt;/span&gt; wird von der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_56"&gt;View&lt;/span&gt; aufgerufen um auf Benutzereingaben zu reagieren.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;View&lt;/span&gt;:&lt;/strong&gt; Bindet das &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_58"&gt;Presentation&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;Model&lt;/span&gt; direkt für die Darstellung.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Für die Kommunikation zwischen &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;View&lt;/span&gt; und &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;Presenter&lt;/span&gt; gibt es bei allen &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;Pattern&lt;/span&gt; zwei Möglichkeiten:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Direkt: Die &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;View&lt;/span&gt; ruft den &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_64"&gt;Presenter&lt;/span&gt; direkt und explizit via Methoden auf (z.B im &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_65"&gt;Eventhandler&lt;/span&gt; in der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_66"&gt;View&lt;/span&gt;).&lt;/li&gt;&lt;li&gt;Indirekt: Der &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_67"&gt;Presenter&lt;/span&gt; abonniert &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_68"&gt;Events&lt;/span&gt; welche die &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_69"&gt;View&lt;/span&gt; zur Verfügung stellt.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Zur Zeit verwende ich meistens das Passiv View Pattern um eine höchstmögliche Testabdeckung in den Unittests zu erreichen.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-4223233764422119438?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/4223233764422119438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=4223233764422119438' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4223233764422119438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/4223233764422119438'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/06/model-view-presenter-mvp-und-seine.html' title='Model-View-Presenter (MVP) und seine Geschmacksrichtungen'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-9049717155300708447</id><published>2007-06-07T18:48:00.000+02:00</published><updated>2007-10-14T12:10:53.392+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Orcas'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>LinqToSql vs. NHibernate</title><content type='html'>Im folgenden vergleiche ich 'LINQ to SQL' mit NHibernate und Stelle die Unterschiede und Gemeinsamkeiten dieser beiden O/R-Mapper dar.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Sessions&lt;/strong&gt;&lt;br /&gt;Was in 'LINQ to SQL' der DataContext ist in NHibernate die Session. Beide Implementationen realisieren &lt;a href="http://www.martinfowler.com/eaaCatalog/unitOfWork.html"&gt;UnitOfWork&lt;/a&gt; und &lt;a href="http://www.martinfowler.com/eaaCatalog/identityMap.html"&gt;IdentityMap&lt;/a&gt; was uns ein sicheres und bequemes Arbeiten mit einem &lt;a href="http://www.martinfowler.com/eaaCatalog/domainModel.html"&gt;DomainModel &lt;/a&gt;ermöglicht.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Transaktionen und Locking&lt;/strong&gt;&lt;br /&gt;Da beide O/R-Mapper &lt;a href="http://www.martinfowler.com/eaaCatalog/unitOfWork.html"&gt;UnitOfWork&lt;/a&gt; implementieren, unterstützen uns beide auf ähnliche Weise beim optimistischen Locking. Beide O/R-Mapper halten den für das optimistische Locking nötigen Ursprungszustand der Objekte intern, also im DataContext oder in der Session.&lt;br /&gt;&lt;br /&gt;Für das pessimistische Locking ermöglichen beide O/R-Mapper den Zugriff auf die Transaktion auf welcher der Transaktionsbeginn und -ende, sowie der Isolationslevel gesteuert werden kann.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Persistence Ignorance (PI)&lt;/strong&gt;&lt;br /&gt;Nur NHibernate ermöglicht das Persistieren von beliebigen Objekten. Bei 'LINQ to SQL' (in Orcas Beta1) muss INotifyPropertyChanging und INotifyPropertyChanged implementiert werden. In 'LINQ to SQL' kann wahlweise die Mapping-Information auf der Klasse als Attribute oder in einem externen XML abgelegt werden.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Eliminierung O/R Impedance-Mismatch&lt;/strong&gt;&lt;br /&gt;Hier zeigt sicher der größte Unterschied zwischen den beiden O/R-Mappern. Folgende nicht abgeschlossene Liste zeigt Features welche NHibernate unterstützt, 'LINQ to SQL' aber nicht:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Abfragen berücksichtigen unpersistierte Änderungen&lt;/li&gt;&lt;li&gt;Unterstützung mehrerer Abbildungsarten für die Vererbung ( table-per-class / table-per-subclasss / table-per-concrete-class )&lt;/li&gt;&lt;li&gt;Mapping von n-m Beziehung&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Da 'LINQ to SQL' den Punkt 1. nicht unterstützt müsste zum Beispiel mit Aggregates (Eric Evans: Domain Driven Design) gearbeitet werden. Diese würden die unpersistierten Änderungen in ihrem Aggregate berücksichtigen und verwalten.&lt;/p&gt;&lt;strong&gt;Abfragesprache&lt;/strong&gt;&lt;br /&gt;'LINQ to SQL' ist mit der Abfragesprache LINQ zur Zeit hier im Vorteil. Eine LINQ-Implementation für NHibernate ist aber in Bearbeitung und danach wird es unter diesem Punkte keine nennenswerte Unterschiede geben.&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Wartung&lt;/strong&gt;&lt;br /&gt;Hier sehe ich keine grossen Unterschiede, da das Warten der Mapping-Informationen immer eine mühsame Angelegenheit ist. Mit dem 'LINQ to SQL' -Designer (Beta1) kann sehr schnell eine erste Version eines Mapping-Schemas erstellen werden. Die Wartung und Pflege des Schemas erfolgt danach aber manuell.&lt;br /&gt;&lt;br /&gt;Falls jemand schon praktische Erfahrungen in einem grösseren Projekt mit 'LINQ to SQL' hat, würde ich mich über einen Erfahrungsbericht sehr freuen.&lt;br /&gt;&lt;br /&gt;So nun muss ich mir noch LINQ To Entities anschauen!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-9049717155300708447?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/9049717155300708447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=9049717155300708447' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/9049717155300708447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/9049717155300708447'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/06/linqtosql-vs-nhibernate.html' title='LinqToSql vs. NHibernate'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-3202553886183488178</id><published>2007-05-30T19:37:00.000+02:00</published><updated>2007-05-30T20:08:35.883+02:00</updated><title type='text'>Mein erster Blogeintrag</title><content type='html'>Heute will ich meinen ersten Blogeintrag veröffentlichen. Ein Vorsatz der ich mir schon länger vorgenommen habe!&lt;br /&gt;&lt;br /&gt;Als analytisch, vorsichtig und strukturiert denkender Mensch musste ich mir aber zuerst einige Fragen beantworten, bevor ich nun mit meinem ersten Blogeintrag starte.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frage:&lt;/strong&gt; Soll ich auf Englisch oder Deutsch schreiben?&lt;br /&gt;&lt;strong&gt;Antwort:&lt;/strong&gt; Ich schreibe auf Deutsch da mein Deutsch besser als mein Englisch ist. Falls ich jemals so schlaue Sachen schreiben werde dass es auch die "englische Welt" wissen sollte, wechsle ich die Sprache.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frage:&lt;/strong&gt; Über was schreibe ich?&lt;br /&gt;&lt;strong&gt;Antwort:  &lt;/strong&gt;Ich schreibe über Softwareentwicklung wie ich sie verstehe, was ich davon verstanden habe oder was ich noch verstehen möchte.  Ich schreibe hier über Softwareentwicklung da dies mein Job und einer meiner Leidenschaften ist. Falls ich damit die Welt verändern kann, werde ich vielleicht auch mal über Sachen sprechen welche mich persönlich beschäftigen.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Frage: &lt;/strong&gt;Warum schreibe ich?&lt;br /&gt;&lt;strong&gt;Antwort: &lt;/strong&gt;Da ich schon immer das Bedürfnis hatte den anderen die Welt aus meiner Sicht und Überzeugung zu erklären. Und natürlich bin ich auch gespannt ob der Blog tatsächlich auch jemals von jemanden gelesen wird.&lt;br /&gt;&lt;br /&gt;Also los ... mal schauen was daraus wird.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-3202553886183488178?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/3202553886183488178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=3202553886183488178' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/3202553886183488178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/3202553886183488178'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/05/mein-erster-blogeintrag.html' title='Mein erster Blogeintrag'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8995878145266667696.post-237395369717784892</id><published>2007-05-28T15:30:00.000+02:00</published><updated>2007-10-14T12:10:00.665+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Orcas'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Lambda'/><title type='text'>p geht zu f</title><content type='html'>Mit der nächsten Version von .NET (Codename 'Orcas') werden wir tagtäglich mit Lambda-Ausdrücken arbeiten. Doch wie spricht man ein Lambda-Ausdruck überhaupt aus?&lt;br /&gt;&lt;br /&gt;Was ist zum Beispiel mit &lt;strong&gt;p =&gt; f =&gt; f(p) &lt;/strong&gt;?&lt;br /&gt;&lt;br /&gt;Wes Dyer vom C# Compiler Team spricht es in einem &lt;a href="http://wm.microsoft.com/ms/msdn/visualcsharp/wes_dyer_2007_01/WesDyer_0002.wmv"&gt;Interview &lt;/a&gt;als 'goes to' aus. In Englisch ist das also &lt;strong&gt;p goes to f goes to f(p)&lt;/strong&gt;. Ich finde dies in Ordnung aber beim Einsetzen der Variable f im Ausdruck f =&gt; f(p) finde ich das 'goes to' ungenau, da neben dem Binden der Variable f auch gleich die Funktionsapplikation f(p) stattfindet.&lt;br /&gt;&lt;br /&gt;Eric White spricht in seinem &lt;a href="http://blogs.msdn.com/ericwhite/pages/Lambda-Expressions.aspx"&gt;Blogeintrag&lt;/a&gt;, abhängig von jeweiligen Kontext, von einem 'becomes' oder 'such that'.&lt;br /&gt;&lt;br /&gt;Für das oben genannte Beispiel finde ich &lt;strong&gt;p goes to f becomes f(p) &lt;/strong&gt;das Beste, weil der Lambda-Ausdruck in folgenden Schritten evaluiert wird:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;'p =&gt; f' oder 'p goes to f', da nach dem Einsetzen der Variable p eine anonyme Methode resultiert welche p bindet und f als Parameter hat. In dem Sinne geht also p zu f, oder eben 'p goes to f'.&lt;/li&gt;&lt;li&gt;'f =&gt; f(p)' oder 'f becomes f(p)', da nach dem Einsetzen von f die Funktion f(p) ausgeführt wird. In dem Sinne wird als f in f(p) umgewandelt, was auf Englisch dann auch als 'f becomes f(p)' ausgesprochen werden kann.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Ich werde also in Zukunft das letzte '=&gt;' als 'becomes' und alle vorangehenden '=&gt;' als 'goes to' aussprechen. &lt;/p&gt;&lt;p&gt;Beispiele:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;'a =&gt; b =&gt; a+b' &lt;/strong&gt;ist 'a goes to b and becomes a+b'&lt;/li&gt;&lt;li&gt;&lt;strong&gt;'a =&gt; 1 + a' &lt;/strong&gt;ist 'a becomes 1+a'&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8995878145266667696-237395369717784892?l=enceradeira.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://enceradeira.blogspot.com/feeds/237395369717784892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8995878145266667696&amp;postID=237395369717784892' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/237395369717784892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8995878145266667696/posts/default/237395369717784892'/><link rel='alternate' type='text/html' href='http://enceradeira.blogspot.com/2007/05/p-geht-zu-f.html' title='p geht zu f'/><author><name>Jörg Jenni</name><uri>http://www.blogger.com/profile/13667749012132495375</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://1.bp.blogspot.com/_hcGoxuElMbw/SWDb2_yfQ0I/AAAAAAAAADk/wfbkpCUzz0I/S220/Foto+fuer+Bewerbung.jpg'/></author><thr:total>0</thr:total></entry></feed>
