Bugfree.dk – Ronnie Holm's blog

Not anti-anything, just pro-quality

SharePoint list access using the Repository pattern

Posted by Ronnie on January 18th, 2010

This post is part of a series (download code here)

  1. SharePoint list definition using the Template pattern
  2. SharePoint list access using the Repository pattern
  3. Building and deploying SharePoint solutions with MSBuild (to come)

Maybe it’s that the SharePoint API is hard to use. Maybe it’s that coding against SharePoint is about making smaller additions here and there. Maybe it’s that the Patterns & Practices SharePoint Guidance isn’t widely known. Whatever the reason, developing for SharePoint requires equal attention to the separation of presentation, business, and data access code. Hence, starting with data access, we may want to create a repository and route queries through it (the SharePoint Guidance outlines a more sophisticated implementation than the one below):

    [TestClass]
    public class EmployeesRepositoryTest {
        private SPSite _siteCollection;
        private SPWeb _site;
        private EmployeesRepository _repository;

        private readonly Employee _duffyDuck = new Employee {
            Id = 1000, Name = "Duffy Duck", HireDate = new DateTime(2009, 12, 1),
            Remarks = "Looks like a duck, quacks like a duck, probably is a duck"
        };
        private readonly Employee _porkyPig = new Employee {
            Id = 1001, Name = "Porky Pig", HireDate = new DateTime(2010, 2, 1)
        };
        private readonly Employee _sylvesterTheCat = new Employee {
            Id = 1002, Name = "Sylvester the Cat", HireDate = new DateTime(2010, 3, 1)
        };
        private readonly Employee _bugsBunny = new Employee {
            Id = 1100, Name = "Bugs Bunny", HireDate = new DateTime(2010, 1, 1)
        };

        public void AddEmployees() {
            _repository.AddEmployee(_site, _duffyDuck);
            _repository.AddEmployee(_site, _porkyPig);
            _repository.AddEmployee(_site, _sylvesterTheCat);
        }

        public void ClearEmployees() {
            var definition = new EmployeesDefinition();
            var employees = _site.Lists[definition.ListName];
            while (employees.Items.Count > 0)
                employees.Items.Delete(0);
        }

        [TestInitialize]
        public void Initialize() {
            _siteCollection = new SPSite("http://localhost");
            _site = _siteCollection.OpenWeb("/");
            _repository = new EmployeesRepository();
            ClearEmployees();
            AddEmployees();
        }

        [TestCleanup]
        public void Cleanup() {
            _site.Dispose();
            _siteCollection.Dispose();
        }

        [TestMethod]
        public void AddEmployee_should_add_valid_employee() {
            _repository.AddEmployee(_site, _bugsBunny);
            var e = _repository.GetEmployeeById(_site, _bugsBunny.Id);
            Assert.AreEqual(_bugsBunny.Id, e.Id);
            Assert.AreEqual(_bugsBunny.Name, e.Name);
            Assert.AreEqual(_bugsBunny.HireDate, e.HireDate);
            Assert.AreEqual(_bugsBunny.Remarks, e.Remarks);
        }

        [TestMethod]
        public void GetEmployeesHiredBetween_should_return_2010_hires() {
            var from = new DateTime(2010, 1, 1);
            var to = new DateTime(2010, 12, 31);
            var employees = _repository.GetEmployeesHiredBetween(_site, from, to);
            Assert.AreEqual(2, employees.Count);
            Assert.AreEqual(_porkyPig.Id, employees[0].Id);
            Assert.AreEqual(_sylvesterTheCat.Id, employees[1].Id);
        }
    }

In the words of Martin Fowler, here’s the essence of the Repository pattern:

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer.

In SharePoint terms, business logic should query a repository which in turn queries a SharePoint list. Within the repository, the weakly typed items returned are then mapped to strongly typed data transfer objects, which are returned to the business layer.

With this approach to data access comes a number of advantages: (1) duplicate data access code is eliminated. Only within the repository do we setup the query and transform the weakly typed SPListItemCollection into strongly typed data transfer objects. (2) The list definition classes introduced in SharePoint list definition using the Template pattern may be used to construct CAML queries from strongly typed field names. Lastly, (3) accessing data through a repository makes it easier to mock the data access part of the application and to integration test that part.

