in

 

Jimmy Bogard

Assistant to the assistant to the regional manager

May 2008 - Posts

  • MVC Storefront Challenge Kickoff

    Last week, I announced the MVC Storefront Challenge, which is a response to some feedback Rob Conery was getting on his ongoing MVC Storefront series.  Before I could get started, I needed to get the original project up and running on my own machine.

    I had to install Unity and restore the included database (I already had ASP.NET MVC installed), but everything is up and running.

    The original idea behind the challenge is the feedback Rob's getting to switch to various OSS tools for an assortment of applications, including ORM, IoC, unit tests, etc etc.  Rob didn't think this made sense, and I don't either, as it doesn't work too well to switch out the engine in the middle of a race.

    The goal of the challenge is to use these open source tools to build an identically functioning MVC Storefront.  By "identically functioning", I'm referring to the end-user experience.  HTML and URLs will be exactly the same for both applications, as well as user flow.

    Ground rules

    Since HTML, URLs etc need to be exactly the same, we can achieve this by:

    • Continue to use ASP.NET MVC
    • Use the same controller classes, at least the signatures
    • Use the same views
    • Use the same view models

    Everything else can change.

    Goals

    Besides just getting familiar with ASP.NET MVC, the goals of this project include:

    • Showing sample usages of popular OSS .NET tools
    • Compare implementations of similar scenarios between the two approaches
    • Hopefully create some teaching opportunities for these approaches

    The point of this isn't an exercise of "Linq 2 SQL is teh lame" or anything like that.  There aren't many comparisons that I could find of identical applications with completely different infrastructure, so it will be nice to have some comparisons.

    First steps

    Right now, all I have is the MVC Storefront code running on my local machine.  The license allows reproduction and derivative works, providing I include the original license (Ms-PL).  To get this going, I'll need to:

    • Pick a name for the project
    • Create a home for the project
    • Remove all non-ASP.NET projects from the solution
    • Get it building!

    From there on out, I'll have some skeleton controllers to start adding behavior.  To do so, I'll probably have to do some myself, and hopefully do some recorded pairing with other folks.  As Rob completes more functionality, we'll add it to the MVC Challenge project.

    Once I get the first steps ironed out (send in project names, kthx), it's just a matter of flushing out the controllers.  <sarcasm>Easy, right?</sarcasm>

  • Austin Code Camp material posted

    I've (finally) posted my slides and code from Austin Code Camp:

    All code includes before and after solutions, along with descriptive comments on the changes made (and why).

    The slides aren't too interesting, as most of the slide notes contain a line-for-line transcription of the classic Mel Brooks movie, Spaceballs.  If things went bad during my presentations, my backup plan was to perform a solo reenactment of the entire film.

    Luckily for the audience, the presentations weren't a complete disaster.

    If you have any questions about any of the material, don't hesitate to contact me.

  • Working with the web model

    Lots of comments from my recent post on ASP.NET WebForms being officially unmaintainable noted that:

    • AJAX works with the ClientID property
    • I don't care about HTML

    One thing to remember about web applications is that web applications are nothing more than HTTP, Cookies, HTML, CSS and JavaScript.  Let's spell that out again.  Web applications are:

    • HTTP
    • Cookies
    • HTML
    • CSS
    • JavaScript

    You can create web applications without CSS and JavaScript, but the latter three represent the structure, style and behavior of a single web page.  HTTP is engine that makes at all work, and the browser is the window into our application.  The browser does not care, nor will ever care about:

    • Postbacks
    • Viewstate
    • Lifecycle events

    All of these are a clever ruse on top of the four elements of a web application, an effort by the ASP.NET developers to make the web appear as a stateful application like the VB6 applications before it.  One slight problem: HTTP is inherently stateless.

    Many web application frameworks solve the stateless problem through Session objects, where a unique cookie value matches clients with state bags on the server.  All persistent state lives completely on the server, hidden from view from the client except a cookie value.

    Now the five components of a web application are simple in and of themselves.  Combined, they can create very powerful client experiences.  The browser, completely decoupled from the server, serves as a conduit for a myriad of applications, each supplying all the building blocks a browser needs. No matter what happens on the server, eventually all data must go across the HTTP wire, delivering HTML and the others.

    And that's the beauty of web development: browsers completely decoupled from the server technology used to serve the pages, and a set of standards covering each component (HTML, CSS, etc.)

    So why the WebForms abstraction?

    ASP.NET needed to convert a mass of VB6 developers into web developers.  To do so, WebForms mimicked a stateful web application through clever use of JavaScript, the FORM element's TARGET attribute, and some hidden INPUT elements to persist state.  These combined tricks enabled the PostBack model, where a page posts back to itself for processing.

    Already, WebForms is subverting and abstracting the very nature of HTTP - statelessness of postbacks.  Additionally, server controls abstracted the raw HTML being sent to the client.  With WebForms, you lost control an important component of a web application: HTML.  You also lost control of the FORM TARGET, which allowed for posting to specific URLs for specific controlling.

    So what's the big deal, right?  HTML is annoying.  It doesn't render properly in every browser, and CSS tricks sometimes are the only way to get IE6 and lower to behave properly.

    But the underlying concepts are dead simple.  HTML to describe the structure of your information, and CSS style the information.  When something doesn't look right in the browser, no server technology matters.  It's only HTML, CSS and JavaScript.

    By programming in the actual underlying language of the web, we don't have to undergo the translation that Web Controls force, nor the behavior change that WebForms force.  Since we're constantly posting back to the same page, a single page has to be responsible for quite a few things:

    • Creating HTML to be rendered, through an elaborate server control hierarchy
    • Flow Control, through elaborate life cycle events

    But the web is much, much simpler than server controls and life cycle events.  HTTP GETs and POSTs are how users request information, not through a Button_Click event.

    Working with the model

    The main problem I have with WebForms is that it tries to make the web something it's not: a client application.  Although events get fired on the server, it's only through the hidden form variables and self-posting forms that this is possible.

    WebForms works completely against the inherent nature of the web, which is why it can be such a pain to work with.  WebForms did introduce a number of great concepts, including a component-based architecture, the request pipeline, caching, etc etc.

    So how do you develop web applications outside of WebForms?  For one, you don't use the WebForms designer.  The designer lies to you, as it is only the browser that is the singular truth to what your web application will look like.  Instead, I structure my HTML directly, using CSS for styling.

    How do you develop behavior and flow control?  MVC frameworks do this by routing control to the Controller first.  The Controller, after performing any flow logic it needs, can pass data to the View.  The View is only responsible for taking in data and creating HTML, CSS and JavaScript.

    By separating these concerns, we are both working with the model the web is built upon, and allowing complexity to vary independently between the Controller and the View.

    When first coming over to ASP.NET from ASP 3.0 back in 2002, I both marveled at the cleverness of ASP.NET and disliked the control that was taken away.  The difficulty in ASP development was the language (VBScript is not OO) and the unholy marriage of concerns, as Controller and View were in one single file.  Not creating HTML, handling requests, or anything else to do with the components of the web.

    Eventually, after seeing other web application frameworks come to the forefront, including Rails, I began to notice the cracks in the woodworks.  HTML isn't hard, it's the flow control where the meat of the application resided.

    Now, I'd rather work with the web model than against it.  I recognize that HTML is all that matters in the end, so I might as well accept it and embrace it.

    Posted May 21 2008, 08:46 PM by bogardj with 26 comment(s)
    Filed under:
  • The MVC Storefront Challenge!

    In Rob Conery's recent post on the MVC Storefront example he's been working on, he got some comment to basically toss out Linq2SQL and use NHibernate instead.

    Blah.

    How about the community does it instead?  I'm not looking for an us vs. them or Linq2SQL vs. NHibernate battle, more of an intellectual experiment where we have two identical apps, built on two different ORM platforms.  The goal would be to highlight NHibernate's strengths and weaknesses, as well as Linq2SQL's strengths and weaknesses through a comparison of the resulting architecture and design.

    Personally, I'd like to start this one out by forking the original code and pairing with someone live.  Maybe it can become a reference NHibernate/DDD app?  Or maybe it will expose the naked truths of my complete lack of coding skills?  Probably the latter.

    The general idea would be to start with the use cases laid out in the screens, and go backwards from that.  Many of the entities would probably remain the same, but the aggregates/roots/repositories would have a distinctly different feel.  All driven from TDD of course.

    As I noted earlier, I'd want this driven live pairing, so either in person (I'm in Austin, TX) or Skype-VNC sessions (if I can figure that stuff out).  Some ground rules are:

    • All code is put in TDD
    • Ping-pong style pairing prevents me from getting *too* plastered
    • Follow DDD concepts, entities, value objects, repositories, blah blah blah
    • Don't knock me for subtly introducing my hilarious ultra-right-wing ideals as variable names (string NRA4EVER = "cold, dead hands";)

    If you're interested, drop me a line here.  WARNING: Dropping a line constitutes a binding legal contract and will result in a ninja squad administering an Evans and Beck tattoo on your knuckles in the dead of night.

    It should be a lot of fun, or a complete disaster, one of the two.  But fun either way.

  • Entities, Value Objects, Aggregates and Roots

    Taking a small detour before I deliver the first installment in the Domain-Driven Design: Supple Design Patterns series, I'd like to cover the basic elements of Domain-Driven Design modeling:

    • Entities
    • Value Objects
    • Aggregates and Roots

    I'd like to cover these aspects partially because these ideas play a large role in the later ideas, but also because Rob asked me to (see comments).  If you'd like an in-depth discussion of these topics, just check out Eric Evans' Domain-Driven Design, chapters 5 and 6.

    Entities

    From Evans:

    Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity.

    In traditional object-oriented design, you might start modeling by identifying nouns and verbs.  In DDD modeling, I try to key in on terms coming out of our Ubiquitous Language that exhibit a thread of identity.

    For example, consider a Person concept.  If I have two Person objects, with the same Name, are they same Person?  Bob Smith from Cheyenne, Wyoming and Bob Smith from Tallahassee, Florida might not agree.  A popular gimmick I've seen is interviewing a Person with a famous name (but different identity).  So if Name isn't a Person's distinguishing attribute, what is?  Address?  Social Security Number?  Not for non-US citizens, what about a Kiwi Bob Smith?

    In each of these examples, a Person is identified by more than their attributes, such as Name, Address, PhoneNumber, etc.  A Person has a unique identity that manifests itself if different ways in different systems.  Each system has their own attributes they're concerned with, but the Person is always the same entity (not class, that's different).

    My "litmus test" for Entities is a simple question:

    If two instances of the same object have different attribute values, but same identity value, are they the same entity?

    If the answer is "yes", and I care about an identity, then the class is indeed an entity.  I model entities with reference objects (classes), and I give them a surrogate identity (i.e., probably a GUID).  Additionally, my model must include what it means to have the same identity.  That means overriding Equals, looking solely at the identity and not attributes.

    Value Objects

    From Evans:

    Many objects have no conceptual identity.  These objects describe characteristics of a thing.

    When I don't care about some object's identity, I carefully consider making the concept a value object.  For example, if I have a system that models Paint buckets, the Color is a great candidate for a Value Object.  I care about one specific PaintBucket or another, as I paint with individual PaintBuckets that will eventually be drained of their paint.

    But when checking the Color of a specific PaintBucket, the Color has no identity in an of itself.  If I have two Colors with the exact same pigmentation values, I consider them to be the same.

    When designing Value Objects, I want to keep them away from the trappings of Entity life cycles, so I make the Value Object immutable, and remove any concept of identity.  Additionally, I'll override Equals to compare attributes, so that attribute equality is represented in my model.

    By making my Value Object immutable, many operations are greatly simplified, as I'm immediately led down paths to Side-Effect Free Functions.  I don't create a type with a bunch of read-write properties and call it a Value Object.  I make it immutable, put all of the attributes in the constructor, and enforce attribute equality.

    Value Objects, like any other pattern, can be over-applied if you go hunting for opportunities.  Value Objects should represent concepts in your Ubiquitous Language, and a domain expert should be able to recognize it in your model.

    Aggregates and Roots

    In real life, many concepts have relationships to each other.  I have a set of credit cards, and each credit card has an owner (me).  Each credit card has a billing institution, and each banking institution has a set of credit accounts, each of which may or may not be a credit card.  If I were to represent all of these concepts as classes, what would the relationships be?

    Should I represent every conceivable relationship possible in my object model?  Where do I draw the line between whether or not to create a reference?  If I have a reference between two entities, how should I handle persistence?  Do updates cascade?  Suppose an Employer has reference to their Manager directly.  If I change the Employee.Manager.Name, and save the Employee, does the Manager's Name get changed?

    Object modeling is complex as it is.  Invariants need to be enforced not only in an Entity, but in all the Entities that are referenced as well.  That gets tough to maintain, and quick!

    Aggregates draw a boundary around one or more Entities.  An Aggregate enforces invariants for all its Entities for any operation it supports.  Each Aggregate has a Root Entity, which is the only member of the Aggregate that any object outside the Aggregate is allowed to hold a reference to.  From Evans, the rules we need to enforce include:

    • The root Entity has global identity and is ultimately responsible for checking invariants
    • Root Entities have global identity.  Entities inside the boundary have local identity, unique only within the Aggregate.
    • Nothing outside the Aggregate boundary can hold a reference to anything inside, except to the root Entity.  The root Entity can hand references to the internal Entities to other objects, but they can only use them transiently (within a single method or block).
    • Only Aggregate Roots can be obtained directly with database queries.  Everything else must be done through traversal.
    • Objects within the Aggregate can hold references to other Aggregate roots.
    • A delete operation must remove everything within the Aggregate boundary all at once
    • When a change to any object within the Aggregate boundary is committed, all invariants of the whole Aggregate must be satisfied.

    That's a lot of rules!  All of them just come from the idea of creating a boundary around our Aggregates.  The boundary simplifies our model, as it forces us to consider each relationship very carefully, and within a well-defined set of rules.  Maintaining bi-directional associations is difficult enough without persistence thrown into the mix, so by modeling our relationships around real-world use cases, we can greatly simplify our model.

    Not all relationships need to be represented through associations.  In the Employee/Manager relationship, I can have a Manager directly off the Employee, but to get a Manager's DirectReports, I'll ask the EmployeeRepository.  Since Employee is an Aggregate Root, it's fine to have an Employee reference its Manager.

    Modeling and simplification

    One of my favorite quotes from Evans' book is:

    Translation blunts communication and makes knowledge crunching anemic.

    To avoid translation, we'll represent real-world concepts in our conceptual model, and our conceptual model expressed as code through Entities and Value Objects (and Services).  To simplify our model, we'll use Aggregates and Roots, enforcing invariants at each operation.  In all cases, I should be able to represent our conceptual model in our code, and it should make sense to our domain expert, as they'll see the Ubiquitous Language represented.

    When the conceptual model we create with the domain expert is realized effectively in code, we'll find that not only to technical refactorings become easier, but enhancements to our model as well.  Entities and Value Objects are but a slice in the DDD world, but a core concept which many other ideas are built upon.

  • More Entity Framework thoughts

    Dan Simmons has a great write-up on Microsoft's vision of Entity Framework that really gives some insight into the motivation behind a lot of the direction that they're going in.  Go read that post, and come back.

    Back now?  OK good.  I like to pull quotes out, and I don't like to pull them out of context, so it's best to read the original post or I might seem like a bit of a tool for doing so.

    The quote that showed me the direction the best was:

    The EF was specifically structured to separate the process of mapping queries/shaping results from building objects and tracking changes.  This makes it easier to create a conceptual model which is how you want to think about your data and then reuse that conceptual model for a number of other services besides just building objects.

    The emphasis added is mine.  Dan then goes on to describe the different ways you might reuse the conceptual model, from reporting, exposing RESTful services, online/offline models, etc etc.

    Those are a LOT of different concerns to be talking to the same database.  Although a mapping layer provides a translation, it's still talking to the same database.

    My comment on his post was:

    I think it's a mistake to share a data model with anyone outside your bounded context (see Evans, Domain-Driven Design).  It's also a mistake to share a conceptual model or a EDM or whatever we're calling this.

    I never want domain objects exposed directly via services.  That's violating the encapsulation I'm trying to create.

    If someone wants SSRS, then I give them a separate reporting database, tailored to reporting needs.  I don't want reporting concerns bleeding into my transactional concerns.  A mapping layer will not solve this problem, products like SSIS can.  You want reporting? Here's your read-only view, updated every hour, five minutes, daily, whatever.

    Sharing a connection string is sharing a connection string, no matter how much lipstick you put on that pig.

    You'll get nothing but trouble if you share a database connection string, no matter how many layers you put between them.  Because eventually, some consumer of that data will want some change in the database (not just the conceptual model).  Not maybe, not in edge cases, but always.

    Personally, I'd much rather go for the Domain-Driven Design style Bounded Context, where I have Anti-Corruption layers between different domains.  Sure, an Order entity might have the same identity from context to context, but that doesn't mean the conceptual model stays the same.

    And how would you manage and maintain those conceptual models, when so many folks might need change?  You'd have to shape your organization around your conceptual models to be able to handle the feedback and change requests from the different groups using your One True Model.

    The EF goal is well beyond simple ORM.  It's an Object-Relational Mapper Mapper.  You map your ORM to another conceptual map, which maps to the data model map, which maps to the database.  The "just building objects" part tells me that EF is seriously discounting the idea of a rich domain model, which is where the heart of my business logic is.

    There, and in stored procedures of course.

  • ASP.NET: officially unmaintainable

    Recent forays back into "classic" ASP.NET (i.e. not MVC) have me completely convinced that ASP.NET is inherently unmaintainable.  Not partially convinced, not on the fence, but completely convinced that the presentation layer of ASP.NET cannot be maintained in any reasonable manner.

    I remember a presentation on MonoRail some time ago, where the presenter asked the audience "how many of you work with ASP.NET in a professional manner?"  A hundred or so hands went into the air.  The presenter then asked, "Now keep your hands in the air if you actually enjoy working with ASP.NET?"  Only a handful of hands stayed in the air.

    Now, obviously some peer pressure skewed these results, and it wasn't a double-blind survey, but it was clear that developing with ASP.NET is a frustrating experience.  My own personal frustrations include:

    • The ridiculous amount of time I spend in Reflector trying to figure out why things that are supposed to "just work" when wired up "just don't"
    • Not having control over the HTML that is spit out.
    • Trying to do anything with AJAX or DHTML with the insane control names
    • That ASP.NET is the king of leaky abstractions

    I try to make the ASP.NET layer as thin as possible, so that the bulk of the application is maintainable.  But even in a MVP setting, the V is still dreadful to maintain.  In the end, HTML is the application, not controls.  HTML is what gets delivered to the client, not crazy post-back event server nonsense.

    I knew early on I would have troubles with ASP.NET, back in 2003-4 or so, when I had to use Reflector to get even basic scenarios to work with a DataGrid.  Debugging why control event isn't getting fired pushes my sanity to the brink.

    It also doesn't help the fact that I've never seen an ASP.NET application with unit tests for the code-behinds.  Without tests, your code is unmaintainable.  Since you can't unit tests code-behinds, you have an immediate charge in your technical debt.  For this reason, I can't really recommend using plain ASP.NET, almost ever.  Using a real MVC framework in MonoRail was not only a breath of fresh air, it felt like I was the frog getting rescued from the pot of boiling water, never noticing the temperature going up.

    So do yourself a favor, take the one week MonoRail challenge.  Try building one aspect or one story in MonoRail, and see how it feels.  Personally, it felt like a crushing weight was finally lifted.  You might feel the same, and with a one-week spike (or even one day), what have you got to lose?

  • Austin Code Camp 2008 post-mortem

    I really hate the word "post-mortem."  Did someone die?  Anyway, I had a great time in my talks over:

    • Legacy Code
    • Intro to C# 3.0
    • Mocks and Stubs

    All in all, I felt the Legacy Code talk went the best as it generated the most discussion.  I heard much of the same story, failures of intense, lengthy refactoring efforts.  Lots of people had the same experience, and these failures led to even deeper trust problems between the business and the developers.  I'll follow up with my own personal story, but it sounded exactly the same, over and over again.  Developers running off for weeks to months, "improving the design", but with little or no business direction in the process.  Failure, every time.

    The best outcome was several folks asking how to apply these techniques back in their place of work.  My answer was start a book club on the Legacy Code book to create awareness of the problem, as well as desire to change.

    The other presentations went OK at best.  The mocking discussion focused too much on a tool as opposed to great examples of the "why", although the later discussion of the "why" finally got some good discussion from the audience.  The example I used skewed towards showing specific use cases of mocking and test doubles.  But, it was my first presentation on the topic, and it was a great learning experience.  Also, it hurt that I was late for the talk because my previous talk ran over.  Note to self: never schedule back-to-back talks, and always adhere to the prescribed stop time.

    I did get to attend a few other talks, and my favorite was Gordon Mongomery's "Coding for stupid users" talk.  Awfully narcissistic and condescending, right?  But the actual talk focused on User Experience, or UX.  UX is (I believe) the most overshadowed project necessity, even above testing and automation.  The best software in the world is useless if the end-user is unable to fathom how to use the darn thing.  It's something I'd like to use more and more in upcoming projects.

    Thanks to the speakers, the organizers, the volunteers, St. Edwards for hosting the conference, and all the attendees that took a Saturday off to geek out.

  • See you at Austin Code Camp!

    This week I'll be speaking at Austin Code Camp, a technical conference here in Austin that features in-depth code-centric sessions.  The sessions I'm doing are:

    • Intro to C# 3.0 - covering practical and pragmatic applications of the new features of C#
    • Mocks and Stubs - a look at mocking and other test doubles, with and without Rhino Mocks
    • From Minefield to Greenfield: Taming the Legacy Code Beast

    The last one is my favorite topic.  I'll present an overview of Feathers' Legacy Code book, and dive into some actual legacy code problems I've encountered over the years.  All of my topics show practices and techniques that I use nearly every day, so you won't see any dragging and dropping.  I'm planning on some raffles and giveaways, though the prizes consist mostly of junk mail and old catalogs.

    The cost is free (as in beer) for the code camp, and the free cost includes lunch and a t-shirt (I think).  See you Saturday!

    Posted May 15 2008, 07:51 AM by bogardj with no comments
    Filed under:
  • Domain-Driven Design: Supple Design Patterns Series

    At last week's Austin DDD Book Club, we discussed my favorite chapter in Evans' Domain-Driven Design book: Supple Design.  Modeling is an important exercise in Domain-Driven Design, but it's not enough to have a codebase that's easy to work with.  In addition to designs that are easily changed, supple designs enable changes originating from deep modeling.

    Code can be easy to change technically with low coupling, high cohesion and a safety net of unit tests.  But what about additions or new concepts to your model?  With supple design, changes in the model are easily realized in your code.  I've been involved in many projects where the conceptual model was clear and well-documented, but the design represented as code was a mess.  There's always a simplification going from model to code, but it shouldn't be a translation.

    Evans notes that developers have two roles that must be served by the design:

    • Developer of a client, where concepts of the model are easily discerned and naturally composed
    • Developer working to change it, so that changes necessary are visible and obvious

    To move achieve a supple design, Evans lays out a set of design patterns:

    • Intention-Revealing Interfaces
    • Side-Effect-Free Functions
    • Assertions
    • Conceptual Contours
    • Standalone Classes
    • Closure of Operations
    • Declarative Style of Design

    The idea of a supple design is fairly abstract and hard to nail down.  But its basic principles are those that go beyond simply code that is easy to change.  If the code doesn't reflect your actual model, it can be just as difficult to work with as bad code.  With supple design, a model is more easily realized in code, eliminating some of the wasteful translations that happen on so many projects.

    Over the next couple of weeks, I'll dive in to each of the design patterns above.  These design patterns aren't structural, like Strategy or Visitor, but related to the model aspects of the design.  By applying the concepts in the supple design patterns, we'll have a codebase that's both easy to change and a pleasure to work with.

  • LINQ query operators: lose that foreach already!

    Now that .NET 3.5 is out with all its LINQ query operator goodness, I feel like going on a mean streak of trashing a lot of our (now) pointless foreach loops.  Some example operations include:

    • Transformations
    • Aggregations
    • Concatenations
    • Filtering

    As I mentioned in my last post, temporary list creation is a great pointer to find opportunities for losing the foreach statements.  I keep the foreach statement when the readability and understandability of the code drops with the LINQ change, but otherwise, a lot less temporary objects are floating around.  Personally, the jury is still out for me whether it's clearer to return "IEnumerable<LineItem>" over "LineItem[]", but the temporary array creation doesn't seem to have much of a point.

    Transformations

    Transformations are easy to spot. You'll create a new List<Something>, then loop through some other List<OtherThing> and create a Something from the OtherThing:

    public OrderSummary[] FindOrdersFor(int customerId)
    {
        IEnumerable<Order> orders = GetOrdersForCustomer(customerId);
        List<OrderSummary> orderSummaries = new List<OrderSummary>();
    
        foreach (Order order in orders)
        {
            orderSummaries.Add(new OrderSummary
                                {
                                    CustomerName = order.Customer.Name,
                                    DateSubmitted = order.DateSubmitted,
                                    OrderTotal = order.GetTotal()
                                });
        }
    
        return orderSummaries.ToArray();
    }
    

    Note the temporary list creation, just to return an array.  With LINQ query operators, I can use the Select method to do the same transformation in less code:

    public OrderSummary[] FindOrdersFor(int customerId)
    {
        return GetOrdersForCustomer(customerId)
            .Select(order => new OrderSummary
                                 {
                                     CustomerName = order.Customer.Name,
                                     DateSubmitted = order.DateSubmitted,
                                     OrderTotal = order.GetTotal()
                                 })
            .ToArray();
    }
    

    By chaining the methods together, it comes out much more readable.

    Aggregations

    Aggregations can be found when you're looping through some list for some kind of calculation.  For example, the GetTotal method on Order loops to build up the total based on each item's ItemPrice:

    public decimal GetTotal()
    {
        decimal total = 0.0m;
    
        foreach (LineItem lineItem in GetLineItems())
        {
            total += lineItem.ItemPrice;
        }
    
        return total;
    }
    

    Again, this can be greatly reduced using LINQ query operators and the Sum method:

    public decimal GetTotal()
    {
        return GetLineItems()
            .Sum(item => item.ItemPrice);
    }
    

    Not only is the code much smaller, but the intent is much easier to discern.  Sometimes a calculation can be tricky, and in those cases LINQ isn't bringing anything to the table.  As always, use good judgement and keep an eye on readability.

    Concatenations

    Oftentimes I need to combine many lists into one flattened list.  For example, suppose I need a list of OrderLineItem summary items, perhaps to display on a grid to the end user.  However, I want to display all order line items for all orders, which is difficult to build up manually:

    public LineItemSummary[] FindLineItemsFor(int customerId)
    {
        IEnumerable<Order> orders = GetOrdersForCustomer(customerId);
        List<LineItemSummary> lineItemSummaries = new List<LineItemSummary>();
    
        foreach (Order order in orders)
        {
            IEnumerable<LineItemSummary> tempSummaries = TransformLineItems(order, order.GetLineItems());
    
            lineItemSummaries.AddRange(tempSummaries);
        }
    
        return lineItemSummaries.ToArray();
    }
    

    Note the two temporary lists: one to hold the concatenated list, and the other to hold each result as we loop through.  With the SelectMany method, this becomes much shorter:

    public LineItemSummary[] FindLineItemsFor(int customerId)
    {
        return GetOrdersForCustomer(customerId)
            .SelectMany(order => TransformLineItems(order, order.GetLineItems()))
            .ToArray();
    }
    

    No temporary lists are created, and all of the LineItemSummary objects are concatenated correctly.  Nested foreach loops as well as the AddRange method are indicators that the SelectMany method could be used.

    Filtering

    Filtering looks similar to transformations, except there's an "if" statement that controls adding to the temporary list.  Suppose we want only the expensive LineItemSummary items:

    public LineItemSummary[] FindExpensiveLineItemsFor(int customerId)
    {
        IEnumerable<Order> orders = GetOrdersForCustomer(customerId);
        List<LineItemSummary> lineItemSummaries = new List<LineItemSummary>();
    
        foreach (Order order in orders)
        {
            foreach (LineItem item in order.GetLineItems())
            {
                if (item.ItemPrice > 100.0m)
                    lineItemSummaries.Add(new LineItemSummary
                                              {
                                                  CustomerName = order.Customer.Name,
                                                  DateSubmitted = order.DateSubmitted,
                                                  ItemPrice = item.ItemPrice,
                                                  ItemName = item.ProductName
                                              });
            }
        }
    
        return lineItemSummaries.ToArray();
    }
    

    This example has both concatenation and filtering.  The filtering can be taken care of with the Where method, and we'll use the same technique earlier with the SelectMany method:

    public LineItemSummary[] FindExpensiveLineItemsFor(int customerId)
    {
        return GetOrdersForCustomer(customerId)
            .SelectMany(order => TransformLineItems(order, order.GetLineItems()))
            .Where(item => item.ItemPrice > 100.0m)
            .ToArray();
    }
    

    By adding the Where method, we can filter out only the expensive line items.  The method chaining looks much better than the nested foreach loops coupled with the if statement, and got rid of the temporary list creation.

    Lose the foreach

    With the new LINQ query operators, any temporary list creation and foreach loop should be considered suspect.  By understanding the operations LINQ gives us, we can not only reduce the amount of code we create, but the end result matches the original intent far better.

    Not every foreach or temporary list should be removed, as sometimes long chains and large lambdas tend to muddy rather than clear the picture.  But for a great deal of scenarios, LINQ query operators can vastly improve the readability of transformation (Select), aggregation (Sum), concatenation (SelectMany) and filtering (Where) sections of your code.

    Posted May 09 2008, 06:11 PM by bogardj with 6 comment(s)
    Filed under: ,
  • Enhancing mappers with LINQ

    The "big 3" higher-order functions in functional programming are Filter, Map and Reduce.  When looking at the new C# 3.0 LINQ query operators, we find that all three have equivalents:

    • Filter = Where
    • Map = Select
    • Reduce = Aggregate

    Whenever you find yourself needing one of these three higher-order functions, just translate them into the correct query operator.  "Select" doesn't have the same dictionary meaning as "Map", but the signature is exactly the same.

    The trick to knowing you can use these higher order functions is to look out for situations where you:

    1. Create a new collection
    2. Iterate through some other collection
    3. Add items from the other collection to the new collection

    Any time you see this general algorithm, there's a much terser syntax available with LINQ.

    Mapper patter example

    For example, consider the Mapper pattern:

    public interface IMapper<TInput, TOutput>
    {
        TOutput Map(TInput input);
    }
    

    A common scenario to map is when I'm creating DTOs or message objects from Domain objects.  Serializing domain objects generally isn't a concern of the domain object, as DTOs tend to be flattened out somewhat.  I might have the following domain objects:

    public class Customer
    {
        public Guid Id  { get; set; }
        public string Name { get; set; }
    }
    public class SalesOrder
    {
        public Customer Customer { get; set; }
        public decimal Total { get; set; }
    }
    

    I'd like to send a Sales Order over the wire for display in some client application.  But suppose the Customer object contains dozens of properties, perhaps things like a billing address, a shipping address, and so on.  The service I'm creating only needs a summary of customer information, so I create a SalesOrderSummary message class:

    public class SalesOrderSummary
    {
        public string CustomerName { get; private set; }
        public Guid CustomerId { get; private set; }
        public decimal Total { get; private set; }
    
        // For serialization
        private SalesOrderSummary() { }
    
        public SalesOrderSummary(string customerName, Guid customerId, decimal total)
        {
            CustomerName = customerName;
            CustomerId = customerId;
            Total = total;
        }
    }

    The corresponding mapper would look like:

    public class SalesOrderSummaryMapper : IMapper<SalesOrder, SalesOrderSummary>
    {
        public SalesOrderSummary Map(SalesOrder input)
        {
            return new SalesOrderSummary(input.Customer.Name, input.Customer.Id, input.Total);
        }
    }
    

    Nothing too exciting so far, right?  Well, suppose now I need to return an array of SalesOrderSummary, perhaps for display in a grid.  In that case, I'll need to build up a list of SalesOrderSummary objects based on a list of SalesOrder objects:

    public SalesOrderSummary[] FindSalesOrdersByMonth(DateTime date)
    {
        // get the sales orders from the repository first
        IEnumerable<SalesOrder> salesOrders = GetSalesOrders();
    
        var salesOrderSummaries = new List<SalesOrderSummary>();
        var mapper = new SalesOrderSummaryMapper();
    
        foreach (var salesOrder in salesOrders)
        {
            salesOrderSummaries.Add(mapper.Map(salesOrder));
        }
    
        return salesOrderSummaries.ToArray();
    }
    

    This isn't too bad, but the creation of a second list just to build up an array seems rather pointless.  But by borrowing some ideas from JP, we can make this a lot easier.

    Using LINQ

    We can already see the higher order function we need, it's in the name of the mapper!  Instead of "Map", we'll use "Select" to do the transforming.  But since we have the interface, we can create an extension method to do the Map function:

    public static class MapperExtensions
    {
        public static IEnumerable<TOutput> MapAll<TInput, TOutput>(this IMapper<TInput, TOutput> mapper, 
            IEnumerable<TInput> input)
        {
            return input.Select(x => mapper.Map(x));
        }
    }
    

    This new MapAll function is the functional programming Map function, where it takes an input list and returns a new IEnumerable with the mapped values.  Internally, the Select LINQ query operator will loop through our input, calling the lambda function we passed in (mapper.Map).  This is the exact same operation in our original example, but now our service method now becomes much smaller:

    public SalesOrderSummary[] FindSalesOrdersByMonth(DateTime date)
    {
        // get the sales orders from the repository first
        IEnumerable<SalesOrder> salesOrders = GetSalesOrders();
        var mapper = new SalesOrderSummaryMapper();
    
        return mapper.MapAll(salesOrders).ToArray();
    }
    

    Much nicer, our service method is reduced to just a handful of lines.  The nice thing about this syntax is that it removes all of the unnecessary cruft of a temporary list creation that clouded the intent of this method.

    So any time you find yourself creating a temporary list just to build up some filtered, mapped or reduced values, stop yourself.  There's a higher calling available with functional programming and LINQ.

  • Mike Cohn in town

    Mike Cohn, author of User Stories Applied and Agile Estimation and Planning, is speaking tomorrow night as a part of Agile Austin's Distinguished Speaker Series.  The topic is "Succeeding with Agile: A Guide to Transitioning", with the description:

    Transitioning to an agile development process is unlike most transitions an organization may make. Many transitions begin when a strong, visionary leader plants a stake in the ground and says, “Let’s take our organization there.” Other transitions start with a lone team thinking, “Who cares what management thinks, let’s do this.” The problem in transitioning to agile is that neither of these approaches alone is likely to lead to the long-term sustainable change required.

    In this session we will look at the primary reasons why agile transitions fail and how to overcome them. We will explore what is necessary for self-organizing teams to emerge and thrive within the transitioning organization. We will also the role self-organization must play during the transition itself. This session will include a description of the eight primary ways of getting started—including going All In, Start Small, and Impending Doom—and the advantages of each. You will leave knowing what approach will work best for you as well as what you must and must not do to succeed with agile.

    Transitioning to Agile is a very bumpy ride, as the rise in communication works to surface problems that were previously hidden and swept under the rug.  Mike's books have had a large influence on how I approach software, so I'm pretty excited about Mike coming to town.  The registration fee for non-Agile Austin members is $10, or in my terms, 20 tacos from Jack in the Box.

    For more information, check out the event page:

    http://mikecohnpresentation.eventbrite.com/

    I know it's not Hannah Montana, but it should be a nice event nonetheless.

    Posted May 07 2008, 07:26 AM by bogardj with 3 comment(s)
    Filed under:
  • PabloTV: Eliminating static dependencies screencast

    Nature abhors a vacuum.  It turns out she also abhors static dependencies (I have my sources).  Static dependencies are the modern-day globals, often exposed through classes named "Helper".  I've certainly been guilty of overusing static dependencies in the past, with classes like "LoggingHelper", "SessionHelper", "DBHelper" and so on.

    The problem with static dependencies is that they are opaque to the extreme, enforcing a strong coupling that is impossible to see from users of the class.  To demonstrate techniques for eliminating static dependencies, Ray Houston and I created a short screencast:

    Eliminating static dependencies screencast

    Our screencast demonstrates using TDD along with ideas and techniques laid out in Michael Feathers' Working Effectively with Legacy Code and Joshua Kerievsky's Refactoring to Patterns.  It details how to make safe, responsible changes to an existing legacy codebase, while improving the design by breaking out dependencies to a static class.

    Hope you enjoy it!

  • A pointless exercise

    I caught this last night from Scott Hanselman on Twitter:

    http://www.betterwebapp.com/drupal/?q=screencasts

    It's a side-by-side comparison of the time to create a simple web app for:

    • Ruby
    • Perl
    • ASP.NET
    • Java

    The website compares a few other frameworks to compare which languages and frameworks are the fastest to develop against.  Not that it matters, but ASP.NET came out on top for the simple application profile, while Python/Django came out on top for the three-tier application profile.

    While viewing the screencast, all I could think was "Holy jeebus, is there a more pointless exercise than timing the creation of software?"  Creating software is easy (some would say too easy).  If our problem was "how fast can we whip out software", the issues of today's software developers would have been solved decades ago.

    The problem is that software maintenance dwarfs the cost of software creation, by a factor of at least 3 to 1.  So if we're trying to optimize software development, isn't it the most expensive aspect, maintenance, what we should focus on?  We use ReSharper to optimize responsible code creation (i.e., micro-codegen vs. macro-codegen), but it also helps with responsible code maintenance through automated refactorings.  Many other responsible engineering practices, such as those espoused by XP, aim to reduce the maintenance costs of software development.

    In the end, I could care less how long it takes to slap out some sample application.  In six years of professional development, no one has ever paid me to write an application on the level of what was demonstrated.  Some managers will care how fast you sling code, but the smart ones care about:

    • Can the software you created be easily changed?
    • Can the software you created be easily tested?
    • Can the software you created be easily deployed?
    • Can the software you created be easily diagnosed for bugs?
    • Is the software you created correct?
    • Is the software you created what we actually need?

    I'd love to see those issues in a screencast, but who would want to watch a screencast that lasted for weeks or months?

    Posted May 05 2008, 07:40 AM by bogardj with 1 comment(s)
    Filed under: ,
Copyright Los Techies 2007. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems