CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff
  • A Train of Thought – QCon San Francisco 2008

    I’ve been at QCon San Francisco most of the week, and I think I can say that content wise, it’s the best “eyes forward” conference I’ve ever attended.  I’m finished with all my speaking and relatively satisfied with how it went.  All the talks were filmed and will appear on InfoQ.com at some point.

    As always, everybody I talk to is working on a more interesting project than I am, but that’s just a case of the grass always being greener on the other side of the hill.  I don’t have much at the minute, but here’s a start on a wrapup.  I’ll catch up on StructureMap requests and emails over the weekend for all of you waiting on something from me.

     

    The Highlights

    • Martin Fowler and Rebecca Parsons talk on reconciling enterprise architects with Agile processes.  I think they made a very good case for using incremental delivery mechanisms and the transparency that Agile can provide to aid architects.  Buuuuuuttttttt, in order for their recommendations to work, I think that large companies will have to dramatically change their attitudes towards the people that build software.  Hands on skills and application architecture skills have to be held in much more regard by many companies than it is today.
    • Seeing some Google Web Toolkit in action at a talk from Alex Moffat (fellow Austinite it turns out).  I’ve always blown off the tools that try to hide Javascript, but I’m intrigued by GWT.
    • The Volta talk.  There was a lot of (highly justified) dubiousness in the room, but it’s interesting.
    • Jay Fields DSL talk. 
    • Don Syme showing how 30-40 lines of C# could be accomplished in 2 lines of F#
    • Tim Bray’s talk on alternative storage devices.  It’s possible, possible I say, that you and I may build a significant system someday that does not run against a relational database.

     

    Just Be Thoughtful

    In my Evolution of a Developer post a couple weeks ago, I had a question in the comments:

    So how do you recommend training an eager kid out of college with little or no experience to get through these steps quickly?

    In typical me fashion, I didn’t get a response together in a timely manner, but I will now.  Be thoughtful about your work.  Experience is the greatest teacher, but not all experience is created equal.  When you do software projects or assignments, and especially something challenging or big, reflect upon it later.  What would you do differently?  Why?  Why did you choose to do it the way that you did for that matter?

    I had the pleasure of attending one of Kent Beck’s talks here at QCon.  It wasn’t anything revolutionary or even informative to be honest, but what I saw was one of the masters of our craft simply reflecting over how he made design decisions.  I think it’s a good example to follow.

    From experience though, do watch out for the “second system syndrome.”

    Favorite Exchange of the Week

    • Me:  Argh!  You should have told me that you were going to show me VB code!
    • Rod:  Relax, dude.  It’s just English.  We don’t use those hieroglyphics that you do (C#).

     

    Big Systems

    Someday, I’d really like another opportunity to build a really big, highly scalable type of application again.  But it’s much more important to my sanity to permanently stay out of big companies.  Oh well, I guess I’ll just settle for working in a very pleasant environment with people that I like.

  • Thoughts on the Decline and Fall of Agile

    If you haven't already, go give this post from Jim Shore a read.

    I've seen a lot of commenters on this post so far, and their thoughts generally mirror my own.  You can't take the "desserts" of Agile practices like working incrementally or the all important adaptive planning and scheduling without quite a bit of engineering practice vegetables.  You wanna work adaptively instead of the ol' fashioned plan driven method?  Fine, but you've got to make that adaptability safe.  You need rapid feedback cycles to know when you're getting off the rails (customer demos, TDD, Continuous Integration, automated acceptance tests, static code analysis or some sort of equivalent).  You need to take steps that make continuous design methods safe and effective (simple design, a constant attention to design fundamentals like the SOLID principles, and an intolerance for technical debt).  And your team needs to be retrospective about its work to make adaptions as they become necessary.

    In the early days, XP was roundly criticized because every practice only seemed to be safe due to the existence of the other practices.  Take one out, and the others weren't that great by themselves.  I think that's more or less a fair criticism, but my response is simply to adopt, and effectively apply, everything you need to make Agile development successful.  You can't just pick and choose the easy things.  If you take something off the old XP practice recipe, you probably need to find an analogue solution to add something else back into your practices.  Regardless of which practices and how you do those practices, there are project needs that have to be filled (planning, quality assurance of some sort, feedback cycles, etc.).

    Of course, it's always going to be easier to get it wrong than right, but that's why we're paid the big bucks.

  • Some Reading on Essence vs. Ceremony

    In both my next MSDN article and a bit of my QCon talk I'm exploring the topic of "Essence vs. Ceremony" applied to .Net architectures.  Along the way, I reread this gem from Stuart Holloway:

    Ending Legacy Code Within Our Lifetime

    and discovered this from Neal Ford:

    Ceremony vs Essense

     

    Stu & co at Relevance are primarily a Ruby shop, but I highly recommend their blog for anyone interested in software craftsmanship.

  • At QCon next week

    Next week I'm presenting the Joys and Pains of Long-Lived Codebase's at QCon San Francisco.  In my 5+ years of evolving the StructureMap code far away from its original intentions I've learned some hard lessons.  In my talk I'll share some experiences and thoughts on:

    • Choosing solid abstractions for your design, and recognizing when abstractions no longer fit the requirements
    • The design principles that allow for evolving a design -- and the painful consequences of not following those principles.  More importantly, how to retrofit those qualities in order to make design changes possible.
    • How can you most effectively use TDD or BDD to enable architectural changes -- and the mistakes I made with TDD that hampered design changes
    • Constructing a framework and how our expectations of a framework have changed in the last half decade
    • Creating API's for other developers

     

    I've been looking forward to this for months.  I hope to see some of you there.  I'll try to blog as much as possible about it as soon as I get back. 

     

    P.S.  Just ignore all the "No Fluff, Just Stuff" gurus that may or may not be speaking at the same time as me.  I may give away some sort of door prize just to get some attendees to my talk;)

  • Don't Check in Spike Code...

    ...into the trunk.

    Just like the title says, do NOT check “spike” code into the source control trunk.  When you do an exploratory spike, you’re generally throwing good coding practices completely out the window.  You’re on a focused mission to “figure out how this gosh durned thing is supposed to work.”  The code that you write in a spike probably sucks anyway. 

    Do spike whenever you’re unsure how to work with some new library or technology or to try out a new object structure – but put that code in a branch.  As soon as the spike has achieved its purpose, put that code aside, and write all new code in the trunk using TDD and your normal coding standards.  You know, the coding and design standards that you've adopted as a team because you think those standards lead to sustainable quality.  But Jeremy, I could just retrofit some unit tests around the spike code and call it good!  Maybe, but you better ask yourself, am I really going to put decent tests around this code?  Retrofitting unit tests never results in the same quality of tests as real test first development.  Besides, as I said earlier, spike code generally sucks anyway;-)

  • Evolution of a Developer (in regards to DI/IoC)

    I’m putting together a new quickstart for StructureMap tonight.  In looking over my notes, I found a draft from earlier this year where I was trying to argue the value proposition of an IoC container.   I’m scrapping most of that post, but I wanted to share some thoughts on dependencies and structure in software designs.  My advice is to get yourself to bullet number 4 below in order to make your design, unit testing, and coding efforts more efficient – regardless of whether or not you use an IoC container.

    I think the evolution of a developer's mindset towards structuring applications goes something like this:

    1. Just gotta make this work.  There isn't any separation of concerns.  Code responsibilities tend to fall wherever the developer happened to be in the code when he or she realized they needed something (what I refer to as stream of consciousness coding).  For myself in the late nineties, this trait manifested itself as popping open an ADO connection and grabbing an ADO recordset anytime, and anywhere, that I needed some data in the middle of a long ASP page.  I've worked in a couple different development environments and read code in twice that many since, but in my experience nothing leads to a big ball of mud faster than the combination of ASP Classic and developer carelessness.  The code worked, and that's definitely something, but large amorphous code modules tend to be difficult to troubleshoot, maintain, and modify.  Plus, they can easily lead to duplication because code isn't structured for reuse.
    2. The next stage is learning to put things in their place.  The developer has progressed enough to internalize the value of separating concerns into cohesive modules.  The developer is thoughtfully asking the question to himself or herself "where should this code go?"
    3. Wait, I've separated my concerns, but everytime I change one module changes ripple into other modules.  Each concern seems to know too much about the details and functions of other concerns.  Now we start to worry about being able to change how the system behaves by making isolated changes that impact the fewest number of modules as possible.  To make this happen we need to make sure the different modules are loosely coupled from each other.  At this point we begin to make much more use of interfaces and abstractions to reduce the coupling between modules.  We also strive to build modules that do not incorporate any knowledge of the other modules that the first module depends on.
    4. The developer is fully cognizant of dependency relationships in his or her codebase.  At this point we're ready to consider using Dependency Injection and Inversion of Control to both further encourage loose coupling and exploit the seams in our application.
    5. The developer finally learns some completely new way of building software and feels like they've started all over again at phase #2.

    I think the leap from #1 to #2 is huge chasm that many developers will fail to cross in their careers, but every following transition becomes easier. 

     

    The following is a partial repeat of an older post, but I think it applies here:

    Coder to Craftsman

    When people first learn how to write code they necessarily focus on just making the code work, with little or no thought for style or structure, and certainly no thought for the future.  Any particular piece of code tends to land wherever the coder happened to be working when they realized that they needed that piece of code -- or wherever the RAD wizards felt like dropping the code. 

    I think there is an inflection point where a coder mindlessly spewing out code transforms into a thoughtful software craftsman capable of creating maintainable code.  That inflection point happens the day a coder first stops, lifts his/her nose out of the coding window, and says to him/herself "where should this code go?"  That might also lead to questions like "how can I do this with less code?" or "how can I write this to make it easier to understand?" or even "how can I solve one problem at a time?"  The rest of a developer's career is spent pursuing better and better answers to the question "where should this code go?"

  • My best days as a coder

    Last time I was negative and sarcastic, so this time I want to be positive.  My best days as a coder were:

    • When I used to write Shadow IT apps for my engineering team, anytime I wrote something that eliminated a lot of grunt work was a very happy day.
    • I got stuck as a noncoding architect in possibly the worst IT shop in the country, but the biggest joy ever was the day they released the new "Responsibility Matrix" and my team realized that our "System Architect" role was not responsible for one single intermediate deliverable.  That's right, zero responsibility.
    • The day that I first "got" ReSharper
    • The day the ReSharper 4.0 finally became stable
    • The day that I first "got" jQuery
    • The day that my first big system went live -- and worked on the first big transaction.
    • The iteration when a previously troubled project suddenly righted itself and the coding became easy
    • The day I toured a factory and saw my software running at all the receiving doors
    • The day Chad & I decided to quit our previous job
    • The day last month when our new rules engine & rules DSL ran flawlessly for the first time after a 6 week coding sprint
    • The time my friend got an award from the business users in appreciation for the new application we built together. 
    • Any single day I get a complement on StructureMap or somebody writes me to say my blog helped them with something
    • My first ThoughtWorks away day.  If you want to learn to be a good developer, the easiest way to get there is to interact with good developers. 
  • Upcoming Posts

    I had tonight reserved as my night to do all those blog posts I've promised folks, but I ended up moving boxes all night and I'm crashing instead.  For all of you that have made requests, in the next couple days I hope to churn out:

    • A Gentle StructureMap Quickstart (very basic)
    • Using StructureMap to bootstrap NHibernate (w/ Fluent NHibernate and our particular flavor of Repository / Unit of Work)
    • Convention Based Type Registry in StructureMap
    • Introduction to the Application Controller Pattern for Desktop Apps (by request, but it amounts to "Jeremy gets serious about the book")
    • My KaizenConf wrapup
    • and I owe Glenn Block several posts.  I'll get around to it.  I promise.

    Now, off to bed.

  • What's your worst day as a coder?

    Yesterday I was switching our test automation driver layer from WatiN to Selenium RC (Firefox / Chrome / Opera support and I was livid with the COM errors from IE in WatiN).  I think I'm glad that we made the switch, but it took quite a bit of trial and error to bend Selenium RC to my will.  That and something else I read today got me to pondering the worst days I've ever had as a coder trying to make unfamiliar or confusing technology work.  My list is something like this:

    • Using a CLOB or BLOB datatype in Oracle.  I've done it several times, but it never seems to get any more pleasant
    • Getting a custom authentication scheme to work with x509 certificates.  Shudder.
    • The day that a client developer hosed our CVS repository
    • The day that our project, the project that was going so marvelously with the team that was starting to gel, was shelved on a management whim
    • The day a month before go live when the BA finally saw fit to tell me about the other half of the requirements document that no one had told me about previously
    • The days that followed "here's how to use our homegrown ORM"
    • The days that followed "you must use our standard architecture for..."
    • Writing queries against a custom Active Directory schema.  Ended up ditching AD a month later and just put all the user information in the database.  The nice, predictable, familiar database.
    • Any number of days doing test automation with NFit or FitNesse
    • Almost any day fighting with Legacy code, but that shouldn't really count
    • The day and a half I spent making StructureMap work with open generic types a couple years ago. 
    What's yours?
  • How to design your data connectivity strategy

    I'm scurrying at lunch to finish reviewing some architectural guidelines for the P&P group (I'll be done today, I promise).  I stumbled across a section with the same title as this blog post.  I'll answer the question concisely:

    Pull an existing persistence tool off the shelf, make sure you understand it, and code, code, code!  Persistence coding is a commodity in this day and age, so just use and existing tool and get on with your project.  It's extremely unlikely that there's any business advantage to writing data access code by hand when there are so many existing tools out there.  I'll repeat this little gem one last time, if you're writing ADO.Net code by hand, you're stealing from your employer or client. 

     

  • Time to slow down the Oslo hype

    This quote about Oslo & SOA is over the top:

    Because the software infrastructure that supports your business model is not based on some gobbledygook that only the guy with the pocket protector and horn rimmed glasses understands. The software that supports your business model is based on models and these models are aligned with business capabilities that bring value to the organization and these models are also aligned with standards based, interoperable and reusable webservices that represent your software infrastructure. 

    Puh-leeze.  Only uber-"pocket protector and horn rimmed glasses" guy is going to be capable of utilizing Oslo effectively to create that clean business facing language in the first place.  And again, only the geeky programmer is going to have the slightest clue about how that spiffy new DSL is actually translated into real functionality.  Having a "Model" that's just a lump of data isn't all that useful.  Something has to actually make the "Model" be executable, and I nominate the guy with the pocket protector.

    Oslo potentially == a new way to integrate external DSL's into the .Net ecosystem != non-programmers "writing" software.  Let's set our sights just a little bit lower.  Just being able to write code that closely reflects the business domain is a huge win.  Getting business experts able to write the actual code, even in a DSL, isn't going to happen.

    C'mon here.  I'm very interested in Oslo too, but I can't see any way in which Oslo is a game changer. 

  • There’s nothing worse…

    …than being a developer who leaves the office with a pernicious coding problem unsolved – mostly due to working with a technology I’m not familiar with.  I spent a couple hours at the end of the day trying to make some new test automation code work to no avail.  Leaving work without solving the issue just leaves a very sour taste in my mouth.  I fired up my computer and took another hour and a half to finally solve my problem this evening.  I wasted a night, but at least I feel calmer heading into the bedtime hours.

  • Chad & I get Opinionated about the ASP.NET MVC

    The videos for Chad & I's talk on our MVC usage from KaizenConf this past week is available on Viddler.  This workshop covered the content from the Our "Opinions" on the ASP.NET MVC post from a couple weeks back with the real code.

    Chad is working to move *some* of our infrastructure into Google Code just with the intention of sharing the code.  We might get serious about making our MVC stack a new OSS project early next year, but there aren't any definite plans.
  • A Quick StoryTeller Update

    I announced the StoryTeller reboot a couple weeks ago.  I had a couple people email me about it, or volunteering to help.  I didn’t respond (I’m sorry) because I didn’t know quite how things were going to go.  I think I can finally say that I’m confident that StoryTeller is on a good path and start thinking about other contributions.  At this point, I’m able to author tests against our system at work and I’ll be able to demo the testing engine at KaizenConf this weekend.

     

    Here’s what I’ve got so far.  It’s very rough, but it’s a start.  I’m deviating a lot more from Fit than I had thought I would, but it’s still easiest to describe the functionality in terms of Fit analogs.

    Terminology:

    • Test – duh.
    • ITestContext – the state of the currently executing test.  My main vehicle for maintaining state during a test.  One of the gripes about Fit is the clumsiness of maintaining state in a test across multiple Fixture classes.  I think I’ve generally alleviated that problem with StoryTeller.  ITestContext is also more or less a service container for the test infrastructure.
    • Step – A test is composed of steps.  The “Step” in StoryTeller is a logical operation in the test, or group of operations.  A Step does not necessarily equate to a single table row in Fit.  In the StoryTeller model, a single Step might equate to a half dozen lines in the rendered test output.  For example, editing my application’s Address form requires 6-7 different actions for filling in different textboxes and selecting dropdown values, but you always have to do these 6-7 things at a time, so it’s a single Step.  I think this is hugely important in making StoryTeller test authoring more mechanically efficient that Fit.
    • Grammar – The fundamental unit of test execution and expression.  Each Step is processed by a single Grammar in the test execution based on the Step’s “grammarKey.”  It is possible to create a CompositeGrammar to group related Grammars into a coarse grained unit.  A TableGrammar is a special kind of Grammar that allows you to recreate a ColumnFixture from Fit in StoryTeller for example driven tests.
    • Fixture – A class that provides one or more Grammars.  Unlike Fit, a Fixture in the StoryTeller architecture can mix table and flow driven grammars in a single class for easier coding and state sharing.

     

        public interface IFixture

        {

            string Name { get; }

            IEnumerable<IGrammar> Grammars { get; }

            IGrammar FindGrammar(string key);

            void ForEachGrammar(Action<string, IGrammar> action);

        }

     

     

    ColumnFixture Analog

    The thing that Fit is best at is table driven “example” tests, or the Row style tests in MbUnit.  Unlike Fit, the StoryTeller analog can just be a method instead of a completely separate class.  Any simple Grammar can be exposed as a TableGrammar.  Here’s an example of turning a normal method into a TableGrammar:

            [ExposeAsTable("Add numbers", "Rows")]

            [return: AliasAs("sum")]

            public int AddNumbersTogether(int x, int y)

            {

                return x + y;

            }

     

    It’s limited to a single return value at the moment (a serious limitation), but that’s a lot less code than the Fit equivalent.  The ExposeAsTable attribute just says “this method is a table grammar.”  The AliasAs attribute is just helping to fine tune the test rendering.  Don’t worry, it’s not crazy with attributes, but I am using some to control formatting.

     

    DoFixture Analog

    This was actually my very first use case for the new engine.  The DoFixture allows you to do flow based testing.  At its simplest, just write public methods on your Fixture class:

        public class AddingFixture : Fixture

        {

            public AddingFixture()

            {

                // This creates a TableGrammar using the AddNumbersTogether2() method

                Grammar("AddNumbersTable").IsTable("Add some numbers together and see what happens").TheInnerGrammar

                    .Is(FindGrammar("AddNumbersTogether2"));

            }

     

            [ExposeAsTable("Add numbers", "Rows")]

            [return: AliasAs("sum")]

            public int AddNumbersTogether(int x, int y)

            {

                return x + y;

            }

     

            [return: AliasAs("sum")]

            public int AddNumbersTogether2(int x, int y)

            {

                return x + y;

            }

        }

    Any public methods will be picked up as Grammars.  In addition, there is the beginning of a DSL for programmatically defining Grammars.  Here’s a real life example from our AddressFixture that tests our Address CRUD and Query web pages:

            public AddressFixture(ApplicationDriver driver)

            {

                _driver = driver;

     

                // More or less script how the Address screen is edited in one logical step

                Grammar("EditAddress").IsScreenEditor<EditAddressViewModel>("Edit Address").WithPrefix(x => x.Address)

                    .Enter(x => x.Address.Address1)

                    .Enter(x => x.Address.Address2)

                    .Enter(x => x.Address.City)

                    .Select(x => x.Address.StateOrProvince)

                    .Enter(x => x.Address.PostalCode)

                    .Select(x => x.Address.Country)

                    .Select(x => x.Address.TimeZone);

     

                // Check all the values saved to the database

                Grammar("CheckFields").IsCompositeTitled("Verify Persisted Fields")

                    .LoadThisObject<Address>()

                    .VerifyPropertiesOf<Address>(x =>

                    {

                        x.Check(o => o.Address1);

                        x.Check(o => o.Address2);

                        x.Check(o => o.City);

                        x.Check(o => o.StateOrProvince);

                        x.Check(o => o.PostalCode);

                        x.Check(o => o.Country);

                        x.Check(o => o.TimeZone);

                    });

     

                // Create a new Address object and persist it

                Grammar("DefineAddress").IsCompositeTitled("Address in the Model Is")

                    .SaveNewObject<Address>(x =>

                    {

                        x.SetAllPrimitivePropertiesSpecificToThisType();

                    });

     

                // Create and persist multiple Address objects

                Grammar("AddressList").IsToSpecifyTheListOf<Address>();

     

     

            }

     

    I should point out that quite a bit of that stuff above is Dovetail-specific language for our application architecture. 

     

    RowFixture Analog

    Very frequently, you need to verify a set or list of values against an expectation.

                // This Grammar clicks the "Save" button expecting input validation failures

                // and validates the displayed validation failures against an expected

                // list, displayed as a table like the Fit RowFixture

                Grammar("ClickSaveUnsuccessfully").IsVerifySetOf<ValidationError>("Clicking Save should fail with validation errors", x =>

                {

                   x.Before((step, context) =>

                   {

                       clickSave(context.Retrieve<ScreenDriver>());

                       var notifyDriver = context.Retrieve<NotifyDriver>();

                       context.CurrentObject = notifyDriver.GetErrors();

                   });

                })

                .MatchOn(x => x.Field)

                .MatchOn(x => x.Message);

  • StructureMap 2.5 is Released!

    As of, oh, whenever SourceForge ends up cooperating and uploading the file, StructureMap 2.5 is officially released! The binaries are available for download now at http://sourceforge.net/projects/structuremap. For the first time in quite a while, the binary release includes a new CHM file for all of the public facing API. 

    So, what does the release mean?

    The documentation is unfortunately not complete, but I wanted to make the release now as effectively putting a stake in the ground and saying "from this moment on, I commit to maintaining *this* public interface and all changes from here on out will be backwards compatible with the 2.5 release." I'm working diligently on the documentation. You can browse the documentation work in progress here.  In the meantime, please ask any StructureMap questions in the google group for StructureMap

    To be upfront, I’ve treated the 2.5 release as my Python 3000 release, meaning that I’ve taken every opportunity to clean up the API and blow away some unfortunate trash in the code.  This release marks nearly a fullblown re-architecting of the StructureMap internals, and that new architecture has largely been responsible for the explosion in functionality in this release.  All of this does mean that some existing API’s introduced in 2.0 for the Registry DSL are already gone.  I’ve learned a lot about writing internal DSL’s with C# in the meantime.  That learning, combined with all the new language goodies in .Net 3.5, have led to a somewhat different Registry DSL, but one that I hope will be easier to read and more discoverable once you stop yelling at me for changing it ;-)

    Unfortunately, this release has taken so long that Jimmy Bogard openly mocks it as the “Duke Nukem Forever” release.  I saw the news the other day about Guns & Roses finally releasing Chinese Democracy, and I knew that I *had* to get this thing out.

    If you happen to be at QCon San Francisco in November, come to my talk and you’ll hear all about the 5 years of hard lessons I’ve learned from doing and redoing StructureMap.  If you’re at KaizenConf this week, go to Chad Myer’s talk and you’ll hear quite a bit from the internal DSL angle.

     

    The new functionality in StructureMap 2.5:

    • Completely revamped Assembly scanning options
    • Cleaner, more predictable way to initialize a Container.  StructureMapConfiguration is now deprecated, please use ObjectFactory.Initialize().
    • Optional setter injection
    • All new abilities to query the configuration of a Container
    • The ability to use StructureMap with ZERO Xml or attributes by default
    • The ability to add services at runtime. You can now programmatically add an entire Assembly at runtime for modular applications that might not want all services to be loaded at startup.
    • An auto mocking container based on Rhino Mocks 3.5. I was a doubter on the validity of AMC, but I'm sold now that I've used it
    • Contextual object construction
    • More sophisticated auto wiring rules
    • Supporting NameValueCollection and IDictionary types
    • Far more extensibility
    • Interception and post processing hooks for you AOP enthusiasts. StructureMap will NOT include its own AOP engine, but will allow you to use the runtime AOP technique of your choice.
    • More configuration options in both Xml and the Fluent Interface. Completely revamped the Registry DSL.
    • More options for modular configuration (mix and match Xml configuration or Registry's at will) -- which basically had to trigger:
    • Completely revamped diagnostics, including the Environment Testing support
    • Transparent creation of concrete types that are not explicitly registered
    • Create objects with explicit arguments passed to the container
    • Use the underlying Container independently of ObjectFactory
    • Pluggable auto registration with your own custom Type scanning policies
    • StructureMap is now strong named (thanks to Steve Harman)
    • Pull configuration from the App.config (thanks to Josh Flanagan)
    • Generics fixes (thanks to Derrick Rapp)

     

    Anyway, I've got some documentation to go write.  Watch the blog for a lot more content on StructureMap usage.  We’ve added some other functionality at work that hasn’t gotten into the trunk, but I’m putting the kibosh on new code until the documentation and website is completely overhauled.

More Posts Next page »

Our Sponsors

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP