Only You Can Prevent Crap Code

Over the last few years I have evangelized about writing clean code.  I have read numerous resources, talked to developers, and spent time developing.  I have felt the pain of an ugly system, I have felt the love of beautiful code, and I have brought down pain and misery upon future developers.   Recently, I have reflected on the last eight years of my professional career and I realized why I obsess about clean code.   For me it comes down to respecting other developers and respecting my users.

What the hell are you talking about you ask?  Well, besides thinking that was a mean way to ask a question, I believe writing good code is an obligation and a way to show future developers you respect their time.  We all have spent a lot of time reading code.  Experience shows that reading code can be time consuming and it is typically more difficult than writing new code.  The more complex the code the harder it is to read and understand.  If the code has poor variable names, no encapsulation, high coupling, god classes, misleading or stale comments, hard coded dependencies, custom design patters, and the list goes on then it is going to take a lot longer to understand and modify the code.

It is easy to write bad code and maybe the developer thought they had to do this to meet a tight deadline.  This might sound convincing, however it just cost the next developer over an hour to understand the code before they could even start modifying the code and now they have to cut corners to meet their deadline.  On top of that, their level of confidence in the new code went down and they introduced a new bug.  If that developer doesn’t refactor the code, then the hour they spent figuring it out was wasted.  The next developer will have to spend another hour or more to understand the code.  Seems like a pretty awesome way to develop.  The problem gets worse overtime and inevitably something really bad is going to happen.

If you don’t care about the next developer, which isn’t professional by the way, then care about your users.  Initially, you could argue you wanted to ship new features to the users as quickly as possible.  This sounds great, but at what cost?  Future releases.  As you continue to build and enhance your software it will take longer to ship new features and you will increase the likelihood of defects.  Is this really what you want to give the user?  Of course it is, if you hate your users enough.  The users, PM, or stakeholders might be pushing for code quickly, but it is our responsibility to set expectations.  Writing sloppy code hurts the organization and the user, period.  Fight for good code.

I like to believe that most developers have good intentions and want to write SOLID code (http://en.wikipedia.org/wiki/SOLID_(object-oriented_design).  So why are we stuck with systems that turn out to be evil, gnarly balls of hate? Code decays only if you let it.  Code rot is the guy you invite to the party that you know you shouldn’t because he invites all of his friends from prison.  Before you know it your house turns into a coke den full of dudes with Russian prison tattoos and rap sheets longer than an emo kid’s journal.  This is not a good place to be, trust me.   The bottom line is we have to be professional and write good code.  It is our job to create a system that is clean and maintainable.  Developers are responsible to fight for the health of the code.  We cannot expect PMs, stakeholders, managers, or anyone else to understand the importance and fight for the cause.   If you want to be a hero be like Batman he cleans up the streets of Gotham!  Batman is badass and you can be too.  Aquaman would stay late every day for a month to reach a deadline.  He would cut corners instead of set expectations.  Don’t be Aquaman, he sucks (http://www.youtube.com/watch?v=bBLaRSmqGS8).  Do yourself a favor, be Batman and not Aquaman.

Edit: After reflecting on this article I want to emphasize that no one developer is perfect and we have and probably will write dirty code at some point. I would like to see more developers provide constructive feedback about code to help each other learn and produce great software. After all, as we learn and progress our source should evolve. I believe sharing code is about helping and learning. It shouldn’t be about throwing daggers.

Don't Just Say You're Doing Code Reviews

I keep hearing how wonderful code reviews are to help improve the quality of code.  There is a lot of information about how code reviews can improve code design, reduce defects, and share knowledge.  I have participated in a number of code reviews, and I can definitely say they have the potential to be a powerful tool.  My problem with code reviews is not the concept, but the follow through.

I think it can be really easy to implement a code review process, but ultimately it takes discipline to make the process effective.  Like any good idea it is all about execution.  I believe there is a reason some are seeing true benefits from a code review while others are seeing very little in return.

Below are two lists of responsibilities for both the developer and the reviewer.  Of course this is not a list to end all lists, but it is definitely a sound starting point.  If your team can be disciplined to execute on these responsibilities you should start seeing consistent return from your code reviews.

Responsibilities of the reviewer:

  1. evaluate the code and not the developer
  2. understand the requirements and intent
  3. ask to see the tests
  4. review the design
  5. collaborate to find ways to make the code better
  6. be engaged

Responsibilities of the developer:

  1. Do not take feedback personally and be prepared to collaborate
  2. reduce the size and scope of the review by having frequent reviews
  3. communicate the requirements and intent
  4. being willing to talk about the “what” and the “why” you did something
  5. be willing to make adjustments based on feedback
  6. be engaged

ASP.NET Scalability and Optimization Part 2

In the last post I showed a few ways to reduce bandwidth usage by taking advantage of the Microsoft CDN, ScriptManager, and the AJAX Minifier. In this post I will explain a scalable approach used to better manage session state while scaling with a changing environment.

The Problem

Over the last few months we had seen increased traffic on our servers and higher memory usage. At first, our solution was to vertically improve the existing servers’ hardware, and then horizontally by adding more nodes to our web farm. Initially, this worked; however, it introduced a new set of problems for maintenance and load balancing. It soon became obvious we were out-growing our current design. We knew we needed to find a scalable solution if we wanted a maintenance-friendly and highly available web application.

Our web application contains state data for each user in a session. Each session was stored on the server in-process. This meant the session was not accessible by other instances of the web application running on other servers (or other processes on the same server). This design choice provided a fast performing session state solution, but caused problems with load balancing and maintenance.

For load balancing we sent new requests, requests not tied to an active session, to the node with the least traffic. For existing requests, requests tied to an active session, we sent all subsequent requests to the same node until the session expired. This worked for a while, until we needed to perform maintenance. When we had to bring down a server we needed to prevent new sessions and had to wait for all existing sessions to end (wait for users to log out or the session to timeout) before bringing down a server for maintenance. As you can see this became time consuming as the number of nodes continued to grow.

Why Session State

Originally our design choices were made based on our current demands. We chose a solution that fit our needs and also provided the quickest performance. As our environment changed so did our needs. We believed our design choice for managing session state would fix many of our issues.

We thought that sacrificing some speed by storing session data in a database would payback dividends in reduced memory usage, shared session state, and persisted session data.

Installing the ASPState Database

The first thing to do is setup the database. Fortunately, Microsoft has made this easy by providing the T-SQL DDL and shipping it with ASP.Net. To build the tables start by opening the Visual Studio Command Prompt and use the aspnet_reqsql.exe tool to build the database.

aspnet_regsql.exe  -?

This command displays all of the options available to use with aspnet_reqsql.exe. For this purpose we want to look at the options below.

-ssadd        Install the SQL Server session state.
-sstype p   Use a persisted session state (t: temporary and c: custom).
-S                A connection string to the database server.
-U               SQL Server Login ID
-P               Password
-E               Alternatively, this users Windows Authentication
For additional aspnet_regsql.exe options and details read the article ASP.NET SQL Server Registration Tool (Aspnet_regsql.exe).

I have decided to use the following command to install the ASPState database using SQL Server Authentication.

aspnet_regsql.exe -ssadd -sstype p -S MyServer -L sgmeyer –P *****

Once the installation is complete you can view the tables in the newly created ASPState database. This database contains all of the tables, views, and stored procedures you need.

Configuring the Session State Mode

Next, tell ASP.NET to start storing the state in the new server. Start by opening up the Web.config, and update it with the following configuration.

<system.web>
  <sessionState mode="SQLServer" cookieless="UseCookies"
  sqlConnectionString="Server=MyServer;Database=ASPState;Integrated Security=SSPI"
  compressionEnabled="True" allowCustomSqlDatabase="True" timeout="60"
  sqlCommandTimeout="10" />
</system.web>

Now, spin up your application, and open the ASPState database and you can see the tables are being updated with the session.

A Piece of Advice

When working with SQLServer session mode all objects are serialized and written to the database. When you work with an in-process session, objects are referenced in local memory and are not serialized. If you are converting an existing application or creating a new object to be stored in a persisted session, be sure those objects and the objects they reference are serializable. The compiler does not check if you add a non-serializable object to a persisted session, instead you will receive a runtime exception.

Note that if you subscribe to the Session_End event this will not work with SQLServer mode. The Session_End event will only be fired when using InProc session state, while the Session_Start event will continue to work as expected.

For more information or serialization see the article Object Serialization in the .NET Framework.

Conclusion

Every project has its own priorities and objectives. The .NET Framework offers a rich set of options for managing session state, each with a different set of pros and cons. It is important to understand the benefits of each option before making a decision. There is not a silver bullet solution for every problem. Identify your objective before picking a solution.

ASP.NET Scalability and Optimization Part 1

Lately I have been spending a lot of time optimizing a fairly high traffic .NET web application.  Over the last few months, performance has become a pretty big concern.  Based on current traffic, we are pushing our monthly bandwidth limitations while memory and server load continue to become a growing concern.

Over the course of the next few posts I will talk about what I did to remedy these scalability issues.  As bandwidth was my initial concern, I will start by talking about what I did to decrease bandwidth and some of the concerns I faced.

Where To Start

When optimizing code it can be difficult to know where to start, however taking advantage of good tools can simplify this task.  I used our web metrics tool to find bandwidth and traffic hot spots.  In my case, our website’s metrics are collected through Google Analytics.

When working on a tight deadline it can be a difficult task to weigh bandwidth consumption per visit versus high traffic pages.  In our case we could make significant improvements just about anywhere so I started with the high traffic pages.

Once I found a starting point, I navigated to those pages using FireFox with the YSlow plug-in installed.  I found YSlow to be particularly useful.  If you have not already used YSlow it is a tool that grades your websites performance based on well-defined and accepted criteria (Yahoo! YSlow).  This tool is very well documented so I will not spend a lot of time discussing its merits.

JavaScript Woes and Sorrows… Saved by the ScriptManager

Using YSlow, I found the biggest problems were related to JavaScript.  The biggest bandwidth hog contained inline script as well as fourteen JavaScript files; amongst those were the Microsoft AJAX JavaScript libraries.  The JavaScript footprint had a total weight of 556 KB despite being GZipped.

To setup some of the enhancements, I moved the inline JavaScript into a file.  This may sound counter intuitive now, but as we will see next this will play to our benefit.

My first priority was to decrease the size of the JavaScript files.  If you are not already familiar with minifying it is the process of reducing the size of HTML, CSS, or JavaScript.  There are many free tools available to minify JavaScript.  I chose to use the Microsoft AJAX Minifier.  Using the command below, I was able to minify all of the JavaScript files.  For simplicity’s sake I am running the minifier manually, but it is possible to integrate the tool within Visual Studio 2010 (Using the New Microsoft AJAX Minifier).

ajaxmin -hc scriptName.debug.js -out scriptName.js

This script takes advantage of Hyper Crunching (-hc), which is an aggressive minifying feature provided by the Microsoft AJAX Minifier.  This performs basic file reduction by removing whitespace and unneeded characters.  It also reduces non-global variable names, extra curly braces, dead code, and more.  As a precaution always test the minified JavaScript prior to deploying.

Once my JavaScript files were minified I was already boasting good reduction in JavaScript file size.  Although, with the minified files in place, I still did not see the bandwidth cut I was hoping to achieve.

Reducing Bandwidth By Hosting Files on a CDN

YSlow has a category that grades your usage of a CDN.  Many developers ignore this grade, as hosting content on a CDN used to require a paid service.  Now there are several free CDNs available to use including those provided by Microsoft and Google.

Our application uses the Microsoft AJAX Library’s JavaScript, which is managed by a ScriptManager control.  Since we are hosting the AJAX libraries we spend our own bandwidth to host these files.  Through the use of the ScriptManager we can take advantage of the Microsoft CDN to host the AJAX Libraries.  This technique does not reduce the amount of data downloaded by a user, unless previously cached.  Instead, we are now using Microsoft’s bandwidth to host those files rather than our own.   Hosting on a CDN provides other benefits such as localized content and quicker page loads.

<asp:ScriptManager ID="ScriptManager1" EnableCdn="true" runat="server">
</asp:ScriptManager>

It is important to note that we now have a dependency on Microsoft’s CDN.  If the CDN is not available your AJAX files will also be unavailable.  As unlikely as it may seem it is important to know the risks no matter how marginal they may appear.

Finishing Touches

Now that that we have taken a big bite out of the bandwidth usage; I took one last step to reduce the number of HTTP requests.  As mentioned earlier I had a number of small JavaScript files that I wanted to combine into a single file.  Again, I can rely on ScriptManager to combine these files for me.  As a side note, the ScriptManager is more efficient at combining assembly-based JavaScript when compared to path-based scripts.

<asp:ScriptManager EnableCdn="true">
  <CompositeScript>
    <Scripts>
      <asp:ScriptReference Path="script1.js" />
      <asp:ScriptReference Path="script2.js" />
    </Scripts>
  </CompositeScript>
</asp:ScriptManager>

Be cautious when combining scripts.  This is not a silver bullet.  Combining too many files can be detrimental to page load.  Today’s browsers allow concurrent HTTP requests.  If you combine too many files this could slow down content retrieval since the browser cannot download the content in parallel.  Also, by splitting our content between Microsoft’s CDN and our own servers it allowed the browser to be more efficient when retrieving content.  Typically, browsers can perform parallel requests, however they limit the number of concurrent requests per domain.  By spreading our content across multiple domains the browser was able to download the content more efficiently.  Finding the right balance is definitely something you should experiment with to find the best gains.

As a side note, you can leverage the ScriptManager to combine scripts even if you do not want to host the AJAX Library.  The ScriptManager exposes an enumeration allowing the developer to leverage the benefit of ScriptManager without hosting the AJAX Library.

<asp:ScriptManager AjaxFrameworkMode="Enable|Disable|Explicit"></asp:ScriptManager>

More details can be found here and here.

Conclusion

When used properly minifying, script combining, and CDN hosting can be good ways to improve user experience and improve performance.  Microsoft has provided many of the tools you need to employ these techniques and observe these benefits immediately.  With any good tool it is possible to misuse it.  I recommend experimenting with these techniques to find the best implementation for your web application.