in

 

Chad Myers' Blog

Department of Problem Prevention
  • Good Design is not Subjective

    In case you haven’t guessed by my recent flurry of posts, I’ve been engaged in some debates in the past few days about design philosophies and why some designs are “good” and some are “bad.”  I’ve been met with some relativistic arguments that no design is either good or bad, it just succeeds or fails differently, etc (ok, they didn’t really say that, but that was the gist of the argument).  Of course arguments of relativism are always wrong in my book (it’s usually just that we haven’t reached a level of understanding and specificity in the subject matter to determine EXACTLY why something is A or B).

    Well, at least in the subject of design, we actually DO have material and research that points to what constitutes a GOOD design and a BAD design. In fact, it was written over 10 years ago (1996/1997).  Interestingly enough, it rings as true today as it ever did.

    What is Bad Design?

    First, what is a BAD design?  Courtesy of Robert C. Martin from his paper on the “Dependency Inversion Principal” (PDF link, sorry – emphasis mine):

    But there is one set of criteria that I think all engineers will agree with. A piece of software that fulfills its requirements and yet exhibits any or all of the following three
    traits has a bad design.

    1. It is hard to change because every change affects too many other parts of the system. (Rigidity)
    2. When you make a change, unexpected parts of the system break. (Fragility)
    3. It is hard to reuse in another application because it cannot be disentangled from
      the current application. (Immobility)


    Moreover, it would be difficult to demonstrate that a piece of software that exhibits
    none of those traits, i.e. it is flexible, robust, and reusable, and that also fulfills all its
    requirements, has a bad design. Thus, we can use these three traits as a way to unambiguously decide if a design is ‘good’ or ‘bad’.

    Rigidity, Fragility, and Immobility are qualities of a bad design.  These are problems that will rear their head later during future enhancement or maintenance of the software. Each of these qualities has a corresponding negative real-world impact on the ability to enhance or maintain the software going forward.

    Fortunately, there are contradictory and counter-acting practices that result in good traits and qualities of GOOD design.  These include all the good ‘ilities’ like “reversibility'”, “reusability”, “maintainability”, “extensibility”, “portability”, etc.

    But it Works!

    I hear this argument a lot. It goes something like, “who are you to judge my design because it WORKS!”  “Works” ends up being the relative word and the point of debate. We have different definitions of “works” apparently.  For me, “works” is more than just “fulfills its requirements” (see emphasis in the Martin quote above).  A design can fulfill its CURRENT requirements, but fail miserably in its ability to accommodate FUTURE requirements.  How many of you out there write systems that are NEVER touched again once they are deployed to production?  No hands? I thought so.  Maintainability is IMPORTANT and justifies forethought and strong consideration in any design. If not, you’ll end up with a Rigid, Fragile, and Immobile design and you have just stiffed your employer for a lot of money in future maintenance.  We can do better, and we should!

    Conclusion

    Good design is not subjective. It is objective. It exhibits properties of high cohesion and loose coupling. Through these fundamental properties, all the other good “ilities” flow and the bad “ilities” are kept at bay.

    P.S. – those who know me know that I’m not a big fan of the abuse** of TypeMock’s exotic features (ability to mock anything by twiddling bits under the skirt of the CLR).  The reason I’m not a big fan is because people abuse it in order to get around having to learn and use core fundamental design principles and they can easily end up with a design that has one or all three of the bad “ilities”. Particularly they could end up with a bad case of the “Immobility” trait since they likely didn’t follow the Dependency Inversion Principle (since TypeMock allows them to get away without needing it in many cases).

     

    ** Note I said ABUSE. I still maintain that TypeMock is a handy tool in general (it’s a good mocking framework) and extra-handy when you’re in an otherwise unmaintainable situation (i.e. SharePoint development). But it’s special powers can be used to get away with things that are supposed to be difficult in .NET (basic OO design stuff).

    Posted Aug 18 2008, 11:02 PM by chadmyers with 31 comment(s)
    Filed under:
  • Fluent NHibernate - Configuration

    Used NHibernate?  Had to use the XML configuration (hibernate.cfg.xml)?  Remember this?

    <?xml version="1.0" ?>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
        <session-factory>
            <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
            <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
            <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
            <property name="connection.connection_string">Server=(local);Initial Catalog=dbname;User Id=user;Password=********</property>
        </session-factory>
    </hibernate-configuration>

    Or maybe you write code like this:

    IDictionary<string, string> props = new Dictionary<string, string>();
    String connectionString = "Server=server;Database=dbName;User ID=user;Password=passwd";
    props.Add("hibernate.dialect", "NHibernate.Dialect.MySQLDialect");
    props.Add("hibernate.connection.provider", "NHibernate.Connection.DriverConnectionProvider");
    props.Add("hibernate.connection.driver_class", "NHibernate.Driver.MySqlDataDriver");
    props.Add("hibernate.connection.connection_string", connectionString);
    config.AddProperties(props);

     

    What if you could do this, instead?

    MsSqlConfiguration
       .MsSql2005
       .ConnectionString.Is("Server=(local);Database=dbname;uid=user;pwd=password");
       .Configure( nhibConfig );

    Hint: It's already in the FluentNHibernate trunk!

    (At the time of this writing, we have MsSql, SQLite and PostgreSQL. It's easy to add new configs, so we'll be adding support for all the ones that NHibernate supports out of the box in the upcoming weeks).

    -Chad

  • Let’s try it again… testability succinctly

    My last try wasn’t that successful, so I’ll try it again:

    (In-language based) Testability is the residue of a good design.*

    Better?

    * (This is a slight play on John Milton’s famous quote ‘Luck is the residue of design’)

    Posted Aug 18 2008, 05:22 PM by chadmyers with 1 comment(s)
    Filed under:
  • Fluent NHibernate LiveMeeting Chat – Wednesday 8/20

    Last Wednesday, a few of us had an impromptu LiveMeeting chat to talk about Fluent NHibernate.  I thought it went well enough. It wasn’t scripted so the conversation meandered considerably, but I think everyone got a little out of it.  We decided to try it again, but crank it up a notch and make it more official like with a prescribed time and maybe even (if we’re lucky :) ) a real agenda and something to talk about and demonstrate.

    Details:

    When:  Wednesday, August 20th @ 8:30PM CDT [UTC-05:00]  (9:30PM EDT, 7:30PM MDT, 6:30PM PDT, 2:30AM BST on the 21st)

    Where: Live Meeting. URL, etc below

    Why:  To show what the Fluent NHibernate API is currently, what it may become, and to discuss it

    Who:  Currently, it’s Zachariah Young of the Northwest Arkansas .NET User’s Group and me (Chad Myers).

    How: The final plans aren’t made yet, but it will likely be a quick code walk-through/presentation with commentary then questions and then finally some form of open discussion.

    Please drop a comment here to RSVP if you plan on attending so we can get an idea of head count.  It’s OK if you don’t RSVP, but the presentation won’t be as good because we won’t be expecting as many people.

    To connect, about 30 minutes before the start, navigate to this url:

    https://www.livemeeting.com/cc/usergroups/join

    The Meeting ID is:

    Z63M24

    The Entry Code is:

    B5s%d&zNq

    Here’s a direct link which (should) work:

    https://www.livemeeting.com/cc/usergroups/join?id=Z63M24&role=attend&pw=B5s%25d%26zNq

  • Design and Testability

    There was a rather healthy public discussion and debate going on via Twitter today between Roy Osherove, Ayende Rahien, Colin Jack, me, and several others. Michael Feathers even dropped in at one point which was cool.  This all started when Roy twittered an interesting link to a post by Jacob Proffitt.

    Most of the “debate” seemed to be all of us saying the same thing different ways and violently agreeing, but there were some honest to goodness points of contention.  Ayende has covered this at length, so I’d like to try to cover it as succinctly as possible which may also help matters. One of the big sticking points was the concept of “Design for testability”. I wanted to point out that TDD != “Design for Testability”.  So here goes my shot at trying to explain why TDD is not “Designing for Testability”, succinctly:

    You should design with the goals of loose coupling and high cohesion in mind.  Using TDD is one really great and surefire (though not foolproof) way of getting you there. You can do it without TDD, but it’s much easier to get it wrong. When striving for a loosely coupled, highly cohesive design, using TDD as a method, you will likely need to perform interaction testing at some point. Mock objects and associated frameworks will assist in this effort and language-based mock objects and frameworks (i.e. those that are created using normal means for normal usage) are all you should need in this regard.

    Most of those involved in the debate/discussion will hopefully understand my attempt above (even if they disagree). If I’ve failed in my succinctness, then allow me to elaborate. TDD is not always possible/effective/realistic in all situations. Roy pointed out SharePoint development, which is a great example of this. While you can go through a lot of rigormoral to achieve TDD in this situation, it’s probably going to involve a lot of frustration, inefficiency, and time that could be better spent bang-for-buck-wise.  In these situations, something like TypeMock would be excellent and a worth-while investment. For those not familiar, TypeMock does not use “normal” means to achieve some of it’s functionality. It uses, among other things, the Profiler API in order to create situations not normally available to regular run-of-the-mill C#/VB.NET code.  In this respect, TypeMock is an extremely powerful tool and enables TDD and interaction testing easily against otherwise insurmountable complexity.

    So you see, SharePoint, in this example, is the big problem. It’s a poor design that doesn’t lend itself well to extensibility (and therefore testability) except the type of extensibility it prescribes (which is usually not enough and very frustrating for developers wishing to extend SharePoint). What I’m pushing for is to help developers (including MS developers – especially those on the SharePoint and ASP.NET design teams) understand these complexities and problems so that we won’t need to resort to extraordinary means to write good, tested good against these designs.

    Simply put, I wish for an environment where TypeMock isn’t needed – or rather, where the extraordinary features of TypeMock aren’t needed. Now, don’t get me wrong, I don’t wish ill on Roy or his company. They’re smart people, they’ll come out with some other amazing tool and service that will blow us away and they’ll be doing quite well. Of this, I am quite sure!

    Posted Aug 16 2008, 09:27 PM by chadmyers with 17 comment(s)
    Filed under: ,
  • Dovetail is Hiring Junior- to Mid-level Developer

    *NOTE*: We have already filled this position. Thank you for everyone who submitted resumes!  Keep checking back as we may post more jobs in the future.

    Work for one of the most progressive development shops in the US. This is an opportunity to work with some of the leaders in the .NET/C# space including Jeremy Miller and our recent addition, Joshua Flanagan – both senior designers and architects with tons of experience. We’re building a new software product line using pioneering practices and technologies, such as:

    • Test-driven development
    • Continuous integration
    • Behavior-driven design
    • Domain-driven design
    • HTML, CSS, Javascript
    • ASP .NET MVC
    • C# 3.0, .NET 3.5, Visual Studio 2008
    • SQL 2005
    • NHibernate 2.x
    • LINQ2NHibernate
    • StructureMap
    • WatiN
    • StoryTeller, FIT

     

    Who we’re looking for || Dovetail Software is staffing a new team for an innovative software project. We’re looking for junior- to mid-level software developers with demonstrable C# (preferably .NET 2.0 or later) and HTML/CSS experience (not necessarily ASP.NET, just web development in general). Any experience with test-driven development or automated unit testing in general is a huge plus.  Also, participation in the community (attendance of events, avid blog reader + commenter, or maybe you even have a blog yourself) will put you firmly in the running for this position. We’re looking for people that believe learning and continuous improvement are primary responsibilities of a software developer. We’re hiring motivated people for a terrific opportunity with a team of recognized .NET and agile community leaders.

    Our development methodology || We are an Agile shop (Scrum/XP). We work in short iterations, not long crushing release cycles. We have a collaborative relationship with our customers. We write tests before we write functional code to clarify our design intentions. We keep the build clean. We work in an environment that maximizes communication to minimize the volume of spec documents. We build software that can effectively respond to change. We use open source tools where appropriate, and Microsoft tools where they make sense. We have executive support and visibility all the way up to the owner of the company.

    About Dovetail Software || Serving companies since 1995, Dovetail Software develops CRM products for global 1000 enterprises. Our product, Dovetail CRM, is a comprehensive customer service and support, logistics management, customer self service, and knowledge management suite. Dovetail is a small company with big customers and great benefits for its employees. Our outstanding compensation package includes company-assisted health, dental, and life insurance, matching 401k, and more.

    About Austin || Placing second in the Large Cities Creativity Ranking, Austin is recognized as a city with a thriving music scene, ethnic and cultural diversity, endless outdoor recreations, and a great nightlife. It’s a nationally recognized center for technology innovation—home to 3,200 tech companies with 98,000 employees.

    Email us and tell us why you’d make a great addition to our team: tech-jobs@dovetailsoftware.com

  • Query Objects with Repository Pattern Part 2

    As promised in my previous post, I’m going to make our query object a little more flexible and dynamic.

    First, this is what I really want to be able to do something like this:

    var customers = repo.FindBy(
                    new TopCustomersWithLowDiscountQuery()
                        .IncludePreferred()
                        .BelowDiscountThreshold(3)
                        .WithMoreSalesThan(500)
                        .As_BLOCKED EXPRESSION
    );

    Better yet, maybe even something like this:

    var customers = repo.FindBy(
            new TopCustomersWithLowDiscountQuery()
                .IncludePreferred()
                .BelowDiscountThreshold(3)
                .WithMoreSalesThan(500)
            .AndAlso(
                new DeliquentCustomersQuery()
                    .WithDebtOver(9999))
                
    );

    Strongly typed query objects, completely testable outside of the repository, chain-able together with other like-typed query objects using AndAlso or OrElse.

    Ok, now how do we do it?

    Expression Tree Helper (Naive)

    First, I started with an extension method class to make dealing with some of the Expression<Func<ENTITY, bool>> expressions (which can get old to type) easier.  What I needed was the ability to take two expressions and AndAlso or OrElse them together.  AndAlso (&&) and OrElse (||) are both binary expressions represented by the BinaryExpression class in System.Linq.Expressions.  You can combine two expressions together with any binary expression type by using the Expression.MakeBinary() method.  One problem though is that both Expressions start with a different parameter (i.e. the ‘c’ in (c=>c.AnnualSales > 999)).  So you can’t just join them together because, unfortunately, the Expression Tree compiler will get the ‘c’ parameters jumbled and it won’t work.

    The way I found to deal with this problem is to basically wrap an ‘Invoke()’ expression around the other lambda using the first lambda’s parameter.  In C# parlance, it’s the difference between these two things:

    c => c.AnnualSales > 99 && c.Discount < 4
        -- VS.--
    c => c.AnnualSales > 99 && new Func<Customer, bool>(x=> x.Discount < 4)(c));

    See how the second one actually involves wrapping the other Lambda (.Discount < 4) with a function and then invokes it?  I’m not sure if that’s EXACTLY what goes on when you use Expression.Invoke(), but that’s what I like to tell myself when I’m working with Expression Trees. It also helps to keep me from ending up in the corner in the fetal position drooling and babbling incoherently which is, unfortunately, a frequent occurrence when dealing with Expression Trees.

    You may notice that I put the condition “naive” on this section. This is because my expression tree helper is very naive and doesn’t account for a lot of the crazy things you can do with Expression Trees. This means that you will probably bump against its limitations and have problems. Sorry in advance for this, but I’m stretching the limits of my knowledge here and doing well to write coherently about it. If you have problems, let me know and maybe we can work it out together.

    Anyhow, once you’ve invoked the other lambda, you can join them together with whatever binary expression you want, and then you have to re-wrap them in a Lambda again in order to continue working with it.  Without further ado, here’s my expression helper extension methods:

    public static class ExpressionHelpers
    {
        public static Expression<Func<T, bool>> AndAlso<T>(
            this Expression<Func<T, bool>> left,
            Expression<Func<T, bool>> right)
        {
            return BinaryOnExpressions(left, ExpressionType.AndAlso, right);
        }
    
        public static Expression<Func<T, bool>> OrElse<T>(
            this Expression<Func<T, bool>> left,
            Expression<Func<T, bool>> right)
        {
            return BinaryOnExpressions(left, ExpressionType.OrElse, right);
        }
            
    
        public static Expression<Func<T, bool>> BinaryOnExpressions<T>(
            this Expression<Func<T, bool>> left,
            ExpressionType binaryType,
            Expression<Func<T, bool>> right)
        {
            // Invoke that lambda with my parameter and give me the bool back, KKTHX
            var rightInvoke = Expression.Invoke(right, left.Parameters.Cast<Expression>());
    
            // make a binary expression between the results (i.e. AndAlso(&&), OrElse(||), etc)
            var binExpression = Expression.MakeBinary(binaryType, left.Body, rightInvoke);
    
            // Wrap it in a lambda and send it back
            return Expression.Lambda<Func<T, bool>>(binExpression, left.Parameters);
        }
    }

     

    With that out of the way, we can get on to the less complicated stuff which is chaining all these things together.  The next thing I did was to create a simple abstract base class for my query objects (I’m sure there’s a million better ways to do this, but to get things running, this was the simplest thing that worked for right now).

    Query Base Class

    The query base is quite simple, actually. It just shuffles around the expressions and provides some convenience methods for you to chain them together:

    public abstract class QueryBase<ENTITY>
    {
        private Expression<Func<ENTITY, bool>> _curExpression;
    
        public Expression<Func<ENTITY, bool>> AsBLOCKED EXPRESSION
        {
            return _curExpression;
        }
    
        public Expression<Func<ENTITY, bool>> AndAlso(QueryBase<ENTITY> otherQuery)
        {
            AsBLOCKED EXPRESSION.AndAlso(otherQuery.AsBLOCKED EXPRESSION;
        }
    
        public Expression<Func<ENTITY, bool>> OrElse(QueryBase<ENTITY> otherQuery)
        {
            AsBLOCKED EXPRESSION.OrElse(otherQuery.AsBLOCKED EXPRESSION;
        }
    
        protected void addCriteria(Expression<Func<ENTITY, bool>> nextExpression)
        {
            _curExpression = (_curExpression == null)
                                ? nextExpression
                                : _curExpression.AndAlso(nextExpression);
        }
    }

    You can AND and OR two queries together (must be of the same type, for now).  Sub-classes can add their own expressions in a nice, easy-to-use lambda expression style.

    Query Implementation

    And now, on to one of the actual query classes. Remember our ridiculously named and implemented TopCustomersWithLowDiscountQuery from my last post?  Here it is in its more simplified form complete with Fluent-API bonus material:

    public class TopCustomersWithLowDiscountQuery : QueryBase<Customer>
    {
        public TopCustomersWithLowDiscountQuery IncludePreferred()
        {
            addCriteria(c => c.Preferred);
            return this;
        }
    
        public TopCustomersWithLowDiscountQuery BelowDiscountThreshold(decimal discountThresh)
        {
            addCriteria(c => c.Discount < discountThresh);
            return this;
        }
    
        public TopCustomersWithLowDiscountQuery WithMoreSalesThan(int salesThresh)
        {
            addCriteria(c => c.AnnualSales > salesThresh);
            return this;
        }
    }

    To use it, just chain the methods together. Consider this test case:

    [Test]
    public void low_discount_high_sales_customers_should_be_selected()
    {
        _query = new TopCustomersWithLowDiscountQuery()
            .BelowDiscountThreshold(3)
            .WithMoreSalesThan(500);
    
        var high = 15m;
        var low = 1m;
    
        _customers.AddRange(new[]
        {
            new Customer {Id = 1, Discount = low, AnnualSales = 200},
            new Customer {Id = 2, Discount = low, AnnualSales = 800},
            new Customer {Id = 3, Discount = high, AnnualSales = 1000}
        });
    
        Results.Count().ShouldEqual(1);
        Results.ElementAt(0).Id.ShouldEqual(2);
    }

     

    If you want to chain them together, just use the AndAlso or OrElse methods.  Consider this other test case which uses OrElse:

    [Test]
    public void preferred_customers_that_are_also_bad()
    {
        _query = new TopCustomersWithLowDiscountQuery()
            .IncludePreferred();
    
        var otherQuery = new DeliquentCustomersQuery()
            .WithPendingLitigation()
            .WithDebtOver(999);
    
        _customers.AddRange(new[]
        {
            new Customer {Id = 1, Preferred = true, PendingLitigation = false, OutstandingDebts = 4000},
            new Customer {Id = 2, Preferred = false},
            new Customer {Id = 3, Preferred = false,  PendingLitigation = true, OutstandingDebts = 4000}
        });
    
        var results = _customers
            .AsQueryable()
            .Where(_query.OrElse(otherQuery));
    
        results.Count().ShouldEqual(2);
        results.ElementAt(0).Id.ShouldEqual(1);
        results.ElementAt(1).Id.ShouldEqual(3);
    }
    Posted Aug 02 2008, 01:29 AM by chadmyers with 18 comment(s)
    Filed under:
  • Query Objects with the Repository Pattern

    Nate Kohari (whose primate brain is far too small to comprehend this post [inside joke, he’s actually really sharp]) was asking on Twitter today about how to structure his repositories: Per aggregate root, Per entity, or just one repository for everything?

    The two suggestions that rose to the top were the per-aggregate and one repository approaches. Jeremy and I use a the one repository approach at work and it’s working well for us so far.  The was one compelling argument for the per-aggregate repository and that is that you could encapsulate your aggregate-specific queries inside your aggregate-specific repositories.

    Thinking about this a little more, I felt it had a little smell to it, namely the potential for business logic (also known as ‘where’ clauses) to creep into the repository which would be bad. Perhaps a better alternative would be to encapsulate the specific logic of a given query into an object. You could then have this object produce something that the repository could (blindly, decoupled) use to query on.

    This approach allows you to maintain the one repository approach, yet still have encapsulated domain-specific queries. Plus, you can test your queries independently of the repository which is a huge benefit.

    Creating and Passing Around Expression Trees

    What might the query object produce that the repository could blindly use?  In the .NET 3.5 world, you could use expression trees!  These come in quite handy and play well with LINQ-style (IQueryable) behavior of Linq2NHibernate, Linq2Objects, and Linq2JustAboutAnythingThatInvolvesAListOfThings.

    Producing an expression tree is actually quite simple:  Have a method or property that returns Expression<Func<T,bool>>. Yep. That’s it. We can all go home now.  In case you actually wanted to see some code, here’s a simple, extremely naive example of what I mean. Let’s say we wanted to find all our customers that have significant sales with our company, but whose discount is really low (for some reason).  We’d like to find these customers and give them a better discount since they do so much business with us. Your query probably (wouldn’t) look something like this:

    public class TopCustomersWithLowDiscountQuery
    {
        public bool IncludePreferred { get; set; }
        public decimal DiscountThreshold { get; set; }
        public int SalesThreshold { get; set; }
    
        public Expression<Func<Customer, bool>> AsBLOCKED EXPRESSION
        {
            return (c =>
                    c.Preferred == IncludePreferred
                    && c.Discount < DiscountThreshold
                    && c.AnnualSales > SalesThreshold);
        }
    }

    Using this query object, we can still get all the benefits of delayed execution that LINQ/IQueryable provides us without forcing us to sprinkle little surprises of business logic everywhere in LINQ queries.

    Using the Expression Tree to Query

    To actually use the expression tree, you can call the Where() method on any IEnumerable<T> or IQueryable<T>.  Consider this silly/contrived example:

    var query = new TopCustomersWithLowDiscountQuery
    {
        IncludePreferred = true,
        DiscountThreshold = 3,
        SalesThreshold = 100000
    };
    
    var customerList = new List<Customer>
    {
        new Customer {Id = 1, Preferred = true},
        new Customer {Id = 2, Preferred = false},
        new Customer {Id = 3, Preferred = true}
    };
    
    var filteredCustomers = 
        customerList
            .AsQueryable()
            .Where(query.AsBLOCKED EXPRESSION;

     

    Once GetEnumerator() is called on filteredCustomers, the magic happens and you’ll end up with an IEnumerable<T> that has only 2 elements in id (ID=1, and ID=3).

    Full Code Example

    Here’s the full code of the test fixture I was using for these examples. Yes, I know it’s not very realistic and there are lots of potential problems with the logic in the query object, but the point was to illustrate how you might go about encapsulating LINQ where clauses, so please go easy on me :)

    [TestFixture]
        public class TopCustomersWithLowDiscountQueryTester
        {
            [Test]
            public void preferred_customers_should_be_selected_when_IncludePreferred_is_true()
            {
                _customers.AddRange(new[]
                {
                    new Customer {Id = 1, Preferred = true},
                    new Customer {Id = 2, Preferred = false},
                    new Customer {Id = 3, Preferred = true}
                });
    
                Results.Count().ShouldEqual(2);
                Results.ElementAt(0).Id.ShouldEqual(1);
                Results.ElementAt(1).Id.ShouldEqual(3);
            }
    
            [Test]
            public void high_discount_customers_should_not_be_selected()
            {
                _query.IncludePreferred = false;
    
                var high = 15m;
                var low = 1m;
    
                _customers.AddRange(new[]
                {
                    new Customer {Id = 1, Discount = high},
                    new Customer {Id = 2, Discount = low},
                    new Customer {Id = 3, Discount = high}
                });
    
                Results.Count().ShouldEqual(1);
                Results.ElementAt(0).Id.ShouldEqual(2);
            }
    
            [SetUp]
            public void SetUp()
            {
                _query = new TopCustomersWithLowDiscountQuery
                {
                    IncludePreferred = true,
                    DiscountThreshold = 3,
                    SalesThreshold = 100000
                };
    
                _customers = new List<Customer>();
                _resultsCached = null;
            }
    
            private TopCustomersWithLowDiscountQuery _query;
            private List<Customer> _customers;
            private IEnumerable<Customer> _resultsCached;
    
            public IEnumerable<Customer> Results
            {
                get { return _resultsCached ?? _customers.AsQueryable().Where(_query.AsBLOCKED EXPRESSION; }
            }
        }
    
        public static class SpecificationExtensions
        {
            public static void ShouldEqual(this object actual, object expected)
            {
                Assert.AreEqual(actual, expected);
            }
        }

     

    Coming up…

    Stay tuned: I’m going to do a follow-on post on how you can make the query object code a little more elegant, as well as chain them together with AndAlso and OrElse expressions.

  • StuctureMap: Advanced-level Usage Scenarios (Part 1: Type/Convention Scanners)

    I’ll start with my strong hand on the advanced StructureMap-foo and go straight to the type scanners (a.k.a. convention scanners).  Thankfully, there was a thread on the StructureMap Users mailing list with just the kind of problem these things solve. I’ll use that problem as the strawman for this post.

    The Problem

    Let’s say you had an IRepository<T> interface implemented by an abstract base class (RepositoryBase<T>) which, in turn, is implemented by many classes – one for each entity.  Let’s say your implementations looked something like this:

    public interface IRepository<T>
    {
        // intersting stuff here    
    }
    
    public abstract class RepositoryBase<T> : IRepository<T>
    {
        // interesting abstract base stuff here
    }
    
    public class UserRepository : RepositoryBase<User>
    {
            // interesting abstract base stuff here
    }
    
    // ... a bunch more of these CustomerRepository, SaleRepository, etc

    And you you may add more in the future and you’d rather not have to register them all individually in StructureMap like this:

    // You don't have to do this!
    StructureMapConfiguration
        .ForRequestedType<IRepositor<User>>.TheDefaultIsConcreteType<UserRepository>()
        .ForRequestedType<IRepositor<Customer>>.TheDefaultIsConcreteType<CustomerRepository>()
        .ForRequestedType<IRepositor<Sale>>.TheDefaultIsConcreteType<SaleRepository>();

     

    What would be nice is if StructureMap could automatically figure my convention out. Well, unfortunately it won’t do that. BUT you can give it enough of a hint so that it CAN do it using your own ITypeScanner implementation. ITypeScanner has one method on it: Process(Type, Registry).  StructureMap will call Process() for each Type it finds when scanning (using ScanAssemblies).  Your scanner can, if it wants, add things to the container (through the ‘Registry’ parameter).  This allows you to do all sorts of cool things like automatically find any types Foo which implement an interface named IFoo (or Bar/IBar, Something/ISomething, etc) and register them for you.  In fact, this last example is done for you using StructureMap.Graph.DefaultConventionScanner. Here, let me show you:

    ScanAssemblies().IncludeTheCallingAssembly()
        .IncludeTheCallingAssembly()
        .With<DefaultConventionScanner>()

     

    Implementing our Repository Convention ITypeScanner

    First, create a class that implements ITypeScanner. Let’s call it RepositoryConvention.

    The next thing we’ll need is a method that will, given a type, see if it’s the type of generic type we’re looking for (i.e. RepositoryBase<T>), and return what the T parameter is (i.e. <User>). With this, we can register an IRepository<User> in StructureMap for that class (UserRepository, for example). It might look something like this:

    private static Type GetGenericParamFor(Type typeToInspect, Type genericType)
    {
        var baseType = typeToInspect.BaseType;
        if (baseType != null
            && baseType.IsGenericType
            && baseType.GetGenericTypeDefinition().Equals(genericType))
        {
            return baseType.GetGenericArguments()[0];
        }
    
        return null;
    }

    This will take a given type (i.e. UserRepository) and check it’s base type (i.e. RepositoryBase<User>) to see if it’s generic and if it’s the generic type we’re looking for. If so, it’ll return the “User” portion of RepositorBase<User>, for example.

    Now, our process method looks something like:

    public void Process(Type type, Registry registry)
    {
        Type entityType = GetGenericParamFor(type, typeof(RepositoryBase<>));
    
        if (entityType != null)
        {
            var genType = typeof(IRepository<>).MakeGenericType(entityType);
            registry.ForRequestedType(genType).AddInstance(new ConfiguredInstance(type));
        }
    }

    We try to get the entityType (i.e. User). If present, then we create a new specific type from the generic IRepository<T> and register it. In our UserRepository case, it’ll register IRepository<User> with the default concrete type of UserRepository. Our whole class now looks like this:

    public class RepositoryConvention : ITypeScanner
    {
        public void Process(Type type, Registry registry)
        {
            Type entityType = GetGenericParamFor(type, typeof(RepositoryBase<>));
    
            if (entityType != null)
            {
                var genType = typeof(IRepository<>).MakeGenericType(entityType);
                registry.ForRequestedType(genType).AddInstance(new ConfiguredInstance(type));
            }
        }
    
        private static Type GetGenericParamFor(Type typeToInspect, Type genericType)
        {
            var baseType = typeToInspect.BaseType;
            if (baseType != null
                && baseType.IsGenericType
                && baseType.GetGenericTypeDefinition().Equals(genericType))
            {
                return baseType.GetGenericArguments()[0];
            }
    
            return null;
        }
    }

    Now, we need to let StructureMap know about it…

    Configuring StructureMap with the new Scanner

    Now, somewhere in your bootstrapping/startup routines for your app, add the With() call to your ScanAssemblies configuration. It should end up looking like this:

    StructureMapConfiguration
       .ScanAssemblies()
       .IncludeTheCallingAssembly()
        // maybe other assemblies, too?
       .With(new RepositoryConvention());  // add our convention for wiring up the repos

    As StructureMap mines through all the types in your assemblies, it’ll pass them to your Process() method where you can evaluate whether they meet your Repository convention and register them accordingly.

    Using the Repository

    Finally, to grab one of your newly configured repositories, you can simple make a normal ObjectFactory GetInstance call:

    var userRepo = ObjectFactory.GetInstance<IRepository<User>>();

    Also, it’ll work with for normal constructor injection scenarios. For example:

    public class SomeService
    {
        private readonly IRepository<User> _userRepo;
    
        public SomeService(IRepository<User> userRepo)
        {
            _userRepo = userRepo;
        }
    }

    What else can you do?

    I hope as you come up with clever uses for this convention technique you let us know about them!  As a teaser, here’s something Jeremy and I are doing:

    public class ControllerConvention : TypeRules, ITypeScanner
    {
        public void Process(Type type, Registry registry)
        {
            if (CanBeCast(typeof (IController), type))
            {
                string name = type.Name.Replace("Controller", "").ToLower();
                registry.AddInstanceOf(typeof (IController), new ConfiguredInstance(type).WithName(name));
            }
        }
    }

    See if you can guess what that’s for… ;)

  • StructureMap: Interlude

    I'm trying to wrap up the "StructureMap: Advanced Scenarios Usage" post. In the meantime, I wanted to make you aware of a few things:

    • I just updated my StructureMap: Basic Scenario Usage post with a correction. I was mistaken about being able to set properties on configured objects. Currently, you cannot configure properties on configured objects unless the property has the [SetterProperty] attribute defined.  This was on purpose since there is a good argument that property injection is 'bad' (i.e. leads to problems later, can complicate configuration and testing, etc).  There are, however, scenarios where property injection is acceptable so being able to configure properties without using the attribute is being seriously considered for the StructureMap 2.5 release.
    • Derik Whitaker posted about how to use StructureMap in an MSTest situation to work around some of MSTest's quirks. He used StructureMap's ability to configure itself through XML in your web.config/app.config file rather than having a separate XML file. Or you could, of course, save half your time and tons of complexity and just use NUnit/MBUnit/XUnit and not deal with the hassle. But it's good for those people required to use MSTest to still be able to take advantage of StructureMap.
    • You should know that Joshua Flanagan was the one who contributed that feature (the app.config configuration stuff) to StructureMap which is useful for a variety of reasons -- not just the MSTest reason.  The reason you should know of him is because...
    • The same Joshua just posted a great post on how to get started from the most basic level with StructureMap. It's a "Hello World" type app, but shows off some of the ways StructureMap works. Of course it's overdone as a Hello World app, but that wasn't the point.  The point is to show how to get started with StructureMap and I think it does a really good job at that.
  • StructureMap: Medium-level Usage Scenarios

    This is a follow-on to my previous post about basic usage scenarios for StructureMap.  This post will focus on slightly more advanced usage scenarios and how StructureMap handles them.  For those playing the home game, I’m still working on the ‘Exploring ShadeTree’ series, but it’s hit a small roadblock because there are some design changes pending on the NHibernate stuff I was going to cover. Please bear with me.  Anyhow, in the meantime, I hope you find these StructureMap guides helpful.

    Auto-wiring Factory

    I have many objects I wish to manage who have dependencies upon each other. Managing the construction and assembly of these objects is complicated and tedious. When I request an IFoo, I want to get back an instance of Foo with all its dependencies satisfied.

    Let's assume you have the IFoo/Foo combination, in addition to IBar/Bar, and IBaz/Baz.   Let's also say that Foo has a dependency on both IBar and IBaz.  The current recommended way of handling this situation is to define a constructor for Foo() that receives an instance of IBar and IBaz.

    Consider this type structure:

    public interface IBar{}
    public class Bar : IBar{}
    
    public interface IBaz{}
    public class Baz : IBaz{}
    
    public interface IFoo{}
    
    public class Foo : IFoo
    {
        public Foo( IBar bar, IBaz baz )
        {
        }
    }

    The StructureMap configuration for this structure would look like this:

    StructureMapConfiguration
        .ForRequestedType<IBar>().TheDefaultIsConcreteType<Bar>();
    
    StructureMapConfiguration
        .ForRequestedType<IBaz>().TheDefaultIsConcreteType<Baz>();
    
    StructureMapConfiguration
        .ForRequestedType<IFoo>().TheDefaultIsConcreteType<Foo>();

     

    And then, to get a Foo instance with all its dependencies satisfied, simply use ObjectFactory.GetInstance like normal:

    IFoo fooInstance = ObjectFactory.GetInstance<IFoo>();

     

    Note that no where did you have to explain to StructureMap that Foo was dependent upon Bar or Baz. StructureMap figured it out automatically!  This concept is known as "autowiring".  By default, StructureMap will attempt to satisfy as many dependencies as it can.  It will attempt to use the 'greediest' constructor (the one with the most parameters).  If your class has two constructors, one has just IBar and the other has IBar and IBaz, StructureMap will try to use the IBar and IBaz constructor.

    Isolated Configuration (Registration of Dependencies)

    I have many objects in many assemblies (some of which may not be known at compile time). Or, I don't like having every single object in my StructureMap configuration defined in my startup routine. Is there a way that each unit of deployment can specify it’s own object dependency registration?

    So in our project at work, we have a few assemblies that have varying concerns such as Web (our ASP.NET MVC project) and Core (pretty much everything else).  Within Core, we have several areas of concern such as Domain model, Persistence, Web (everything related to Web applications in general – stuff we can reuse on other web projects).  Each of these areas of concern has a class that derives from Registry. No, this has nothing to do with the Windows Registry, this is in the context of ‘object dependency registration.’  You can create a class which derives from StructureMap.Configuration.DSL.Registry and override the configure() method.  In this method, you should register the objects that are “local” to the Registry class. For example, your ‘WebRegistry’ class would register all the controllers, any HttpContext abstractions, and things like that.

    Another, perhaps better, example case for this might be a composite UI/SmartClient type application (think CAB, Prism, etc) where entire portions of the application are loaded at runtime from external assemblies. It’s actually impossible for the central application startup code to know all the components that will be loaded into the system. In this case, Registries really shine.

    Consider this contrived example of what a PersistenceRegistry class might look like:

    public class PersistenceRegistry : Registry
    {
        protected override void configure()
        {
            ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();
            ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>();
            ForRequestedType<ISecurityDataService>().TheDefaultIsConcreteType<SecurityDataService>();
        }
    }

    Notice how it has only the stuff related to persistence and nothing about controllers or anything like that? 

    In order for these Registries to take effect, you must let StructureMap know of their existence. One way is to tell it implicitly using the AddRegistry method, like so:

    StructureMapConfiguration.AddRegistry(new PersistenceRegistry());

    Auto-discovery of Configuration

    I have several registries including ones that I don’t know about at compile time. It would be nice if these could be auto-discovered.

    Another way in which to invoke StructureMap Registries, which also happens to be the the preferred method of doing so, is to tell StructureMap to scan through the assemblies you tell it to scan through (including the current one, if you tell it to do so). StructureMap will automatically recognize types deriving from Registry and invoke their configure() method.  There are two primary use cases for this behavior: 1.) You know all the assemblies at compile time and 2.) You do not know all the assemblies at compile time.  For the first case, consider the following example:

    StructureMapConfiguration
        .ScanAssemblies()
        .IncludeTheCallingAssembly()
        .IncludeAssemblyContainingType<CoreRegistry>()
        .IncludeAssemblyContainingType<PersistenceRegistry>()
        .IncludeAssemblyContainingType<WebSharedRegistry>()
        .IncludeAssemblyContainingType<OurWebApplicationRegistry>();

    As you can see here, we’re explicitly telling StructureMap to load the current assembly, plus our contrived “Core”, “Persistence”, “WebShared”, and “OurWebApplication” assemblies which each have their own Registry implementations.  Note that if it just so happened that TheCallingAssembly was also OurWebApplicationRegistry’s assembly, StructureMap would handle that gracefully and would not result in duplicate registrations.

    As for the other case -- the dynamically-loading-assemblies case – you’ll just need to call ScanAssemblies().IncludeTheCallingAssembly() from the initialization/startup/bootstrap method of your plugin.  For example, assuming you’re using some sort of SmartClient/Composite UI application, when you load in a new module, you’re likely going to have some sort of entry point into the module (i.e. a well known IModule interface that some class implements that has an Initialize() method on it of some sort).  Put your ScanAssemblies().IncludeTheCallingAssembly() call in there or have it called by your Initialize() method.  Your module/plug-in’s Registry implementation will know all about the dependencies of your module and when you inform StructureMap of this, the module and all its dependencies will be loaded into the container and your module will be ready to go.

    Profiles, Alternate Configurations

    Certain objects I’ve defined in my container are not appropriate in all circumstances. I would like to have one concrete instance returned when my application is running in Mode A and a different instance returned when my application is running Mode B.

    A common scenario we use at work is “Live” and “Stubbed” where live usually means “connected to the database and external services” and “stubbed” means “it’s not connected to anything outside the application.”  This is, of course, useful for integration testing and for quick smoke tests, etc where full connectivity might not be required. Another example might be the “Google Map API” or “Yahoo Map API” profiles where some different services with different underlying implementations may be warranted, etc.

    First, declare your dependencies like normal. Then, create a new profile and declare the differences. New profiles will gain all the configuration of the default/unnamed profile, so you only need to define what is different.  Remember our PersistenceRegistry up above?  He’s an example of how it might change when the concept of profiles are introduced:

    public class PersistenceRegistry : Registry
    {
        protected override void configure()
        {
            ForRequestedType<IValidator>().TheDefaultIsConcreteType<Validator>();
            ForRequestedType<IRepository>().TheDefaultIsConcreteType<Repository>();
            ForRequestedType<ISecurityDataService>().TheDefaultIsConcreteType<SecurityDataService>();
    
            CreateProfile("Stubbed")
                .For<IRepository>().UseConcreteType<InMemoryRepository>()
                .For<ISecurityDataService>().UseConcreteType<StubSecurityDataService>();
        }
    }

    Note the ‘CreateProfile’ call.  When StructureMap’s current profile changes to “Stubbed”, requests for IRepository will receive an InMemoryRepository instead of a normal Repository object.

    In order to use this profile, you can do a number of things (this list is not comprehensive, I’m sure I’m missing something else): 1.) Call TheDefaultProfileIs(“YourProfileName”), 2.) Drop a StructureMap.Config file in your bin folder or web root.

    #1 is easy, somewhere in your startup code, when you’ve determined (somehow) that you need to load a specific profile, you can simply call StructureMapConfiguration.TheDefaultProfileIs(“SomeOtherProfile”).

    #2 is also pretty easy. When we want to run in ‘stubbed’ mode, we simply drop a mostly-empty StructureMap.config file into our web root (see example below). When we want to run ‘live’ again, we remove the file. Pretty easy, huh?  Here’s what our stubbed file looks like:

    <StructureMap MementoStyle="Attribute" DefaultProfile="Stubbed">
    </StructureMap>

    Conclusion

    That’s a good chunk of stuff for right now, there may be a few other medium scenarios that aren’t coming to mind right now. Please feel free to suggest some and I’ll look into it.

    In the next post, I’m going to go into some more advanced scenarios such as convention scanners, more manual/fine-grained object construction, construction-via-lambda, direct object container injection, and possibly a few others.

  • StructureMap: Basic Scenario Usage

    First, I'm going to assume that you are somewhat already familiar with the concepts of Dependency Injection and what, in general, an Inversion of Control Container is for. If not, you may find these links helpful:

     

    I'm also going to assume that you know what I'm talking about when I say "StructureMap".  If not, then you should check out this link:

     

    If I've lost you with any of these assumptions, please leave a comment and I'll step back and go into these some more for you!

    Most Common Usages

    I'm going to cover three of the more common usage scenarios and how you accomplish these with the upcoming StructureMap 2.5.

    Simple Factory

    I have an interface IFoo with a concrete implementation Foo. When IFoo is requested, new up and return a Foo.

    First, somewhere in the startup code area of your application, register the two types with the container, like so:

    StructureMapConfiguration
        .ForRequestedType<IFoo>()
        .TheDefaultIsConcreteType<Foo>();

    Next, to retrieve the instance elsewhere in your code, use the ObjectFactory class in StructureMap:

    // fooInstance is actually of type Foo
    IFoo fooInstance = ObjectFactory.GetInstance<IFoo>();

     

    Object Lifetime Manager

    I have a session-type object I need kept alive for the entire thread or ASP.NET request.  When IFoo is requested, return me a Foo instance specific to this ASP.NET request or thread

    StructureMap can create an instance of an object for you and manage it's life time according to the life of the current Thread or, in an ASP.NET scenario, the life of the current HTTP request.  This is useful for caching things like database connection sessions or user credentials, etc.

    First, when you define your object in your startup code, add the CacheBy() option:

    StructureMapConfiguration
        .ForRequestedType<IFoo>()
        .TheDefaultIsConcreteType<Foo>()
        .CacheBy(InstanceScope.HttpContext);

    You can also use InstanceScope.ThreadLocal for non-ASP.NET multithreaded scenarios, InstanceScope.Singleton which means the object will live for the entire life of your AppDomain, and InstanceScope.Hybrid which will choose HttpContext if available, otherwise it'll revert to ThreadLocal. Hybrid is particularly handy in a unit testing scenario where your tests will automatically adapt to either a live ASP.NET scenario or a test threading scenario.

    Then, request your object just like normal:

    IFoo fooInstance = ObjectFactory.GetInstance<IFoo>();

    If you've called GetInstance<IFoo> more than once in that same ASP.NET request, you'll get the same Foo instance.  If there are two requests executing simultaneously on your web server, they'll each get their own Foo instance.

     

    Object Assembler

    I have an object that needs to have a value set from the application configuration on startup. When IFoo is requested, new up a Foo, set it's NumberOfChickens property from the AppSettings/NumChickens setting in my app.config and return me the instance.

    UPDATE 7/26/2008:  My apologies -- at the time of this post and updating, StructureMap does not currently set property values unless they have the [SetterProperty] attribute.  The 'WithProperty' and 'SetProperty' methods are misleading as they apply normally to CONSTRUCTOR parameters by that name OR properties with the [SetterProperty] attribute placed upon them.  There have been several requests for this in the past and there is likelihood the ability to set properties without requiring attributes will be added to the final StructureMap 2.5 release (currently version is 2.4.9).

    Like the previous examples, define your object in your startup code, but change it slightly to have StructureMap automatically take care of getting the property for you:

    StructureMapConfiguration
        .ForRequestedType<IFoo>()
        .TheDefaultIs(
            new ConfiguredInstance()
                .UsingConcreteType<Foo>()
                .WithProperty("NumberOfChickens")
                .EqualToAppSetting("NumChickens")
        );

    Just like the others, the business end is still the same:

    IFoo fooInstance = ObjectFactory.GetInstance<IFoo>();
  • Project anti-pattern: Many projects in a Visual Studio Solution File

    I've been hearing from several colleagues about how their Visual Studio solution files have many (i.e. more than 10, and usually more than 30 -- in one case, more than 100!).  So far, none of them have been able to give me any good explanation for why this is and most of them hate it but they can't change it because their architect/lead/whatever won't let them.

    I'm hoping that by getting the discussion going on this in the greater community, we can try to discourage everyone from having lots of projects in a solution. 

    Why are lots of projects in a single solution not good?

    Aside from some of the more obvious arguments about performance, runtime optimization, PDB and assembly size, etc, etc, etc -- actually, wait. These are obvious, right? Anyone who's ever loaded a VS solution file with more than 20 projects should know exactly what I'm talking about.  And if you've made the mistake of kicking off a build in Visual Studio with this solution, you know that you're in for a 1-5 minute sit-on-your-hands party.  And also -- and I could be wrong about this, but it was true as of .NET 2.0 -- the JIT cannot optimize code across assembly boundaries (or at least it can't do ALL its optimizations).  Then there's the inherent overhead of each DLL file and assembly metadata being loaded for each assembly, not to mention the extra overhead of having so many PDB/symbols loaded in Debug mode, etc, etc, etc.  If you need more proof of the performance problems caused by lots of assemblies, let me know and we'll go deep. I'm hoping that these facts are well established in the wide, wide world of .NET.

    Ok, so hopefully we're past the obvious arguments, let's get back to some of the more subtle ones.  Why do you need so many assemblies? Is it namespace control? Why not put them in one big assembly and use namespaces there?  Is it Strong Naming? Ok, I'll give you that one, strong naming does throw a wrench in things sometimes, but I'd still challenge whether you need 30+ assemblies in your solution just due to strong naming.  Is it licensing? Security?  All of these problems have a better solution that usually doesn't require more assemblies.

    One common argument I've heard is 'dependency' management. That is, I don't want my XYZ.Foo assembly to reference System.Web or something like that. My counter to this is: Why not? What does it matter? It's usually an aesthetic argument that comes back and has little to do in the way of any real merit from a business value perspective.  In fact, I can usually counter back with arguments that more business value is gained by having things easier to use and package and not worrying about dependencies for dependency's sake.  System.Web is in the GAC just as much as System or mscorlib are. You're not saving yourself any problems by having an assembly that has references to all of those.

    Another argument is that I don't want my different 'layers' all in the same assembly. Why not, I ask?  Sometimes there's a valid argument here because you need to deploy these things separately to separate physical layers. Ok, I'll grant you that one, but remember, we're talking 3-4 assemblies here, TOPS. If you're over 20, something is probably seriously wrong. It's a smell, not a sure sign of fire, so your mileage may vary here, but 20 is definitely a line that I would try very hard not to cross. In fact, 10 is probably pushing it.

    What are some exceptions when consolidating assemblies?

    Utility/console application projects. Unit test projects. Integration/longer-running test projects might do well to be in their separate project.  Interface assemblies for remoting/serialization/integration purposes. Plug-in/frequently changing assemblies, resource assemblies, etc.

    In the case of utility/console application assemblies and things like resource or satellite assemblies, you might consider a separate solution for these since they are likely not built or used as often as the main-line code.  You can have multiple SLN files reference a single project, so you can mix and max your SLN files. Be careful though, as the management of these things can get out of hand, so make sure you always have a core SLN file that you trust as the definitive source for what 'works' in your project.

    Also, consider an automated build and test process (NAnt, Rake, Bake, etc) that can independently build and verify the fitness of the build after tests and such so that you remain honest.

    Posted Jul 15 2008, 08:17 PM by chadmyers with 35 comment(s)
    Filed under:
  • StructureMap Users mailing list set up

    In preparation for the upcoming 2.5 release of StructureMap, and since I can't stand SourceForge's mailing list and forum capabilities, I set up a mailing list via Google Groups for users of StructureMap to discuss usage, give and receive support, etc.

    We'd like to start moving all support and discussion to the mailing list (instead of the SourceForge forums).

    Anyone can subscribe and post to the mailing list via email or online from this link:
    http://groups.google.com/group/structuremap-users


    You can also subscribe or unsubscribe via email at the following address:
    structuremap-users@googlegroups.com


    You can track the discussion via RSS using this URL:
    http://groups.google.com/group/structuremap-users/feeds

     

    Developer Mailing List Set Up, Too!

    http://groups.google.com/group/structuremap-devel


    You can also subscribe or unsubscribe via email at the following address: 
    structuremap-devel@googlegroups.com


    You can track the discussion via RSS using this URL: 
    http://groups.google.com/group/structuremap-devel/feeds

  • Exploring ShadeTree Features, Part 2: Cache<KEY, VALUE>

    Or, as I like to call it: "That stupid dictionary thing we've all written a thousand times but were too lazy to component-ize for reuse"

    How many times have you written code like this in your C# 2.0-and-later life?

    Foo foo = null;
    
    if( fooCache.TryGetValue(key, out foo))
    {
        foo = new Foo();
        fooCache.Add(foo.Key, foo);
    }
    
    return foo

    Well, no more!  Enter ShadeTree.Core.Cache!

    Nifty features:

    1. Automatic cache miss value creation: When you attempt to get an item from the cache that's not there, if configured to do so, it'll new one up for you, add it, and return it.
    2. Quiet Add: Call the Store method to add an item if it's not already added (otherwise, it'll do nothing)
    3. Quiet Remove: Remove won't throw an error if the item isn't in the Cache
    4. Each(): Handy lambda-friendly version of 'for each'
    5. Exists(): Handy lambda-friendly version of TryGetValue

    Cache Miss Handling Example

    This one I particularly like, especially when you need something like this: Dictionary<string, IList<Foo>>.

    Consider this example: We want to have a Cache<string, IList<Foo>>.  We want to add a new key "Blah" and add a new Foo to it's list.

    With Dictionary<T,U>, you have to do something like:

    Dictionary<string, IList<Foo>> dict = new Dictionary<string, IList<Foo>>();
    
    IList<Foo> fooList = null;
    
    if( ! dict.ContainsKey("Blah") )
    {
        fooList = new List<Foo>();
        dict.Add("Blah", fooList);
    }
    
    fooList.Add(new Foo());

    But with Cache, it's much simpler:

    Cache<string, IList<Foo>> cache = new Cache<string, IList<Foo>>(k => new List<Foo>());
    cache.Get("Blah").Add(new Foo());

    The trick is that little lambda expression (k => new List<Foo>()).  When the call to Get("Blah") fails to find anything in the underlying dictionary, it'll add a new entry to the dictionary with key "Blah" and the result of that lambda expression (i.e. a new List<Foo>).

More Posts Next page »
Copyright Los Techies 2007. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems