<CharlieDigital/> Programming, Politics, and uhh…pineapples

31Aug/09Off

Misc. Adventures

Posted by Charles Chen

Just some random photos to unload from the camera.


We recently saw this little guy scouring our Mums for prey:



Spent the weekend in Tennessee. Stopped by a BBQ/country music festival in Nashville. Got myself some Bayou Billy's homebrew soda. Love their tagline: "Put Some South In Your Mouth":


You're supposed to keep the mug for lifetime $1 refills. Sandra particularly liked how I carried mine around:


Spent Sunday at Cheekwood Botanical Gardens just outside of Nashville. Amazing place; a shame that I didn't have a better camera, lens, and -- well -- skill to capture it all.














The main mansion was beautiful as well, however, photography wasn't allowed.  The backstory is that it was once owned by one of the early investors in Maxwell House Coffee (The Cheek family).  There's a whole section of the garden, the sculpture trail, that we didn't do...maybe next time.  Also, there's supposed to be a Dale Chihuly exhibit next year if you're planning on making a trip to Tennessee!


If you're ever in Tennessee, don't pass up the chance to stop by Cheekwood.  Bring some comfortable hiking/walking shoes, a bottle of water, a nice camera, and some time.  Oh, and finally: where did this guy come from?


Filed under: Life, Miscellany No Comments
29Aug/09Off

SharePoint Design Patterns: Entry 2

Posted by Charles Chen

In the previous entry, we explored how to clean up our interaction with instances of SPSite, SPWeb, and SPList objects. Logically, the next scenario that we'd want to cover is working with the SPListItem that we get back from the list.

What does this look like? Usually something like this (we'll use some sample code from our last entry):

public string GetLastModifiedBy(int id) {
    string lastModifiedBy;
 
    using(ProposalsLibrary library = new ProposalsLibrary()) {
        SPListItem item = ...; // Get the instance
        lastModifiedBy = Convert.ToString(item["Modified_x0020_By"]);
    }
    return lastModifiedBy;
}

By itself, this seems innocent enough, but the problem lies in the fact that it's rarely so easy as returning simply one field value. Even if that were the case, the issue remains that these field name strings leak out across the codebase. Again, this is typically mitigated through the use of Constants or configuration settings, but it's still messy code, IMO. Aside from that, it can be difficult to figure out which fields are valid for which lists. In general, it makes it hard for developers to figure out how to work with the existing code without good documentation.

Enter the Decorator pattern. The intent of Decorator, as described in Design Patterns, is as follows:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality.

Basically, what we'd like to do is to make working with SPListItems more intuitive and more domain specific. Since we can't subclass SPListItem (and even if we could I don't think it would make sense to do so since it would also expose all of the properties and operations on the SPListItem), we'll have to leverage the simplified version of the Decorator pattern to help us instead. Here is an example:

using System;
using Microsoft.SharePoint;
 

namespace SharePointExample
{
    /// <summary>
    /// Models a sales proposal.
    /// </summary>
    public class Proposal
    {
        private SPListItem _managedItem;
        private string _title;
        private string _lastModifiedBy;
        private bool _checkedOut;
        private string _checkedOutUserLoginName;
        private string _checkedOutUserDisplayName;
        private string _status;
        private string _customerName;

        /// <summary>
        /// Gets the title.
        /// </summary>
        /// <value>The title.</value>
        public string Title
        {
            get { return _title; }
        }

        /// <summary>
        /// Gets the login name of the check out user.
        /// </summary>
        /// <remarks>
        /// Null or empty if not checked out.
        /// </remarks>
        /// <value>The login name of the checkout user.</value>
        public string CheckedOutUserLoginName
        {
            get { return _checkedOutUserLoginName; }
        }

        // Other properties omitted...

        /// <summary>
        /// Private constructor; use the <see cref="FromSPListItem"/>
        /// call to create an instance.
        /// </summary>
        private Proposal() { }

        /// <summary>
        /// Creates an instance from a SharePoint list item.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns>An instance of <c>Proposal</c>.</returns>
        public static Proposal FromSPListItem(SPListItem item)
        {
            Proposal proposal = new Proposal();

            proposal._title = Convert.ToString(item["Title"]);
            proposal._checkedOut = (item["CheckoutUser"] != null
                && item.File.CheckOutStatus != SPFile.SPCheckOutStatus.None);

            if (proposal._checkedOut) {
                string fieldValue = Convert.ToString(item["CheckoutUser"]);

                // NOTE: item.Fields requires the display name.
                SPFieldUserValue checkoutUser = (SPFieldUserValue)
                    item.Fields["Checked Out To"].GetFieldValue(fieldValue);

                proposal._checkedOutUserLoginName = checkoutUser.User.LoginName;
                proposal._checkedOutUserDisplayName = checkoutUser.User.Name;
            }

            // Set other fields here...

            proposal._managedItem = item;

            return proposal;
        }
    }
}

If nothing else, we now have a clean, domain specific way to access the SharePoint list item. Team members and new developers don't have to guess which fields are valid for this items retrieved from this list; it would be hidden from them by the properties on the Proposal class instead. If you look at the code to determine the check-out user, you can see that we now also have a single location to encapsulate this parsing logic and any associated error handling we may want to add; other developers don't need to duplicate this code when they use the list item.

It's debatable whether you should use a constructor to initialize the instance, some sort of implicit conversion operation, or a static method like I've used here. I would rule out an implicit conversion operator since it may be hard for users to understand at first blush (i.e. XName and string). As for a "natural" constructor that takes the SPListItem instance? While it's slightly more discoverable (XDocument.Parse() is pretty hard to find for new users), I feel like that's a bit misleading and the intent isn't clear, however, YMMV. Another possible improvement is to pull the abstraction up yet another level since many of the fields are common (like title and last modified by); this exercise is left to the reader ;-).

If we go back to our first example, we can now write this as:

public string GetLastModifiedBy(int id) {
    string lastModifiedBy;
 

    using(ProposalsLibrary library = new ProposalsLibrary()) {
        SPListItem item = ...; // Get the instance

        lastModifiedBy = Proposal.FromSPListItem(item).LastModifiedBy;
    }

    return lastModifiedBy;
}

That's pretty cool. While this example is intentionally simple, you now have a nice object oriented way of working the the fields. In addition, you have a very logical place to put all of your domain specific operations on specific list item types (or should that be content types?). For example, it may make perfect sense to add a method here called CompressAndEmail(string recipientEmailAddress) which would compress the file contents of the proposal and email it to the specified recipient.

Admittedly, this still isn't ideal since 1) we still have to deal with SPListItem on some level ("leakage", if you will) and 2) what about the other side of this equation: updating the item? With regards to (1), we can simply hide this by adding a method to the ProposalsLibrary class as discussed in the previous entry:

using Microsoft.SharePoint;
 

namespace SharePointExample
{
    /// <summary>
    /// Concrete implementation of <see cref="Library"/>
    /// </summary>
    public class ProposalsLibrary : Library
    {
        protected override string ListName
        {
            get { return "<listNameHere>"; }
        }

        protected override string WebName
        {
            get { return "<webNameHere>"; }
        }

        /// <summary>
        /// Finds and instance of <see cref="Proposal"/> the by ID.
        /// </summary>
        /// <param name="id">The ID.</param>
        /// <returns>An instance of <see cref="Proposal"/>.</returns>
        public Proposal FindById(int id)
        {
            SPListItem item = ...; // Find the list item

            return Proposal.FromSPListItem(item);
        }
    }
}

Now our method looks like this instead:

public string GetLastModifiedBy(int id) {
    string lastModifiedBy;
 

    using(ProposalsLibrary library = new ProposalsLibrary()) {
        Proposal proposal = library.FindById(id);

       lastModifiedBy = proposal.LastModifiedBy;
    }

    return lastModifiedBy;
}

That's pretty awesome since it means that we can now remove all references to and knowledge of SharePoint from a whole layer of our application code.

Now onto point (2). For a moment, let's say our proposals have properties called "Status" and "CustomerName". From time to time, we may want to update these (from a source other than the web form, like through a custom web service call or if we have a batch process that runs on our SharePoint environment). One way we can handle this is by implementing the set operation on the properties which can be updated and a Save() method:

using System;
using Microsoft.SharePoint;
 

namespace SharePointExample
{
    /// <summary>
    /// Models a sales proposal.
    /// </summary>
    public class Proposal
    {
        private SPListItem _managedItem;
        private string _title;
        private string _lastModifiedBy;
        private bool _checkedOut;
        private string _checkedOutUserLoginName;
        private string _checkedOutUserDisplayName;
        private string _status;
        private string _customerName;

        /// <summary>
        /// Gets or sets the status.
        /// </summary>
        /// <value>The status.</value>
        public string Status
        {
            get { return _status; }
            set { _status = value; }
        }

        /// <summary>
        /// Gets or sets the name of the customer.
        /// </summary>
        /// <value>The name of the customer.</value>
        public string CustomerName
        {
            get { return _customerName; }
            set { _customerName = value; }
        }

        // Other properties omitted...

        /// <summary>
        /// Private constructor; use the <see cref="FromSPListItem"/>
        /// call to create an instance.
        /// </summary>
        private Proposal() { }

        /// <summary>
        /// Saves this instance back to SharePoint.
        /// </summary>
        public void Save()
        {
            // Error checking first; i.e check if user has item checked out

            // Save
            _managedItem["Customer_x0020_Name"] = CustomerName;
            _managedItem["Status"] = Status;
            _managedItem.SystemUpdate(false);
        }

        /// <summary>
        /// Creates an instance from a SharePoint list item.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns>An instance of <c>Proposal</c>.</returns>
        public static Proposal FromSPListItem(SPListItem item)
        {
            // Same as before; omitted
        }
    }
}

Nice. In doing this, we've basically hidden most knowledge of the SharePoint list item from the users of our object and framework. Downstream developers only need to know about the domain specific objects. It's now far easier for a member of our team or a new developer to reuse this code and it cuts down on error prone duplication and leakage of field names across our codebase. We also now have a nice place to put field validation logic (for example, in the Save() method). If we wanted to, we can also add logic here (through some references to services or DAOs or something) to load additional metadata from external systems like databases.

If you want to get fancier, you could also add a dictionary keyed by string (internal field name) and with value type object and use that to hold your "set" properties until Save() is called. In the save, you'd simply iterate the keys and set the values then update, only changing the values that were actually set by the caller.

Updating the status of a proposal would go from looking like this:

public void UpdateStatus(int id, string status) {
    using(SPSite site = new SPSite(_siteUrl)) {
        using(SPWeb web = site.OpenWeb(_web)) {
            SPList list = web.Lists[_list];
 

            SPListItem item = ...; // Get the list item

            // Perhaps add error checking.

            item["Status"] = status;

            item.SystemUpdate();
        }
    }
}

To this instead:

public void UpdateStatus(int id, string status) {
    using(ProposalsLibrary library = new ProposalsLibrary()) {
        Proposal proposal = library.FindById(id);
 

        proposal.Status = status;
        proposal.Save();
    }
}

It becomes even more compelling once we consider that in a real world implementation of an UpdateStatus() operation, it would probably involve checking to see if a user has the object checked out in the first place! This would make our first example explode into a giant mess of code while in our second one, it would be one line (or integrated into the Save() method which could throw a custom NotCheckedOutException or framework InvalidOperationException or try to check it out automatically).

All this with relatively little work involved. It's better in every way: less nesting of code, much more readable and natural, less error prone, better discoverability, and more domain specific (and less SharePoint-centric). In the end, I think it dramatically improves usability and reuse of your SharePoint application code. It also leads to a nice, logical place to encapsulate much of the common, repetitive, and error prone code that would otherwise be littered among your application (or worse, UI) code.

In future installments, we'll examine how flesh out the FindById() method on the ProposalsLibrary. We'll also examine a GUI pattern to help promote reuse, improve tesatability, and cut down on duplication of business logic.

Filed under: Dev, SharePoint 4 Comments
29Aug/09Off

Design Patterns For SharePoint : Entry 1

Posted by Charles Chen

One thing that I've discovered is that it's easy to write sloppy, hard to read code when SharePoint is involved. A lot of it may be due to the quick-and-dirty code samples out on the 'Net and a general lack of thought put into the structural details of the examples on MSDN (I can understand why as it can make example code much longer to write it well). I have a whole series of blog post ideas on how to mitigate this (based on my own real world experiences) that I've been meaning to put together that kind of put together a big picture of how to make your team's SharePoint development experience less crappy.

While I have some general workflow related tips and tricks, I'll start off this series with a code based sample. Something small that I think will make a big impact in cleaning up code.

One of the most common things that developers need to do when working with SharePoint is to create an instance of SPSite, open an instance of SPWeb and then get a list (or do something else against the web).

Typically, this takes on the following pattern:

private static readonly string  _siteUrl;
private static readonly string  _web;
private static readonly string  _library;
private static readonly string  _otherLibrary;
static MySharePointDAO() {
    _siteUrl = ...; // Hard coded, from a Constants class, or from config.
    _web = ...;
    _library = ...;
    _otherLibrary = ...;
}
 

public void DoSomething() {
    using(SPSite site = new SPSite(_siteUrl)) {
        using(SPWeb web = site.OpenWeb(_web)) {
            SPList list = web.Lists[_library];

            // Code goes here.
        }
    }
}
public void DoSomethingElse() {
    using(SPSite site = new SPSite(_siteUrl)) {
        using(SPWeb web = site.OpenWeb(_web)) {
            SPList list = web.Lists[_otherLibrary];
 

            // Code goes here.
        }
    }
}

There are many different variations of this basic pattern (in the worst case, this code is written right into layout pages or webpart code which I imagine to be quite a common practice...). Sometimes, the strings are hard coded inline, sometimes the strings are from a Constants class, sometimes the strings are read from a configuration file. No matter how it's done, it tends to muck up the code and it ends up all over the place. One of my beefs with this is that it's not very aesthetically pleasing; deep nesting does that (plus, depending on how deep the rest of the code nests, it may start to scroll horizontally...yuck!). You can also stack the using statements (instead of nesting), but that still leaves it a mess (my other beef) since you need to specify the site URL, the web, and potentially a list - it creates a lot of useless, duplicated code all over your codebase.

Yet there is a very simple solution: abstract this logic into a class that implements IDisposable:

using System;
using Microsoft.SharePoint;
 

namespace SharePointExample
{
    /// <summary>
    /// Abstraction for a SharePoint list.
    /// </summary>
    public abstract class Library : IDisposable
    {
        private static readonly string _siteUrl;

        private readonly SPSite _site;
        private readonly SPWeb _web;
        private SPList _list;

        /// <summary>
        /// Static initializer that sets the site URL.
        /// </summary>
        static Library()
        {
            _siteUrl = ...; // Hard coded, from config, or Constants
        }

        /// <summary>
        /// Default constructor that creates the site and web.
        /// </summary>
        protected Library()
        {
            _site = new SPSite(_siteUrl);
            _web = _site.OpenWeb(WebName);
            _list = _web.GetList(ListName);
        }

        /// <summary>
        /// Gets the name of the list.  Inheriting classes
        /// implement this property for a specific list.
        /// </summary>
        /// <value>The name of the list.</value>
        protected abstract string ListName { get; }

        /// <summary>
        /// Gets the name of the web.
        /// </summary>
        /// <value>The name of the web.</value>
        protected abstract string WebName { get; }

        #region IDisposable Members

        /// <summary>
        /// Performs application-defined tasks associated with freeing, 
        /// releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <remarks>
        /// See Cwalina, Abrams; Framework Design Guidelines, 1st Ed., p. 251
        /// </remarks>
        /// <param name="disposing"><c>true</c> to release both managed and 
        /// unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_web != null) _web.Dispose();
                if (_site != null) _site.Dispose();
            }
        }
    }
}

(It's generally not advised to call abstract/virtual members in a constructor, but in this case, they should simply return strings -- should be safe.)

And that's it; so simple. What do our calls look like now? From our presenters/controllers/views, we have something like this instead:

using(ConcreteLibrary library = new ConcreteLibrary()) {

	// Do stuff here with the library.

}

If we only consider this as a win, then it's a very small win. But in the bigger picture, our downstream callers don't need to know about the SPSite, SPWeb, or the SPList if we take the abstraction far enough -- we'll examine this in future installments. Furthermore, we now have a convenient place to put common list based operations and if our business requirements dictate that there are specific lists for specific types of documents, this abstraction becomes even more useful.

I've intentionally left the "Do stuff here..." empty. In the simplest case, at this point, you can simply expose the list, web, and/or site as public properties to inheriting/calling classes and just access library.List or library.Web and use it as you normally would. If nothing else, you've cleaned up the nesting and the leakage of the site URL, web names, and list names. (To make this abstraction more useful, IMO, we would have you hide all of our operations in the ConcreteLibrary and expose the site, web, and list as protected properties to the inheriting classes only.)

This design assumes that you have specific, well known libraries in your SharePoint deployoment in which case it makes sense to create library specific methods and a concrete library sub-type for each library. For example, if a library holds proposals that your sales department has written, you may want to have a class called ProposalsLibrary with a method called FindPendingProposals()which is specific to that library. Of course, common functionality across all lists can be easily added to the base abstract Library class (and this usually involves a "find" operation of some sort).

In general, it's a very small, easy, and intuitive change that makes the code that implements your business logic (as it pertains to SharePoint) much easier to read and to maintain. As we'll explore in future entries in this series, if we take the abstraction far enough, we can completely eliminate the Microsoft.SharePoint namespace from our business/presentation logic.

See also: SharePoint Design Patterns: Entry 2

Filed under: Dev, SharePoint No Comments
27Aug/09Off

On Healthcare: What We Can Learn From The Music Industry

Posted by Charles Chen

Nathan Alderman has an interesting write up on the effect of a public option on the healthcare industry:



A decade ago, the major record labels were fat and happy, making piles of cash off CD sales. They could use their massive marketing muscle to push manufactured bands onto the airwaves and into listeners' ears. If you had to buy a whole subpar album just to get the few songs you really wanted, well, too bad.


Then Internet file-sharing rolled into town. I'm not arguing that piracy's right, but digitally available tunes did become a real competitor to the established music business. Rather than adapt to consumers' changing tastes by going digital themselves -- which would have meant surrendering their fat margins, and some of their control over what people listened to -- the record labels panicked. They started suing file-sharers, driving their own customers away. In short, the record labels weren't meeting customers' demand; they were trying to dictate what they thought customers should demand, and actively ignoring what the free market really wanted. Does that sound like capitalism to you?


Industry outsider Apple (Nasdaq: AAPL) finally had to almost bully labels into offering digital tunes at a fair (or at least fairer) price. Now Amazon.com (Nasdaq: AMZN) and a host of others compete with Apple's iTunes, a rivalry that has lowered prices, eliminated restrictive copy protection, and generally given consumers better music options. In return, audiophiles bought more music in 2008 than ever before, according to a January USA TODAY article. Most of those sales came in the form of digital downloads and individual tracks.


In my opinion, private health insurers are no less slothful and stubborn than record labels were at the dawn of the digital era. Insurers' defenders say that a rival public option would "destroy their industry." WellPoint (NYSE: WLP) has set up a website to oppose it. But in my opinion, it's more likely that the increased competition would merely reduce their profits, loosen their control, and force them to work harder, smarter, and more efficiently. That may be bad news for health insurers' stockholders, but you can't deny that it's good news for folks who need health insurance.


I tend to agree with this view.  A public option would, like Apple's iTunes, hopefully drive prices down over time and force the private insurance industry to adapt, streamline,  cust costs, and come up with a better product.  This is good for consumers.  The whole debate has been pretty baffling to me given that it's an option


Alderman doesn't address two other facets of a public health insurance option that would be good for Capitalism:




  1. It would allow people to take risks.  No, not like jumping out of airplanes or something, but employment risks.  People would feel more comfortable seeking jobs at startups and small businesses (or starting their own!), which traditionally have a hard time offering competitive healthcare benefits.  Risk is good since it is what spawns invention and innovation; it would give smart people more flexibility in moving around and brining their ideas with them.


  2. It gives employees greater freedom (and employers a greater talent pool).  This is kind of related to the first point in that I think this is important to help spread ideas and innovation.  Employees who are dependent on their employer provided healthcare (like people with young kids, a sick spouse, or with a pre-existing condition) are kind of locked into their employers if they are dependent on employer provided healthcare.  Greater freedom to change jobs without worrying about losing health benefits would seem to lead to better wages, greater spread of innovation, and better options for everyone (employee and employers).  How can this be anything but a good thing?

Alderman's basic premise is spot on, in my opinion, that a public option -- if not a full out single payer system -- would help Capitalism and not hurt it.

Filed under: News, Rants 1 Comment
24Aug/09Off

Rental Car Diaries

Posted by Charles Chen

Being a consultant means traveling from time to time (or all the time).  Since May, I've been traveling to Boston on a weekly basis and I've had a variety of cars.  Oddly enough, my favorite car has been a Hyundai; they've really come a long way.  Here's my list of rental car reviews, ranked by preference.



  1. Hyundai Elantra *****.  By a close margin, this has been the best rental I've had.  I've gotten these twice and each time, it was a pleasant surprise (although the second time, it was because it smelled like the previous driver was delivering pizza in it all week).  To begin with, Elantras have perhaps one of the best headrests I've personally used.  It moves up and down like most headrests, but unlike others that just tilt forward, it actually slides forward.  Perfect seating posture for me.  The fit and finish on the interior is excellent with very rich feeling materials and soft plastics.  Driving dynamics were so much better than anything I expected.  Sure, you're not going to be autocrossing in one of these guys, but it handles nicely enough for commuting and the suspension is great when it comes to absorbing bumps.  The transmission also does a good job and gear hunting is relatively minimal.  To top it all off, I was able to plug in my Sansa Clip using a USB cable and the radio automatically recognized it and loaded my play lists.  Awesome!  The radio controls actually control the MP3 player.  Finally, this has been the only car that I've had with auto down and up windows (great for toll booths).
  2. Ford Mustang ****1/2.  I have to admit, this car was: 1) incredibly uncomfortable, 2) hard to find a good seating position in, 3) difficult to get in and out of, 4) had terrible button/control layouts in the center stack, had those silly Ford light controls (on a knob...).  And yet, despite all of that, it's a great rental car because you just feel like such a badass driving one.  I'd never buy one myself, but it's great fun for a rental.  That said, from the driver's seat, I swear, it feels like you're driving a boat; the thing feels huge.  The V6 engine also seems a bit underwhelming considering the sporting nature of the vehicle.  While the Elantra wins hands down in terms of ergonomics, build quality, and fit-and-finish, the Mustang makes up for its shortcomings by being badass. 
  3. Chevy Impala ***.  The Impala was mostly a forgettable vehicle.  The fit-and-finish were certainly nice enough, but the seat was flat as a board and difficult to get comfortable in.  It's ony ranked this high because the other vehicles are so terrible.  Truth be told, if I had one of these as a rental?  I'd probably ask for a downgrade to an Elantra instead.
  4. Saturn Vue **1/2.  I just had this one last week.  Like many American cars I've driven, the Vue suffers from terrible steering feel.  The wheel feels very loose and the steering effort seems to be way too light for my tastes with a lot of play on-center.  Despite the big exterior size, its interior size seemed underwhelming.  Speaking of underwhelming, the engine was clearly working overtime to move the mass of the Vue; it felt lethargic and the transmission was constantly hunting for gears.  If I were in the market for this type of vehicle, I'd probably go with a Rogue instead.  Overall, an underwhelming vehicle.
  5. Subaru Forrester **.  The Forrester has some redeemig qualities like having AWD, which would be great in the winter, and a spacious interior.  Aside from the chintzy, cheap looking/feeling, plasticky interior, there's not much to hate...but then again, there's not much to love either.  On top of all that, you're driving a station wagon.  It doesn't get much lamer than that :P  Oh yeah, the engine was grossly underpowered.
  6. Toyota Corolla *1/2.  This was the first time I'd driven a Toyota Corolla and to be honest, I don't get it.  I was expecting so much more from this car, but it was so disappointing in every respect from the cheap, dark, dingy interior to the forgettable...everyting.  If you're in the market for one of these, the Elantra seems like it would be a much better buy.
  7. Nissan Versa *.  Okay, I'll admit: I'm a Nissan guy.  My mom had a Sentra and then a Maxima.  My wife drives a Murano and I drive a Frontier.  If I had the extra money, I'd by a 370z and a G37x and switch them up for my daily commute (if I had one).  But there is nothing redeeming about the Versa.  The interior was not only dingy, it looked positively industrial and completely uninviting.  Like the Corolla, it was mostly a forgettable car.  If I were in this market segment, I'd probably get a Hyundai Accent or a Kia Forte.
  8. Kia Rondo *.  Maybe I'm just holding it against this Rondo, but the one I have this week is dirty and stained inside.  If I had the patience, I probably would have asked to trade to an Elantra.  Aside from that, being a tall wagon, it looks particularlly lame.  Its one redeeming quality is that its A/C is super frigid.
  9. Dodge Caliber 0*.  Lame. Terrible.  DO NOT WANT.
  10. Pontiac G6 -1*.  Perhaps the Pontiac doesn't deserve this hate, but the week that I had it, it was basically pouring every day of the week.  Unfortunately for me, the key fob was broken and I wasn't able to remotely open the door.  This lead me to discover that the G6 didn't have a very basic feature: the ability to unlock all of the doors by double turning the key in the driver side door (bonus level of suck: no key hole on the passesnger side).  This made it extra hard to get my stuff in and out of the car...while it was pouring.  I can't figure why they wouldn't have this very basic feature, but it was a terrible week without it as I constantly had to unlock the rear door from the inside.

This post was partially inspired by Autoblog's spyshots of the upcoming Sonata (another very nice rental).  Hyundai has seriously come a long way since my '98 Accent.  Hopefully, the Consulting Gods will look kindly upon you the next time you have to travel for business (and rent economy) and bless you with an Elantra!

20Aug/09Off

Thoughts From The Trenches (Giant Brain Dump Incoming!)

Posted by Charles Chen

A random assortment of random thoughts (and rants!) from the trenches...

You Know You're In Trouble When...

  1. You have to convene three people to figure out how to create an instance of one of the core objects in your framework.  I think this is directly related to having an anemic domain model - it just isn't obvious which "service" you should be calling to set the properties on the object.  It seems like the whole thing would be easier if you could just call the constructor or a static initializer on the class to get an instance; this is the most basic premise of an object oriented system (and one that gets thrown to the wayside much too often).  Constructors are the most natural way to create an instance of an object; why not use them?
  2. Your team members are afraid to update their code (in fact, they'll wait days before updating because it's always a painful, time-consuming excursion to get your codebase compiling not to mention your environment working afterwards).  This could be a symptom of many different ills.  In this case, the problem is three fold:
    1. The source control system is painful to use. The culprit is Accurev; it is perhaps one of the worst source control systems I've ever used (not to mention it's very obscure and uses obtuse terms for common source control actions).  A quick search on Dice yields 6 results for the keyword "Accurev" while "svn or subversion" yields some 786 results.  Of course, the big problem with this is that it takes an extraordinarily long time to ramp up a new addition to the team to the peculiarities of the source control system.  (I still haven't figured out how to look at changesets, run "blame" on a file, and why it's so slow...)
    2. There are no automated unit tests for the most basic and important of functionality: data access code. The lack of a structured way to unit test your core data access code makes the entire codebase seem....fragile. Changes in code that are not regression tested tend to break things, which tends to ruin productivity.  I can understand not testing code that is dependent on external libraries which are difficult to test (it really requires a lot of thinking and work to do right), but I can't understand why any team wouldn't test their core data access code.
    3. There is no software support for tracking breaking changes. What I mean by this is, for example, changes to a database schema or a stored procedure.  The standard way some teams "resolve" this issue is by emailing people when a breaking change is entered.  However, the problem with email is that it's easy to forget someone and, even if you remember everyone, it's not easy to backtrack and find all of the different email notices.  For example, if I'm in the process of writing an intense piece of code, I'll ignore a breaking change and deal with it the next time I update.  But by that time, there could be two or three breaking changes.  It's difficult to sort these out in email and much easier to sort them out with some pretty basic software support.  On FirstPoint, we used a Trac discussion to track breaking changes.  Developers checking in breaking changes were required to document the steps that the other developers would need to take to ensure that the environment remained stable.
  3. You're worried about deadlines, but you roll off two people who've been working on your project for two years and replace them with one person who's been working on the project for two months.  Fred Brooks' The Mythical Man-Month covers this pretty succinctly:

    adding manpower to a late software project makes it later

    The problem is that the new resource cannot possibly have the richness of experience with the existing codebase that is require to be productive right away.  In a system that's sparsely documented (and by that I mean there is no documentation on the core object model), it means that a new developer has to interrupt the workstream of more seasoned developers to get anything done.  This is probably okay when the going is slow and steady, but in crunch time, this becomes a big productivity issue.  I know I hate being interrupted when I'm in the zone, so I personally hate to interrupt others, but in this scenario, I have no choice since there is no documentation, the codebase is huge, and it's not at all obvious how to get the data that I need.

  4. When there are multiple ways to set the value of a property on a core object in your model.  What I mean by this is say I have an object called Document and somehow, there were two or more ways to set the value of VersionId (and each way getting you a different type of value) when you use a data access object to retrieve an instance.  Again, this is a byproduct of an anemic domain model.  Because the rules of how to use the object are external of the object itself, the proper usage of the properties becomes open to interpretation, based on the specific service populating the object.
  5. Your object model is littered with stuff ending in "DAO", "Util", "Service", or "Manager".  It means that you haven't really thought about your object model in terms of object interactions and the structural composition.  These are suffixes that I use only when I can't think of anything better.  More often than not, when I write these classes, they truly are utility classes and are usually static classes.  If this is a big portion of your codebase, you have some serious problems.

