Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Robert Bogue MS MVP, SharePoint (MOSS) Thor Projects ARC309 Agenda Overview of patterns and practices What are patterns and why use them? Overview of patterns introduced in SharePoint version 1 Refactor Model-View-Presenter Why unit testing? Why is unit testing SharePoint hard? Deeper dive on mocking Questions and answers SharePoint Guidance – Version 1 Design, build, test, deploy and upgrade SharePoint intranet applications http://www.microsoft.com/spg Patterns Factoring and packaging Team-based development App Lifecycle Management Design tradeoffs http://www.codeplex.com/spg Upgrading applications Unit testing Designing for testability Continuous integration Build verification testing What are Design Patterns? A design pattern is a general reusable solution to a commonly occurring problem in software design. A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations. - Wikipedia Why Use Patterns? Design patterns can speed up the development process by providing tested, proven development paradigms. Effective software design requires considering issues that may not become visible until later in the implementation. Reusing design patterns helps to prevent subtle issues that can cause major problems, and it also improves code readability for coders and architects who are familiar with the patterns. - Wikipedia What Do Patterns Cost? In order to achieve flexibility, design patterns usually introduce additional levels of indirection, which in some cases may complicate the resulting designs and hurt application performance. - Wikipedia Patterns Help Frame What to Do… Increase productivity Common problems → common solutions Leverages experience Lower long term costs Easier to test Increases flexibility Easier to maintain Easier to evolve Patterns Applied to SharePoint in Version 1 Guidance View Presenter Model-View-Presenter Model Locates ClassA IServiceA serviceA = ServiceLocator.Get<IServiceA>() Locates Service Locator IServiceB serviceB = ServiceLocator.Get<IServiceB>() Custom Business Logic Repository Service Locator ServiceA Repository ServiceB SharePoint Lists Deep Dive - Model View Presenter Similar to Model View Controller Separation of view from presentation logic Separation of role responsibility View Presenter Model Business entities Services Data Repositories View Markup Logic for conditional formatting Presenter Logic for taking action on events resulting from user gestures and model changes Model Factoring Out View and Presenter Service Locator Motivation Loosely couple service provider and consumer Provides a pluggable implementation Improves test coverage “Poor mans” dependency injection – reduce complexity introduced Tightly Coupled Service Dependencies Uses ClassA ServiceA ServiceA serviceA = new ServiceA() Uses ServiceB serviceB = new ServiceB() ServiceB Service Location Locates ClassA Service Locator ServiceA IServiceA serviceA = ServiceLocator.Get<IServiceA>() Locates ServiceB IServiceB serviceB = ServiceLocator.Get<IServiceB>() Repository Motivation Improves test coverage Better separation of data and business tiers Reduces opportunity for erroneous or poor practices with list access Adding an Item to a List SharePoint API //-- Direct List Data Access ----------------// Adds a new SPListItem directly to the list. SPList list = web.Lists[Lists.Announcements]; SPListItem item = list.Items.Add(); item[Fields.Title] = "Direct List Data Access"; item[Fields.Body] = "Item added using Direct List Data Access."; web.AllowUnsafeUpdates = true; item.Update(); web.AllowUnsafeUpdates = false; id = item.ID; Adding Via AnnouncementRepository //-- AnnoucementRepostitory Data Access ----------// Adds a new Announcement using the AnnouncementRepository. AnnouncementRepository announcementRepository = new AnnouncementRepository(); Announcement announcement = new Announcement() { Title = "AnnouncementRepository Data Access", Body = "Item added using AnnouncementRepository." }; id = announcementRepository.Add(announcement, web); What is Wrong with This Code? SPList bigList = web1.Lists[“BigList”]; foreach(SPListItem item in bigList.Items) { if(item[“MyColumn”] == “Foo”) { Console.WriteLine(“Found One!”); } } Working with SPList SPList.Items gets a collection with ALL list items Terrible for big lists Lots of memory needed Lots of SQL I/O Lots of network Lots of CPU Instead use SPList.GetItems Takes a CAML query Now Using a Repository… //BigList access code refactored using repository BigListRepository bigListRepository = new BigListRepository(); Ilist<BigListItem> bigListItems = bigListRepository.GetByMyColumn(“Foo”); if (bigListItems.Count >0) Console.WriteLine(“Found One!”); RI Architecture - Before IIS Workflow Activities Workflow SharePoint Accounting ASPX Pages Web Parts HR RI Architecture - After ASPX Pages Web Parts IIS Accounting HR Repositories SharePoint Presenters Workflow Controllers Workflow Activities Workflow Where Do Patterns and Practices use Unit Testing? Develop and build Source Control Stand Alone Stand Alone Development Stand Alone Development Environments Development Environments Environments Continuous Integration Server Build and unit test on check-in events Development Owned Automated Build Verification Test Server Validated WSP Automated build and build verification test ran periodically Test Owned How Does Unit Testing Help? Quickly validates code logic executing correctly Rapidly iterate code/test Rapid identification of breaking changes Improved quality and frequency of check-in Avoids the dreaded mondo check-in Builds confidence to re-factor Enables CI What Unit Testing Doesn’t Do: Ensure that code is functionally correct Load or stress test the code (see integration tests) Is This a Unit Test? [TestMethod] [ExpectedException(typeof(SPException), "The Enrollment Deadline Date can not be before today's date.\r\n")] public void AddingCourseWithInvalidEnrollmentDateCancelsWithError() { //Setup our mock so that our enrollment date is invalid TrainingCourse course = new TrainingCourse { Title = "My Title", Code = "12345678", EnrollmentDate = DateTime.Today.AddDays(-1), StartDate = DateTime.Today.AddDays(1), EndDate = DateTime.Today.AddDays(2), Cost = 100 }; using (SPSite site = new SPSite(siteUrl)) { using (SPWeb web = site.AllWebs[webId]) { TrainingCourseRepository repository = new TrainingCourseRepository(); repository.Add(course, web); } } } Background: Unit Testing (Agile Definition) Tests business logic in class/method being examined No SharePoint logic Dependencies isolated and pass in Breaking change affects only a few unit tests Background: Integration Testing (Agile Definition) Evaluates integrated business logic Tests real system behavior Often complex setup/teardown logic Typically no UI Breaking change often affects multiple tests Why is it So Hard to Unit test in SharePoint? What are Substitutes and How Do They Fit? Test Production Code UnderlyingSubstitute Dependencies (For (Mock, Example, Stub, SharePoint) Wrapper) Integration Test Alternatives for Unit Testing With SharePoint? Wrapper/Façade Surround all SharePoint APIs with classes that wrap functionality Wrapper redirects calls under test to a test implementation (Mock or Stub) Generally prohibitively costly to achieve Typemock Isolator Third party tool Uses IL interception SharePoint licensing model is reasonable cost Wouldn’t it Be Nice if… [TestMethod] public void GetsContentFromListAndSetsInView() { //Arrange SPWeb mockWeb = new SPWeb(); mockWeb.Lists.Add(“List Name”, “mock list”, customerListTemplate; SPList mockList = mockWeb.Lists[“List Name”]; SPListItem mockListItem = mockList.Items.Add(); mockListItem[“First Name”] = “testfirstname”; IMyView view = new MockMyView(); //Act MyViewPresenter presenter = new MyViewPresenter(view); presenter.GetContent(); //Assert Assert.AreEqual(1, view.Content.Count); Assert.AreEqual(“testfirstname”, view.Content[0].[“First Name”]); } Unfortunately, can’t construct SPWeb… Bringing Patterns and Unit Testing Together Model-View-Presenter to test web forms Increases unit test surface area for logic that is often in code behind Mock views to test presenter in unit tests Use repositories to encapsulate access to SPList instances (Training Courses, Registrations…) Mock repositories for unit tests Use ServiceLocator to help swap mock services in place of real ones Use Typemock to mock calls to SharePoint API Test logic that is previously not easily unit testable (like event receivers) Resources www.microsoft.com/teched www.microsoft.com/learning Sessions On-Demand & Community Microsoft Certification & Training Resources http://microsoft.com/technet http://microsoft.com/msdn Resources for IT Professionals Resources for Developers www.microsoft.com/learning Microsoft Certification and Training Resources Related Content Patterns and practices SharePoint guidance (http://www.microsoft.com/spg and http://www.codeplex.com/spg) SharePoint Best Practices Center http://technet.microsoft.com/enus/office/sharepointserver/bb736746.aspx SharePoint ALM Resource Center http://msdn.microsoft.com/en-us/office/cc990283.aspx Team Foundation Server Resource Center http://msdn.microsoft.com/en-us/office/cc990283.aspx Complete an evaluation on CommNet and enter to win! © 2009 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.