The code below is a simple, yet usable, implementation of the Repository pattern. The idea is to have all repositories inherit from a common base class. Its purpose is to wrap the querying of a list and to log what’s going on. Because it’s a base class, it shouldn’t know how to transform the weakly typed result into strongly data transfer objects or which CRUD operations a particular repository supports:

    public abstract class ListRepository {
        protected ListDefinition Definition { get; set; }
        protected SPListItemCollection Result { get; set; }

        protected void Query(SPWeb site, string caml) {
            AssertValidSite(site);
            AssertValidCaml(caml);
            AssertListExistence(site);
            AssertListDefinitionSetBySubclass();

            var watch = new Stopwatch();
            var list = site.Lists[Definition.ListName];
            var query = new SPQuery {Query = caml};
            Debug.WriteLine(
                string.Format("About to run query against list '{0}': {1}", list, caml));
            watch.Start();
            Result = list.GetItems(query);
            watch.Stop();
            Debug.WriteLine(
                string.Format("Query against '{0}' returned {1} rows in {2} ms",
                              list, Result.Count, watch.ElapsedMilliseconds));
        }

        protected void AssertListExistence(SPWeb site) {
            if (!ListDefinition.ListExists(site, Definition.ListName))
                throw new ArgumentException(
                    string.Format("No '{0}' list on site '{1}'", Definition.ListName, site.Url));
        }

        protected void AssertListDefinitionSetBySubclass() {
            if (Definition == null)
                throw new NullReferenceException(
                    string.Format(
                        "Sublcass must set Definition property prior querying '{0}' list",
                        Definition.ListName));
        }

        protected void AssertValidCaml(string query) {
            if (string.IsNullOrEmpty(query))
                throw new NullReferenceException("Query must not be null or empty");
        }

        protected void AssertValidSite(SPWeb site) {
            if (site == null)
                throw new NullReferenceException("Site must not be null");
        }
    }

Each ListRepository connects to a corresponding ListDefinition, holding the name of the list to query and its strongly typed field names. It’s the responsibility of a concrete repository to set the Definition property prior to doing any querying. After running a query, the Result property holds the weakly typed result, which a concrete repository can then transform into data transfer objects to be passed to the business layer.

As an example, add to the concrete EmployeeRepository any CRUD method you see necessary to fulfill the business requirements:

    public class EmployeesRepository : ListRepository {
        public EmployeesRepository() {
            Definition = new EmployeesDefinition();
        }

        public void AddEmployee(SPWeb site, Employee e) {
            var list = site.Lists[Definition.ListName];
            var item = list.Items.Add();
            item[EmployeesDefinition.EmployeeId] = e.Id;
            item[EmployeesDefinition.Name] = e.Name;
            item[EmployeesDefinition.HireDate] = e.HireDate;
            item[EmployeesDefinition.Remarks] = e.Remarks;
            item.Update();
        }

        public Employee GetEmployeeById(SPWeb site, int id) {
            var caml =
                string.Format(@"
                      <Where>
                        <Eq>
                          <FieldRef Name=""{0}"" />
                          <Value Type=""Integer"">{1}</Value>
                        </Eq>
                      </Where>",
                    EmployeesDefinition.EmployeeId, id);
            Query(site, caml);

            IList<Employee> employees = Map(Result);
            if (employees.Count == 0)
                throw new ArgumentException(string.Format("No employee with id = {0} exists", id));
            return employees[0];
        }

        public ReadOnlyCollection<Employee> GetEmployeesHiredBetween(SPWeb site, DateTime from, DateTime to) {
            var caml =
                string.Format(@"
                      <Where>
                        <And>
                            <Geq>
                              <FieldRef Name=""{0}"" />
                              <Value IncludeTimeValue=""TRUE"" Type=""DateTime"">{1}</Value>
                            </Geq>
                            <Leq>
                              <FieldRef Name=""{0}"" />
                              <Value IncludeTimeValue=""TRUE"" Type=""DateTime"">{2}</Value>
                            </Leq>
                        </And>
                      </Where>",
                    EmployeesDefinition.HireDate,
                    SPUtility.CreateISO8601DateTimeFromSystemDateTime(from),
                    SPUtility.CreateISO8601DateTimeFromSystemDateTime(to));
            Query(site, caml);
            return new ReadOnlyCollection<Employee>(Map(Result));
        }

        protected IList<Employee> Map(SPListItemCollection items) {
            var employees = new List<Employee>();
            foreach (SPItem item in items) {
                var e = new Employee {
                                Id = (int)item[EmployeesDefinition.EmployeeId],
                                Name = (string)item[EmployeesDefinition.Name],
                                HireDate = (DateTime)item[EmployeesDefinition.HireDate],
                                Remarks = (string)item[EmployeesDefinition.Remarks]
                            };
                employees.Add(e);
            }
            return employees;
        }
    }

Calling the GetEmployeeById or GetEmployeesHiredBetween methods, the caller is required to pass in an SPWeb instance pointing to the the site holding the list to query. Outside the SharePoint context, you have to manually create this instance, like with the integration tests above. But within the SharePoint context, callers are likely to just pass in SPContext.Current.Web.

The above repository implementation deliberately ignores any issue of caching. If you find the need for it, however, you can replace SPList.GetItem with PortalSiteMapProvider.GetCachedListItemsByQuery. The advantage of using the PortalSiteMapProvider over Asp.Net caching of the result is that the provider takes care of invalidating cache entries when items are modified. The disadvantage is that the provider is part of the SharePoint publishing API, which isn’t part of WSS 3.0. In addition, it’s only available from code running within SharePoint, and likely requires cache settings to be tweaked.

      Another, non-trivial, improvement would include the use of the Unit of Work pattern. A commonly used pattern in ORMs because it offers a way to “keep track of everything you do during a business transaction that can affect the database. When you’re done, it figures out everything that needs to be done to alter the database as a result of your work". Like with the DataContext class in LINQ to SQL or the DataSet class in ADO.NET, it could add transaction support to SharePoint lists.

      • Share/Bookmark

      Tags: , ,
      Posted in .Net, SharePoint | 1 Comment »

      SharePoint list definition using the Template pattern

      Posted by Ronnie on January 11th, 2010

      This post is part of a series (download code here)

      1. SharePoint list definition using the Template pattern
      2. SharePoint list access using the Repository pattern
      3. Building and deploying SharePoint solutions with MSBuild (to come)

      Books on SharePoint often show how to create lists from code by calling the SharePoint API from directly within a feature receiver. This receiver would then contain in-place string literals for column names, create the columns, update the default view, and so on. While such an approach provides for an nice demonstration of the SharePoint API, it tends to carry over into production code.

      My take on feature receivers, however, is that they should contain the least possible amount of code. Staying true to object-orientation and separation of concerns, list definition and creation should instead consist of a common set of classes and methods to be called from the receiver:

          public override void FeatureActivated(SPFeatureReceiverProperties p) {
              using (var site = p.Feature.Parent as SPWeb) {
                  var employees = new EmployeesDefinition();
                  if (!ListDefinition.ListExists(site, employees.ListName))
                      employees.CreateOnSite(site);
              }
          }
      

      The first area to improve on is that of string literal field names getting duplicated across the code base. String literals make it impossible for the compiler to enforce a consistent naming of columns. As column names are used in defining the list, in forming CAML queries against it, and in accessing the result, misspelled column names is a common source of runtime errors. The second area to improve on is that of duplication of code for doing common list operations, like checking for the existence of the list or removing its title column. Lastly, we want to get rid of duplicate control logic, i.e., verifying preconditions and calling the same series of methods with every list definition.

      One approach to improving on these areas is to start by defining a base class for list definitions. The base class combines helper methods, working on lists, with the Template pattern for defining the common steps of list creation:

          public abstract class ListDefinition {
              public string ListName;
              public string ListDescription;
              protected SPList List;
      
              public void CreateOnSite(SPWeb site) {
                  if (string.IsNullOrEmpty(ListName))
                      throw new ArgumentException("Expected not null or not empty list name member");
                  if (site == null) throw new NullReferenceException("Expected valid site");
                  CreateList(site);
                  if (List == null) throw new NullReferenceException("Expected list member not null");
                  CreateFields(List);
                  UpdateDefaultView(List);
                  SetAdditionalProperties(List);
              }
      
              protected abstract void CreateList(SPWeb site);
              protected virtual void CreateFields(SPList l) {}
              protected virtual void UpdateDefaultView(SPList l) {}
              protected virtual void SetAdditionalProperties(SPList l) {}
      
              public static void HideAndMakeTitleFieldNotRequiredOnItemNewAndEditPage(SPList l) {
                  var title = l.Fields.GetField("Title");
                  title.Required = false;
                  title.Hidden = true;
                  title.Update();
              }
      
              public static bool ListExists(SPWeb site, string listName) {
                  if (string.IsNullOrEmpty(listName))
                      throw new ArgumentException("ListNameMustNotBeNullOrEmpty", listName);
                  SPList list = null;
                  try {
                      list = site.Lists[listName];
                  }
                  catch (ArgumentException) {
                      // list not found
                  }
                  return list != null ? true : false;
              }
          }
      

      At the core of the Template pattern is the template method. It defines the steps of an algorithm through a series of method calls. Each either abstract or virtual depending on if the step is mandatory or voluntary in the algorithm. Subclasses then specify the behavior of individual steps by implementing or overriding methods. In case of the ListDefinition class, CreateOnSite is our template method. It ensures that context, in the form of an SPList instance, is passed along to each step in the algorithm.

      Each subclass defines the specific characteristics of a list. It defines constants for column names and their data types, the views and which column to index, and so on. This makes for a concise, easy to read, and consistent list definition:

          public class EmployeesDefinition : ListDefinition {
              public const string EmployeeId = "EmployeeId";
              public const string Name = "Name";
              public const string HireDate = "HireDate";
              public const string Remarks = "Remarks";
      
              public EmployeesDefinition() {
                  ListName = "AcmeEmployees";
                  ListDescription = "Employees at Acme Corp.";
              }
      
              protected override void CreateList(SPWeb site) {
                  var guid = site.Lists.Add(ListName, ListDescription, SPListTemplateType.GenericList);
                  List = site.Lists[guid];
              }
      
              protected override void CreateFields(SPList l) {
                  l.Fields.Add(EmployeeId, SPFieldType.Integer, true);
                  l.Fields.Add(Name, SPFieldType.Text, true);
                  l.Fields.Add(HireDate, SPFieldType.DateTime, true);
                  var remarks = (SPFieldMultiLineText) l.Fields[l.Fields.Add(Remarks, SPFieldType.Note, false)];
                  remarks.RichText = true;
                  remarks.RichTextMode = SPRichTextMode.FullHtml;
                  remarks.Update();
                  l.Update();
              }
      
              protected override void UpdateDefaultView(SPList l) {
                  var v = l.DefaultView;
                  v.ViewFields.Delete("LinkTitle");
                  v.ViewFields.Add(EmployeeId);
                  v.ViewFields.Add(Name);
                  v.ViewFields.Add(HireDate);
                  v.ViewFields.Add(Remarks);
                  v.Update();
              }
      
              protected override void SetAdditionalProperties(SPList l) {
                  HideAndMakeTitleFieldNotRequiredOnItemNewAndEditPage(l);
                  l.Fields[HireDate].Indexed = true;
                  l.Update();
              }
          }
      

      Since the string literals have now become public constants, we get IntelliSense and compile-time checking referencing them. In addition, by defining common operations on the base class and using the Template pattern, we reduce the amount of code that would otherwise have to go into each definition. Finally, the base class asserts, on behalf of all subclasses, that the list name is set before attempting to create the list and that the SPList field is set after calling the CreateList method.

      • Share/Bookmark

      Tags: , ,
      Posted in .Net, SharePoint | 1 Comment »

      Planning for 2010

      Posted by Ronnie on January 4th, 2010

      In my previous post I looked at 2009 in hindsight. Consequently, in this one I look ahead at 2010 and what I want to accomplish professionally this coming year. I don’t plan on anything too esoteric. Instead, I want to consolidate my skills around building web applications with C#.

      My goals for the coming year are:

      • Focus more on architecture and design. Not in the architecture astronaut connotation. But as in becoming more aware of how to build better software. I want to apply the SOLID principles more consciously and re-read classics such as Design Patterns: Elements of Reusable Object-Oriented Software and Patterns of Enterprise Application Architecture.
      • Continue exploring LINQ. It’s a fascinating technology that’s going to get only more popular in years to come. Truly understanding LINQ is a way to getting into the habit of applying the more functional and succinct style to my own code. To get started on this endeavor I’m going to read and apply LINQ in Action.
      • Learn Entity Framework. Using an object-relational mapper should be second-nature to most developers. In the past the light-weight LINQ2SQL has served me well. Still, I want to step up and learn how Entity Framework deals with the impendence mismatch. I want to write an application that uses Entity Framework.
      • Become better at browser technologies. JavaScript and jQuery are high on the list, but I want to improve on HTML and CSS as well. My goal isn’t to become an HTML or CSS Jedi. I simply want to have enough knowledge to avoid making rookie mistakes. The technologies all come together in jQuery, making Learning jQuery a good starting point. Besides, I want to use a tool like Firebug to learn from others.
      • Be on top of SharePoint 2010. SharePoint 2007 and 2010 is what I want to work with daily. That doesn’t imply me not keeping up to speed with the rest of .Net. Just that SharePoint will act as my gateway to other technologies. The great thing about SharePoint is that work is frequently divided between working inside and outside SharePoint, integrating with external systems.
      • Become more involved in higher-level development decisions. By the end of the day, developers don’t deliver software, they deliver value to stakeholders. Writing code is but a means to that end. I want to be involved from idea to completion.

      To me these points strike a good balance between technical and non-technical goals and between short and long term goals. However, by the end of the day, building great software is about being attentive to the entire stack and its surroundings.

      • Share/Bookmark

      Tags:
      Posted in Uncategorized | No Comments »

      2009 in retrospect

      Posted by Ronnie on December 28th, 2009

      As 2009 is drawing to a close, it’s time to look back and see what I’ve accomplished this past year. My professional goals for 2009 were to work on challenging software development tasks, preferably on larger projects. I wanted to continue to grow my skills working with .Net in general and SharePoint in particular. In addition, I wanted to be more involved with higher-level development decisions, such as requirements gathering and solution design.

      So how did the year go?

      • Changed jobs to one that gravitates more around larger projects. The rationale being that larger projects come with larger engineering challenges. I spend six months on an Asp.Net project followed by three on a SharePoint project. For various reasons, I wasn’t as involved in higher-level development decisions as I would’ve liked to.
      • Did two presentations. One on Unit testing and mocking for the Asp.Net project that I was working on at the time. The other presentation was on Parallel page rendering with Asp.Net and SharePoint for my current project. None involving rocket science, but I find so few are familiar with the techniques.
      • Made my way through three certifications. The 70-536: MS .NET Framework, Application Development Foundation, 70-562: MS .NET Framework 3.5, ASP.NET Application Development, and Prince2 Foundation. I’ve mixed feelings with regard to certifications, though. Certainly, I learned valuable lessons studying for each one. Yet, given the same amount of time, I’m inclined to think I would’ve learned more studying books, blogs, listening to various podcasts, and writing.
      • Attended the Jaoo conference on software engineering. It was my first time ever attending a conference and it sure was enlightening. I intentionally went for a conference not tied to a specific vendor because I felt I’d learn more that way. My issue with Microsoft conferences like Tech-Ed or PDC is their focus on the latest technology buzz. Buzz that quickly becomes obsolete or is already heavily exposed on the web. Not to mention that most sessions are available online afterward.
      • Learned functional programming. My focus on new technology has mostly been on various aspects of functional programming. A subject that’s interested me for years, but one that’s only recently started to permeate C#, my language of choice. I learned a great deal about F# when I generated fractal terrains and about XSL when I had to jump through functional loops and about functional programming in general.
      • Wrote 16 blog posts (25 pages, 10,000 words). Compared to previous years it’s a record. Naturally, not all posts were equally good. Nevertheless I enjoyed learning about the subjects and feel they helped advance my writing skills. The posts on Basic unit testing guidelines and Why not to comment code did manage to gain traction on Reddit, though.

      All things considered, I’m pleased with 2009. The only thing I regret is not being more involved in higher-level development decisions. I like coding, but it’s a means to an end. Being involved with a task from start to finish is what ignites my fire. I must push harder on that in 2010.

      • Share/Bookmark

      Tags:
      Posted in Uncategorized | 1 Comment »

      Printing iframe content using JavaScript

      Posted by Ronnie on December 17th, 2009

      JavaScript is on top of the list of things I’d like to become better at. So I was quite happy when assigned a JavaScript-related defect in an application at work. Apparently, there was a bug in the JavaScript routine used for printing only the content of an iframe on a page. Rather than printing only the iframe’s content, it printed the page hosting the iframe, cropping parts of the iframe’s content.

      I started out confident that printing would be easy to fix. But after Googling and playing around with JavaScript for a while, frustration, fueled by the number of non-working hits I’d stumbled on, started to grow on me. Suppose you start out with an HTML document hosting an iframe and a few lines of JavaScript.

        <html>
          <head>
            <title>IFrame printing example</title>
            <script type="text/javascript">
              function myPrint() {
                var browser = navigator.appName;
                if (browser == "Microsoft Internet Explorer") {
                  window.frames["frame"].focus();
                  window.frames.print();
                }
                else if (browser == "Netscape")
                  alert("Printing not supported in Firefox");
              }
            </script>
          </head>
          <body>
            <iframe id="frame" name="frame" width="100"
                    height="100" src="http://google.com">
            </iframe>
            <a href="#" onclick="javascript:myPrint();">Print</a>
          </body>
        </html>

      A number of issues arise when printing the iframe. First you need to consider if you’re always hosting the main document on the same domain as the iframe’s source. If so, printing only the iframe with Internet Explorer works like a charm. If, on the other hand, the main document and the iframe’s source reside on different domains, it triggers Internet Explorer to displays a bar across the top of the window.

      Now, to print the iframe’s content, you must allow blocked content. Only then can JavaScript access the iframe’s object model. But at the same time, you make yourself vulnerable to cross-site scripting attacks.

      As far as Firefox support goes, you can issue the same API calls as for Internet Explorer. But Firefox will always print the main page, including only the visible parts of the iframe. To my knowledge there’s no way to make Firefox print the iframe’s content as seamlessly as Internet Explorer. One workaround, though, would be to open a new window, grab a reference to the iframe element, and move its contents to the new window before printing it. For cross-domain content, however, Firefox responds with a “permission denied” error when accessing the iframe element. And there’s no option to allow blocked content. Another workaround may therefore be to use Ajax to retrieve the source of the iframe for any domain and insert it into the new window. That, however, wouldn’t work in my case since the iframe may contain a form that the user may have started filling out before hitting print.

      As a last resort, I considered writing a proxy to retrieve cross-domain hosted content. This would make Internet Explorer never display the bar and allow Firefox to always open a new window with the iframe’s content loaded, even if the user started filling out a form first. But this approach sort of defies the purpose of the browser bar and the permission denied error. Unless you absolutely trust your iframe’s source, you’re exposing your users without their consent.

      In the end I went with the simplest and most secure solution of not supporting printing at all.

      • Share/Bookmark

      Tags: , ,
      Posted in Uncategorized | 2 Comments »

      Parallel page processing with Asp.Net

      Posted by Ronnie on November 26th, 2009

      (This post grew out of a presentation I did on the subject. Turn to the slides for more details, including code.)

      With Asp.Net, by default a page is rendered synchronously, one control at a time. The thread rendering the page comes from the thread pool within the world wide web worker process (w3wp.exe) and is assigned to the request when it comes in on the web server. Only when the page has fully rendered can the thread go back in the pool waiting for the next request.

      Processing a complex page using only one thread, however, may cause the page to render slowly. The page may hold controls that require calls to web services, databases, or other external resources for it to render. Whenever the worker thread encounters such a control, it goes idle waiting for data to come back from the external resource. Only when data is received can the worker thread resume processing.

      One way to speed up page processing would be for the page or control to explicitly make use of threads. Depending on the situation, this may be a cumbersome task that requires a significant amount of boiler-plate code. A simpler approach might be to turn to the Asp.Net 2.0 feature for asynchronous page processing. At its core is an extension to the page or control lifecycle.


      Except for the Begin and End events, the flow is the same in both models. But while the synchronous model executes all code on a single thread, the asynchronous model makes implicit use of multiple worker threads to speed up page processing. With multiple threads, some threads still go idle waiting for input, but at least the main worker thread continues to work its way through the controls.

      In the asynchronous model, we hook into the Begin and End handlers in one of the events preceding the call to Begin. Following PreRender, Asp.Net will then execute our Begin handler, where we call out to some method that carries out the long-running task. When that method exists the End handler is called and processing carries on as in the synchronous model.

      To illustrate the flow and timing of the asynchronous model (turn to the slides for the complete code sample), suppose we add five controls to a page. Each control takes five seconds to render so using the synchronous model the page would take 25 seconds to render. Using the asynchronous model, and writing out trace information about which thread each method executes on, here’s what happens:

      1: Page_Load: 10            9: DoWork: 8
      2: Page_Load: 10           10: DoWork: 11
      3: Page_Load: 10           11: Render: 11 15:16:13 15:16:18
      4: Page_Load: 10           12: Render: 11 15:16:13 15:16:18
      5: Page_Load: 10           13: Render: 11 15:16:13 15:16:18
      6: DoWork: 4               14: Render: 11 15:16:13 15:16:18
      7: DoWork: 10              15: Render: 11 15:16:13 15:16:19
      8: DoWork: 9

      The user control’s Page_Load and the code making up the Begin handler executes on the main worker thread. But the method carrying out the long-running task, and the code for the End handler, executes in parallel on different worker threads. Finally, after End is called, another worker thread takes over and executes the remaining parts of the control. Now page rendering has decreased from 25 to about five seconds.

      All in all, little effort is required to make more efficient, and implicit, use of the thread pool, thereby decreasing the time required processing a page. Asynchronous page processing should be used judiciously, though. Optimizing away a bottleneck in the processing of a page may well lead to bottlenecks appearing elsewhere, e.g., the number of simultaneous calls made to a web service may be too much for it to handle.

      For more details and examples, turn to Jeff Prosise’s article on Asynchronous Pages in Asp.Net 2.0.

      • Share/Bookmark

      Tags: , ,
      Posted in .Net, SharePoint | 1 Comment »

      Getting organized with Emacs Org-mode

      Posted by Ronnie on November 5th, 2009

      It’s been four months and 350 clocked work-hours since I started using Org-mode for Emacs. I use Org-mode, mixed with some of the Pomodoro principles, to maintain my task lists at work and home.

      In a nutshell Org-mode is a plug-in for Emacs that makes taking notes, maintaining lists, clocking time, and many other tasks more straightforward. The mode works by adding features on top of Emacs for editing plain text files. Features that enrich the interaction with the underlying text buffer by parsing and adding (meta-)information to it.

      With Org-mode you group items into a hierarchical structure. A path to the item to work on is then formed by unfolding items in a way analogous to how you navigate the file system with Explorer.

      To efficiently work with items, Org-mode supports moving items around the hierarchy. Items may also be tagged (buy, work, phone, etc.) or associated with a state (done, waiting, started, etc.). Additional meta-information may include a deadline, an estimate, or time spent working on a task. The clocking of time is accomplished by Org-mode adding a timestamp to the item. On completion, another timestamp and the elapsed time is calculated and added.

      Below is an example of an expanded and a collapsed item containing clocked times and estimates.

      With a few keystrokes, Org-mode is able to correlate estimates with time spent on an item-by-item basis. This truly short-circuits the estimation feedback cycle. Imagine doing this on a file containing a large hierarchy of items and the transparency it brings.

      If you want to keep track of billable hours, it may make sense to clock all your time using Org-mode and generate timesheets from the clocking information. Especially since the billing context is automatically provided by the item storing the timestamp, and since you’re free to organize the file in any way you see fit. Few other tools manage to compete with the flexibility of a plain text buffer.

      This post only scratches the surface of Org-mode. To get a sense of the possibilities, the manual amounts to 184 pages. However, for a quick introduction I encourage you to watch the Google Tech Talk on Org-mode.

      • Share/Bookmark

      Tags: , , ,
      Posted in Uncategorized | No Comments »

      Jaoo 2009 conference

      Posted by Ronnie on October 12th, 2009

      (My notes from the conference is available here.)

      From Oct 5 to Oct 7, I was fortunate enough to attend the Jaoo 2009 conference on software engineering in Aarhus. It was a great conference with three days of insightful talks. The talks I attended were:

      Monday

      Tuesday

      Wednesday

      As a supplement to the official homepage, the Twitter feed provided a great source of information for attendees to learn about the presentations and reactions. Not being on Twitter meant missing out on half the conference.

      For other reactions, listen to (in Danish) Daniel Frost and Brian Rasmussen discussing day one and two. On day three Daniel interviewed Mads Torgersen of the C# core team.

      • Share/Bookmark

      Tags:
      Posted in Uncategorized | 1 Comment »

      Why not to comment code

      Posted by Ronnie on August 15th, 2009

      Update, Aug 18, 2009: I’m amazed at how much attention this post has received. More than 200 comments on Reddit.

      I was just listening to the Why comments are evil episode of Deep Fried Bytes. The views put forward by the guest, Corey Haines, deeply resonate with me because I believe they’re what every developer should strive for. I’m not advocating that code should be entirely free of comments, but that most comments do more harm than good.

      Below I’ve listed what I consider the main points of view — or pearls of wisdom — from the episode and included my own commentary.

      • It’s important to differentiate between code comments and API documentation. For API documentation, don’t auto-generate. Especially don’t go with tools like GhostDoc. Take the time to document properly. Otherwise, you’re more likely to confuse the developer trying to make sense of your code.
      • Stop focusing on having the computer understand you and start focusing on the person that comes after you, e.g., while there’s some overhead to method calls, unless the profiler tells you otherwise, don’t hesitate to break down a method into as many smaller methods as it takes to make it more approachable.
      • Every time you’re tempted at writing a comment, take the time to think if you can make the code tell its own story, e.g., instead of some branching condition, extract the condition into a method to emphasize the story of why over how.
      • Developers comment to explain a confusing part of their code, rather than take the time to refactor it by extracting a method or naming a variable properly. Inevitably the code gets modified and the comment rots.
      • Parts of a method may be complicated so a comment is added. Saying part of a method is complicated is in itself a sign that it’s doing too much.
      • The prevailing culture among developers is to focus on what it takes to get code working. It’s a battle of short-term vs. long-term maintainability, and short-term almost always comes out as the winner. Writing code, ask yourself if you’re able to immediately understand the code a month from now.

      The opinions put forward in the episode aren’t new. Still, I find them well worth iterating because as developers we tend to not pay enough attention to them.

      While refactoring is probably as old as programming, Martin Fowler’s 1999 Refactoring: Improving the Design of Existing Code turned it mainstream. Others have followed it his footsteps advocating for the larger concept of software craftsmanship. Most notably Uncle Bob, who delivered an excellent talk on the subject at Øredev 2008.

      On a personal note, I once worked at a consulting company where every new employee was handed three books on the first day of employment. One of these was the Refactoring book. The others were the seminal Design Patterns: Elements of Reusable Object-Oriented Software and Writing Effective Use Cases. I think that reveals something important about that company’s culture. Sadly, most companies aren’t that specific on issues of code quality.

      • Share/Bookmark

      Tags: , ,
      Posted in Uncategorized | 7 Comments »

      Becoming aware of and minimizing distractions

      Posted by Ronnie on July 27th, 2009

      Spending a great deal of time in front of my computer, I often get carried away by instant messaging, mail, RSS, Twitter, Facebook, etc. For the most part, these activities aren’t the reason I turned on the computer. Nevertheless they end up being where a lot of time is spent.

      Like with any habit, every so often you should take the time to review it. I find TimeSnapper (the free edition) to be an invaluable tool for reviewing computer habits. It captures an image of the desktop every few seconds and is able to create a movie from the images. That way, a partial life log (mine is currently 393 days) is automatically created to help you remember what you did yesterday and the day before.

      There’s nothing like reviewing a few of weeks of captured images to make habits stand out. I found that I’ve a tendency to re-visit the same maybe ten sites all too often. I also have difficulty single-tasking. Listening to a podcast or watching a movie, I’m often browsing the web instead of paying attention to the podcast or skipping it altogether. I may even have several media players launched at once, although only one playing.

      Most of my distractions can be attributed to me always being online. I need Internet access for work, so turning it off altogether isn’t an alternative. So, not unlike Paul Graham, on several occasions, I’ve made myself adhere to a set of rules for using the Internet. And every time they’ve worked — for a short while.

      In Disconnecting Distraction, Paul takes these rules one step further and argues that using two computers may be a better solution: one computer with Internet access and one without for doing real work. Ideally, the computers should be placed some distance apart to make you psychically get up to go on the Internet.

      For a week I’ve given the two-computer approach a try. It was hard initially, but I’ve come to appreciate it. Forming permanent habits takes time. Thus, I’ll continue the experiment for a couple of weeks. Perhaps in time I’ll even learn to turn off instant messaging and only do mail once or twice a day. Or I may end up spending most of the time in front of the connected computer.

      Then again, there’s more to life than work.

      • Share/Bookmark

      Tags: ,
      Posted in Uncategorized | No Comments »