You Can Make People Productive If...

I think the role of any senior developer, lead, or principal on a project is not to watch over everyone's shoulder and make sure that they are writing good code.  I've learned pretty early on that this doesn't work; you can't control how people write code and if you try to, you'll just get your panties in a twist all the time, raise your blood pressure to unhealthy levels, and piss off everyone around you.  So then the question is how can you get a group of diverse individuals with a diverse level of experience to write consistently good code?

It's a hard question and one that I'm still trying to answer.  However, I've learned a few lessons from my own experiences in working with people:

  1. Make an effort to educate the team.  This means reading assignments, group discussions, and making learning a basic requirement of the job, not an optional extracurricular activity.  Pick a book of the month and commit to reading a chapter a day.
  2. Have code reviews regularly.  One of the surest ways to help get everyone on the same page is through code reviews.  The key is to keep it focused and not let the process devolve into a back-and-forth debate regarding the little things, but rather focus on the structural elements of the objects and interactions.
  3. The smartest guys on the team work on the most "useless" code.  What I mean by "useless" here is that the code doesn't yield immediate benefits; in other words, framework code.  Typically, this involves lots of interfaces, abstract classes, and lots of fancy-pants design patterns.  The idea here is to make it easy for the whole team to write structurally sound code, regardless of skill level, by modeling the core interactions between objects and the core structure of the objects.  I think a key problem is that project managers see this as a zero-sum activity early on in the game (the most important time to establish this type of code) when in reality, it usually returns a huge ROI when done with the right amount of forethought and proper effort to refactor when the need arises.
  4. Document things...thoroughly.  One of the easiest ways to mitigate duplication and misuse is to use documentation in the code.  For framework level code, it's even more important to have solid documentation about the fields, what type of values to expect, how the objects should be used, how instances are created, what special actions need to be performed for cleanup, etc.  Documentation done right can also help improve code consistency if you add examples into your documentation.

Writing good code is productive.  It becomes easier to maintain, easier to bugfix, easier to ramp up new developers, easier for one developer to take over for another, and it means a generally more pleasant and insightful workday, every day.  Which brings us to...

Sound Software Engineering Is Like...

Exercise!  Project managers seem to lose this very basic insight when they make the transition from a developer.  Like exercise, it's always easier to put in the effort to do it regularly and eat a healthy diet than to wait until you're obese and then start worrying about your health and well-being.  Sure, it feels like hard work, waking up at the crack of dawn and going out into the rain/snow/dark, eating granola and oatmeal, skipping the fries and mayonaise, but it's much easier to keep weight off than to lose weight once you're 200lbs overweight!

Likewise, it's always going to be easier to refactor daily as necessary and address glaring structural issues as soon as possible than to let them linger and keep stuffing donuts in your face.  It's like carrying around 200lbs of fat: you lose agility, it becomes difficult to move, everything seems to take more effort - even simple things like climbing the stairs becomes a chore.  The lesson is to trim the fat as soon as possible; don't let serious structural issues linger -- if there's a better, cleaner, easier way to do something, do it that way.  Every excuse you make to keep fat, ugly code around will only make it heavier and harder to maintain.

How To Reinvent The Wheel...

It seems like a pretty common problem: a lead or architect doesn't want to use a library because it's not "mature" enough.  What this means, exactly, still baffles me to this day.  Mature is such an arbitrary measure that it's hard to figure out when software becomes mature.  What this usually leads to is reinventing the wheel (several times over).

When evaluating third party libraries, I really only have a handful or criteria to consider whether I want to use it or not:

  1. Is it open source and is the license friendly for commercial usage? I'll almost always take a less feature-rich, open source library over a more complete licensed library.  The reason is that there's less lock-in.  I won't feel like I've just wasted $1000 (or whatever) if I encounter a scenario where the library is insufficient or plain doesn't work.
  2. Does it have sufficient documentation to get the basic scenarios working? This is perhaps the only measure of "maturity" that matters to me.
  3. Does it solve some scenario that would otherwise take the team an inordinate amount of time to impelment ourselves? I hate wasting time duplicating work that's freely available and well documented with a community of users who can help if the problem arises.  And yet, time and time again, there is no end to the resistance against using third party libraries.  Part of it is this very abstract definition of "maturity" (objections by technical people) and part of it is a fundamental misunderstanding and general laziness about different licensing models (the business folks).

That's it.  I don't need the Apache software foundation to tell me whether log4net is mature or not.  I look at the documentation, I write some test code, I use it and I evaluate it, and I incorporate it once I'm satisfied.

Software Estimation And Baking Cakes...

Fine grained software estimation is most assuredly the biggest waste of everyone's time.  Once it comes down to the granularity of man-hours, you know that someone has failed at their job since there is no way to even quantify that level of absurdity.  Once you start having meetings about your fine-grained estimates that pull in all of the developers, then you really know that you're FOCKED.

If I handed you a box of cake batter and asked how long it would take you to bake the cake, you'd probably take a look at the directions, read the steps, and estimate how long it would take you to perform all of the steps and add the baking time and come up with 50 minutes.  Okay, we start the timer.  You're off and cracking eggs and cutting open pouches and what not.  But wait, your mother calls and wants to talk about your trip next week.  -5 minutes.  You open the fridge and find that you're half a stick of butter short so you run to the grocery store.  -30 minutes.  Oh shoot!  You forgot to pre-heat the oven.  -5 minutes.  Finally, you've got the batter mixed up and ready to bake.  The directions say to bake for 40 minutes but you've already used up 40 minutes and only 10 minutes left of your original estimate: now what?

Well, you could turn up the heat, but that'd only serve to singe the outside of the cake while leaving the inside uncooked.  You could just bake it for 10 minutes, but your cake would still be uncooked -- but hey, you'd meet your estimate.  More likely than not, you'd just bake the cake for 40 minutes and come in 30 minutes late since late, edible cake is better than burnt or mushy cake.

Software estimation is kinda like that (and look, in the case of baking a cake, all of the directions and exact steps are already well defined and spelled out for you -- writing software is rarely so straightforward).  It's mostly an exercise in futility once it becomes too granular since there are just too many variables to account for.  The answer -- if it must be implemented feature complete -- is that it's going to take as long as it's going to take (and probably longer!).  For most non-trival tasks, I feel like the only proper level of granularity is weeks.  Don't get me wrong, I'm not saying that you shouldn't estimate, but that you should estimate at the right level of granularity and accept that once you've reached your estimation and the work isn't done, your only real choices are to:

  1. Extend the deadline.
  2. Trim the unnecessary features.

So that's it; feels good after a brain dump!

12Aug/09Off

Advertising Done Right

Posted by Charles Chen

This one made me chuckle:




Filed under: lulz, Miscellany No Comments