Several folks, including Microsoft employees and members of the Oxite team, have politely requested I do a post or few on the problems I see with Oxite and why I previously recommended that it is not a good example/sample from which to base future products.
At first, I was reluctant to do this since I was afraid people might see it as some sort of attack or other negative. But since I have been encouraged by several folks as mentioned, I feel that this will be constructive and received as a "good thing".
Setup
First, I want to make sure that everyone knows there's no attack here, nothing personal, this is purely about code and in no way a reflection on the individual. The way we roll at Dovetail is that we are dispassionate about our code and follow practices such as collective code ownership, refactoring mercilessly, pair programming, and no premature optimization, which help disassociate our passion, creativity, and soul from the code so that we can objectively look at parts and say "that is bad" or "this is good" and mean it. So I'm coming from a viewpoint that the code is code and should be mercilessly, objectively torn apart and made to stand on its own merits, independent of who wrote it and under what conditions. I say that code can be objectively determined to be "good" or "bad" and patterns and anti-patterns identified with certainty and no subjectivity.
Second, please consider Nate Kohari's recent great post on debate vs. argument; ego, pride, personal attachment, etc. as this also helps to frame where I'm coming from. During this review, I'm not going to mention people, their motivations, their goals and desires, etc. I'm only going to talk about the code and the requirements of the features the code is trying to accomplish.
With these things in mind, let us now objectively view Oxite as a body of work, independent of any individuals involved in its creation, that must stand alone and be evaluated solely on its own merits.
As a Sample Application...
Oxite is a "real world sample" and not necessarily official guidance (a la the Patterns & Practices type stuff). As a sample, the packaging of Oxite is good as it includes many facets of a project from the domain, to the database, to the front end, etc. Perhaps it could've included some more documentation (maybe I missed it? I didn't look very hard, admittedly). Since this wasn't positioned as a guidance project, people should avoid referring other people to it as any sort of best practice or official anything from Microsoft. As ASP.NET MVC matures after release, I expect we'll start seeing more official guidance from P&P and other groups within Microsoft.
Recommendation: [For MS, primarily, as this problem is mostly unique due to MS' position with respect to .NET] Perhaps MS could establish more official terms to set expectations for customers. "Sample" is not "Guidance" is not "Recommendation" is not "Stance", etc.
As an OSS project...
Oxite is an open-source project. It is released under the Microsoft Public (Ms-PL) license which is quite permissive and in line with generally accepted good practices for open source. This is very good. Oxite is hosted on the CodePlex project site and (correct me if I'm wrong) is not accepting patches from the public due to, I believe, concerns of patent/IP violations and such. This is not very good. Part of being open is allowing people to modify it without having to fork the code. At the very least, we can fork it which is certainly heads above what we normally get from large corporations which is either no visibility, or only push releases. Overall, I'm very pleased MS has taken this approach with Oxite and I'd like to greatly encourage them to pursue this method of release in the future. My only critique is that maybe they find a way to accept patches from the public (I'm ok if they need to fill out some affidavit or other legal form).
As a .NET OSS project, I was particularly disappointed in the fact that the high-level Visual Studio Team *.* SKU's were used in its creation. I don't have the numbers, but I'm willing to bet that the vast majority of .NET developers do not have the full Visual Studio suite (Database, Test, etc) and so they won't even be able to open the SLN file without having to hack CSPROJ files and such (like I had to). There is a SLN file for Visual Web Developer Express that will help get people going, but this seems like an afterthought, rather than a good strategy.
Also missing is any sort of automated build script. What if I want to set up Oxite in my own CI server to pull down the trunk nightly and do builds in my environment? This is pretty standard among .NET OSS projects, so I was disappointed that this was missing.
Recommendation: [For MS and other companies seeking to release .NET OSS] Either let these things go out to be full OSS projects and release the copyright and liability to the public somehow to achieve full indemnity from possible patent or copyright infringement. And/or, find a legal framework for being able to accept patches from individuals in the community.
Recommendation: [For anyone managing an OSS project] Please take a little more care to ensure that you have respected generally accepted minimum expectations of an OSS project such as an automated build and decent test coverage.
Tests!?!
Technically, this should just go under the previous section, but it's significant enough that it should be called out on its own. Unless I'm missing something, there are around 51 tests for the entire project and those tests cover only the MetaWeblog API handling and the XmlRpc handling. Without having run a coverage tool, I'm guessing that coverage is below 10%. I'm very serious when I say that this would be considered unacceptable on most projects I'm involved with. I would be put on probation or possibly removed from a project at a corporate customer or removed as a committer on an OSS project for committing code with <10% coverage. Quite frankly, it is dangerous to have a large application with <10% test coverage. It is also a liability in that future changes become ever increasingly difficult with the friction and fear of change due to the unknown of how changes may break functionality and cause regression bugs.
The tests that are there (for example, I count 49 in the MetaWeblogServiceTests) are a little heavy. In my opinion, this indicates that MetWeblogService has too many responsibilities and is putting too much burden on the tests to account for the excessive dependencies of MetaWeblogService. It's also curious that no mocking framework was used, but instead (excessive, IMHO) use of fake, concrete test implementations were used. Several(though not most) of the tests are asserting too many things which leads to brittle tests and can cause friction during refactoring.
Testing is not just about ensuring the current code works properly (that is important), but also explaining how the code works so that, in the future, when changes are made, maintenance programmers understand why the change they made broke other things. This enhances change confidence and encourages fearless refactoring which is key to maintaining a rapid, sustainable pace throughout the life of the development.
But I digress, this subject is perhaps too large and requires a post in an of itself. Suffices to say that there are too few tests and the tests that are there, while meaningful, will contribute to increased friction over the life of the product and should probably be refactored as the project goes on.
Recommendation: [For anyone managing an OSS project] Tests serve many purposes including encouraging contributors because they can see how things are supposed to work, and can be more confident in their changes, knowing that tests will most likely catch them if they make a big mistake. At this point, going BACK and adding tests would likely be a waste of time. Going forward, all new features should be developed with tests (preferably test-driven as this helps keep your design on track, it's a curious side effect of writing client code FIRST, then the code to make it work). Any bugs that pop up between now and then should first have a test that reproduces the problem, then the fix should be implemented, and the tests should then pass (without modification). If they don't pass, the fix isn't quite right. If, during the fixing of bugs, you discover other problems or realize there's more refactoring to do, do that code test-driven along with the bugfix. Try to keep changes minimal and focused, though, and with a high degree of coverage (preferably >90%, but that's not a hard rule).
Test should be small, easy to write, and not require a lot of setup. If they're not meeting ALL of these three criteria, you have a design problem and need to reinvestigate. It happens all the time that I find myself violating one or more of these rules, and the tests help to point me to where in my design I screwed up. This is a natural thing and shouldn't be seen as negative. You caught the problem early and tests helped spot it and point you in the right direction. Just keep these criteria in mind as you proceed.
Domain
The heart of any good project is its domain. The domain is the understanding and model of the core problem this application is trying to solve. The domain is king. It should be fat, juicy, and contain the core logic that constitutes how this application behaves. Everything else in the application serves the domain by either bringing information to it, or relaying information out of it to the customer (users, other applications, data storage, etc). Great care and investment should be placed on the domain of the application as it is your greatest and most important asset. Principles, patterns, and practices have evolved around this very integral part of application design. Entire books have been written. These include Domain Driven Design (Evans) and Applying Domain-Driven Design and Patterns: Using .NET (Nilsson), among many others.
An important part of key domain object model design is to do it independent of persistence concerns (known as "Persistence Ignorance"). Object Oriented Design is a fundamentally different problem than Relational Data Model Design and each should be done independent of the other to avoid the patterns of one being misapplied in the other. The intermediary between the contrary physics of these two worlds is the Object/Relational Mapper (ORM) such as NHibernate, LLBLGen Pro, and, to a lesser extent, ADO.NET Entity Framework and the now defunct Linq2SQL.
In Oxite, the domain appears to have been driven from the relational model (i.e. database) which has caused some interesting problems that had to be worked around and have hampered the domain (we'll get to this later). The data provider used was Linq2SQL. Object/database design were achieved using the Linq2SQL designer-generated classes. These classes are partial classes which allow the application to create the other half of the partial class in another file. In these partial classes are added the property-changed, relationship, and other data-concerned handling/functionality. Also, each partial adds an interface (i.e. IPost for the oxite_Post object) presumably to hide away some of the details of Linq2SQL.
Recommendation: Domain objects should be POCO objects with no attachments to or knowledge of the database whatsoever. You can have class hierarchies (but proceed cautiously and light here) and entities can have interfaces, but this should be a rare occurrence and should not required of all of them. The objects should be able to be used and their functionality fully useful without requiring any backend infrastructure, services, database, etc. When it comes to persistence, the persistence framework should "just work" and support the objects naturally without them having to implement any special interfaces or have to do anything special (i.e. including support for transparent lazy loaded collections, and none of this EntitySet business). If your ORM can't do that, consider one of the already available, major, post 1.x version offerings that have been proving themselves for years on the market in battle.
Linq2SQL Problems
You may have noticed earlier when I said "to a lesser extent" when talking about Linq2SQL as an ORM. This is because Linq2SQL is missing a lot of key functionality to be considered as a full-fledged ORM. Among these are automatic change-tracking and cascade support, transparent lazy loading, and database data-type minutiae handling. These things are just a given in a more mature and full-featured ORM like NHibernate, for example.
I also said that the use of Linq2SQL has caused some interesting problems. Aside from having to manually do change tracking, deal with underlying SQL data-types, and having to deal with relationships manually, the Linq2SQL-based objects have the pernicious problem of not being able to be used (easily) without being connected to the database. This is the opposite of "Persistence Ignorance." To counter this problem, Oxite has entity interfaces (i.e. IPost). Generally speaking, interfaces for entities is a smell. In this case, the smell is definitely pointing to a problem and using interfaces is merely a band-aid for that problem.
Recommendation: Don't use Linq2SQL as it's simply too much friction and lacks critical features. Use a full-featured ORM like NHibernate or several of the commercial ones available.
Interface Entities
I mentioned above some of the problems with interface-based entities like IPost, ITag, etc. I wanted to call out a specific example of where something like this can go very wrong. In the partial class declaration of class oxite_Tag, the Parent property has a significant problem for reuse and future maintenance. For reference, see PartialClasses.cs, line 646.
The problem with this property is that it means oxite_Tag is only valid with other oxite_Tag implementations of ITag. This is what's known as a violation of the LiskovSubstituionPrinciple and/or the OpenClosedPrinciple. Put simply, anyone doing anything with ITag would be surprised if they started getting InvalidCastExceptions because of some problem lurking deep in your design. If the intention is that oxite_Tag can only work with other oxite_Tag's, then it shouldn't use an ITag interface when it doesn't really mean it.
Is this nitpicking? Kinda. The oxite_Tag problem may never get hit, but it is a potential landmine in your code, waiting to explode on an unsuspecting maintenance programmer. If your design has special magic and gotchas, you have a problem.
Recommendation: Interfaces should be intention revealing and their implementation contain no surprises. Interfaces also should only be used where true abstraction is needed. Entities/domain modeling is generally one of these places where abstraction is not necessary (and therefore interfaces shouldn't be used).
Database Assumptions
The entities in Oxite have several assumptions specifically about SQL Server (heavy use of SqlDateTime.Min/MaxValue). This is yet another problem that stems from the of usage of Linq2SQL. To address this, Oxite has abstracted entities (behind interfaces such as IPost, ITag, etc) and abstracted the repositories behind interfaces (good, actually!) and these repositories are accessed through an "IOxiteDataProvider" implementation, such as OxiteLinqToSqlDataProvider (bad, more on this later). This is not the appropriate place to abstract database concerns. I'll cover proper layering and proper concern separation later. For now, the relevant point is that concerns about the specific usage of the underlying database have seeped up too high in the layering of the application, necessarily requiring more and more complex architecture and abstractions to work around this. This means implementing an "IOxiteDataProvider" is more difficult for would-be implementers than it should be and much duplication of code will likely result. It also prohibits the use of a fat/rich domain model which leads me to the next section (Anemic Domain).
Recommendation: Keep database-specifics as close to the database as possible and, to the maximum extent possible, completely out of your application code. This is best handled by a persistence framework such as an ORM like NHibernate. Doing this will make it much easier to implement different data access strategies later in the product's life and to support a wider range of database platforms with little to no change to most of the application code. You'll still have to test on each database you plan on supporting, but the code should not have to change (much) when adding support for a new database.
Anemic Domain
Another problem with the domain of Oxite is that all the entity objects are anemic with a few minor exceptions. An anemic domain model is one that is largely if not entirely comprised of getters/setters and are just data containers (DTOs for the database, if you will). This necessarily forces all the interesting logic of the domain to be the responsibility of other, perhaps less appropriate, parties which can lead to "service explosion" or "manager anti-pattern", etc.
Like I said earlier, domains should necessarily be fat and contain all the relevant logic. They should contain concepts such as "required" and "unique", etc and these concepts should flow out into the rest of the application including into the relational database model. The domain should prevent invalid states/situations and should enforce rules throughout the system. This is not to be confused necessarily with the antiquated concept of a Business Logic Layer, however.
Recommendation: The domain model should be "fat" and rich. It should be modeled according to the current understanding of how the domain SHOULD work (i.e. X is required, there can only be 1 Y per every X, When an A is added to a B, that B's "A" property should be set to the newly-related A instance, etc, etc, etc).
Conclusion of Part 1
It looks like this will be a multi-parter, because it's already long and I haven't even gotten to the majority of issues. By the time this review is done, I'd like to cover the following things by the time I'm done (wish me luck):
Problems with the Provider anti-pattern
Incorrect layering and slicing of abstractions
Lack of Dependency Injection (in some cases) and IoC causes cascading design problems
High Coupling, Low Cohesion
Single Responsibility Principle, Separation of Concerns, and Interface Segregation Principle violations causing problems
What is a "Controller" for?
What is a "View" for?
Mystery Meat, Magic Strings, and Bags of Holding +1
Presentation Models
Logic in Views Is Bad
ASP.NET MVC guts leaking up into all parts of the app
(other stuff that will probably come up in the comments that I didn't think of)
With 2008 behind us, what better way to kick off the new year than another cheesy top 10 list. This time, with more bold!
Rather than focus on the negative, here are a few things I'd like to see continued and embraced in the year ahead.
1) Open spaces
Open spaces, coupled with targeted workshops, provided the best bang-for-your buck experience for technical conference this past year. What started (in the .NET space) with 2007's ALT.NET Conference, continued with ALT.NET Seattle, spread to other cities, countries and continents, and taken to the next level with KaizenConf and workshop. The quality of conversations at these events, before, during and after, in the sessions, in the hallways and continued at hotels and local dives and eateries, was top notch. Open spaces encourage community growth through multiplication instead of addition, and I'm happy to see this format branch out more and more in the .NET community.
2) MS forays into ORM
A few years ago, ORMs were described as the "Vietnam of Computer Science". It's an oft-misunderstood metaphor that still requires a read today. However, as modern ORMs embraced the POxO (Plain Ol' Xxx Objects), much of the impedance mismatch problems disappeared. I've used NHibernate on green-field, brown-field and mine-field applications, with NHibernate never missing a step. ORMs are a viable and recommended data access strategy, but not every enterprise is ready (or able) to embrace OSS. In these cases, MS technologies such as LINQ to SQL and the Entity Framework are valid options for teams tired of hand-rolling ADO.NET code. Although each technology has its deficiencies (one so much so, I signed a Vote of No Confidence), the development teams are listening and incorporating feedback. My sincere hope is that these technologies don't get reset or canceled, as we've seen with SQL Server Notification Services and Workflow Foundation. However flawed it may be, efforts by MS to develop ORM technology are a step in the right direction.
3) OSS and MS
CodePlex.com is a site design, run and operated by Microsoft to host open source projects. Several MS projects have made their way to at least open their source code (but not accept patches) onto CodePlex. This again is a Good Thing. I don't expect, nor will I ever care if MS open sources Windows or Office. But it's encouraging to see DevDiv realizing the benefits of OSS. I'm no FreeTard, nor do I see OSS leading society into some hippie magic love-land, but OSS can react more quickly to feedback than traditional closed-source software. What I'd love to see is that one the first questions a new product team at MS asks itself is, "should we CodePlex this one?" Just asking that question shows a huge shift in attitude.
4) LINQ query providers
Last year saw a big push to expand the LINQ providers to the major ORMs, including LLBLGen, NHibernate, and the MS offerings that included LINQ built-in (LINQ to SQL and the EF). The way I see it, the more exposure LINQ query expressions get, the more we'll hear requests for the compiler hooks that made this magic possible made public. While I'm not holding my breath, the increased attention on language-oriented programming and internal DSLs triggered an explosion of innovation. The gut reaction to a powerful new tool is "how will it be abused". Abuse is inevitable, but sharp tools drive innovation. LINQ allows a terse querying syntax that's both easy to read, yet powerful. You'll need to understand the basics of deferred execution and expressions to fully grasp the implications of the LINQ compiler magic, but once you do, many of the LINQ query operators (Where, SelectMany, etc) become quite elegant in LINQ. But only if a LINQ query provider exists.
5) Expanding xDD ideas
DDD, BDD and TDD saw a big expansion into the .NET community in 2008. For the first time that I can remember, MS products were designed with testability in mind. Several of the MS products released on CodePlex also included unit tests. In Rob Conery's excellent MVC Storefront series, Rob shares his journey in creating an awesome MVC application, using a wide variety of design principles and techniques. BDD is starting to come on strong as well, with a BDD mailing list with folks from many communities (Ruby, .NET and Java) participating in the conversation. Software development still has a long way to go to match the maturity of other engineering disciplines, but pushing better design, architecture and development practices will get our industry [BLARG]
6) Internal DSLs and Fluent Interfaces
The ease of parsing XML made it an easy choice for framework developers as a means to provide configuration. As anyone that is familiar with Spring can attest, something went horribly awry. As a programming language, XML stinks. It's verbose, noisy, and stifling. With extension methods, lambda expressions, and expression trees in C# 3.0, a lot of pieces were in place to support some quite powerful language-oriented programming. Although we hit some bumps in the road (Fluent Interfaces aren't supposed to read like Tolstoy), some great internal DSLs in applications like Rhino Mocks and StructureMap show the potential of the C# language. I'm personally looking forward to Fowler's DSL book, whose website already provides a great source of information on DSLs. It's a testament to the power of these ideas to see how quickly they've taken hold.
7) Quitting while you're ahead...or behind
Top 10 lists are lame, even if they sprinkle in the bold. Bogard out.
I was having a spot of trouble the other day trying to get my extension methods to show up in my ASP.NET MVC Views. One of the issues we've run into is trying to make our Views (more) intelligent on the HTML they create. Our Views still only work off of a Model, but they can be much more intelligent on creating the HTML for a single property, or group of properties. However, if we're trying to extend our Views (and not that crazy HtmlHelper), there are at least 6 View types we have to deal with:
ViewUserControl
ViewUserControl<TModel>
ViewPage
ViewPage<TModel>
ViewMasterPage
ViewMasterPage<TModel>
Now, at least the generic types inherit from their counterpart (ViewPage<TModel> inherits ViewPage). However, no real correlation exists between the six types, other than IViewDataContainer for the most part (which the ViewMasterPages do NOT implement). We noticed quite a bit of duplication in our common base behavior for each of these types. Since we couldn't make all of these inherit from the same type, making extension methods off of a common interface seemed to make sense:
public static class ViewBaseExtensions
{
public static string HtmlFor<TModel>(this IViewBase view,
Expression<Func<TModel, object>> modelExpression)
{
// Zomething interesting
}
}
Since I was working in the View, I expected my HtmlFor method to show up as an extension method. Even after some helpful tweets from folks, nothing seemed to work; my extension methods simply did not show up. What was my problem? Here's a simplified example:
public static class FooExtensions
{
public static void Bar(this Foo foo)
{
}
}
public class Foo
{
public void PrettyPlease()
{
Bar(); // Does not compile
this.Bar(); // Not so magic :(
}
}
I defined an extension method for the Foo type, but tried to use it inside Foo. Well, that doesn't work unless I call the extension method directly on an instance of Foo, which leads me to use the "this" keyword. Which is why you see examples like these that make prodigious use of the "this" keyword.
Duplication be damned, all that "this" nonsense just isn't worth it. Especially when you realize that it's only there to initiate the extension method compiler magic.
In the end, this is just another example that extension methods aren't mixins, and I seriously doubt the new C# 4.0 "dynamic" keyword will do the trick. I'm starting to believe that if I want a dynamic language, I should stop looking for a static language to bend yoga-style backwards to be one.
One common question when applying DDD is how to interpret other architecture's concepts of a "model". For example, two common presentation architectures are MVC and MVP. In each of those acronyms, the "M" is short for "Model". So what exactly is this Model? Is it the Domain Model? Presentation Model? Something else entirely?
This question came up recently on the DDD list, and naturally, a slew of wide ranging answers came pouring in. One of the problems with trying to marry these two concepts is that MVC is a rather old concept, with roots almost 30 years old now. The concept of a "domain model" certainly wasn't invented by Eric Evans. However, it takes some sleuthing to understand if the DDD model concept applies to MVC. It's rather clear that the original concept intended that the "M" is "domain model". Randy Stafford pointed this out in one of the replies to the original question, also suggesting an alternative name to the separate Model concept, "Model Model View Controller". Another is the concept of "Model View ViewModel".
Personally, I don't like either of these names. Rather than come up with a different name, the real question comes down to, "should I use my Domain Model as my Presentation Model?" Lately, I've leaned strongly towards NO.
Keeping our POCOs safe
When programming in an MVC architecture, you're often playing by someone else's rules. We strive to make our entities POCOs (Plain Ol' CLR Objects), and completely persistent ignorant. Just as the persistence layer is an infrastructure detail, the View and Controller technology are a similar type of infrastructure, just at the other end of the pipeline. If we create our POCOs, then expect them to be used in the Controller and View (especially as things like arguments to a controller action), limitations on the technologies make our objects look like all sorts of crazy.
Now, no one really suggested making entities as arguments to controller actions, as the MVC technology can't support the richness of our POCO objects. But what about the model passed to the View? Still, because of the limitations of MVC technology, the Model used in a View must look a very certain way for binding to work correctly. For example, in MonoRail and ASP.NET MVC, collections usually need to be arrays, and properties need to be read-write for binding to hook up properly. The same holds in MVP architectures, where the View technology is very sophisticated, but needs a Model that "plays nice" with its expectations. Otherwise, you won't get any of the benefit of the underlying technology.
But we don't want our entities to be sullied by these outside forces. We want to create rich models, untouched by persistence and presentation concerns. But to take full advantage of our presentation/view frameworks, we have to create something else. That "something else" goes by a couple names, both "ViewModel" and "Presentation Model". I really like this concept, not only because of my zealotry for POCOs and DDD, but because it's a natural manifestation of the Separation of Concerns principle.
Separating our presentation concerns
In addition to presentation/view frameworks requiring their models to look a very certain way, often many concepts belong only in the presentation layer. Things like required fields, type checking, and other invariants are a product of the task of interpreting user input. Since all data comes as text over the web, something has to translate these values to types like ints, decimals, enumerations, and so on. Presentation frameworks can go quite a long way to convert types, but what about non-trivial cases?
What about the web form that has an input for Hour and Minute, and you need to combine them? But "Hour" needs to be a real hour, not 5784. That rule has no business in the Domain Model, as my model cares about DateTime, not about individual Hour Minute values.
For things like invariants and validation, I don't want my Domain Model stuffed with invalid values that I then have to check after the fact. But stuff a ViewModel with invalid data, no harm done. I can validate that object by itself, and report the errors back to the user in a way that most presentation frameworks have built-in support for. It's clear that while we'd have to make sacrifices in our Domain Model to make it available in the view, it's often advantageous to simply break free altogether and embrace a completely separate ViewModel.
Crafting a wicked ViewModel
When crafting a ViewModel in MVC land, there are two main "models" you need to worry about: the ViewModel used by your View, and the ViewModel used in action parameters. When designing a GET ViewModel, I craft the ViewModel to contain only what is needed by the View to display its data, and nothing more. Some folks call these DTOs, some ViewModel, but the idea is that you don't pass your entities to the View. Create some ViewModel, map your entity to it somehow, and pass the ViewModel to the View. In our current project, we're using a fluent-y auto-mapped solution, so that we never need to configure our mapping from Domain Model to ViewModel (this should be in MVCContrib sometime soon). The nice thing about this ViewModel is that it can use things like MVC validation and binding technologies, gelling nicely with whatever View framework you're using.
In the action parameter side, here it really depends if the request is GET or POST. For POST, I have only one action parameter, and this is the same ViewModel type that was used to construct the original form. For GET, my rules are relaxed, and I might use Controller technology to bind actual entities to the parameters, so that I don't have to manually load them up myself. In any case, I make a hard distinction between what my Controller uses, and what my View uses. I have no issue with the Controller knowing about my entities. But when it comes to the View, it's generally best to let the presentation/view technology do what it does best and not affect my POCOs.
One nice side effect of this approach is that you can design your ViewModel exactly around each screen, so that one entity could be used on several screens, but you'd never need to compromise on the design of each individual ViewModel. Since each View has its own ViewModel, no other View influences the data it displays. Separation of Concerns circling around again.
Keeping it simple
If you're in a domain where your domain model can be easily used in your Views, you should take a real, hard look at other ways of making your life easier like the Active Record pattern. But if you're having trouble dealing with DDD, it often comes with the impedance mismatch between MVC technologies and the quest for POCOs. You're not doing anything wrong, except trying to force that elegant square peg into that stubborn round hole. By letting MVC frameworks do what they do best, and use mapping to go between these layers, we can shield our model from the concerns of the presentation layer.
Today marks the one year anniversary of the first commit to the MassTransit GoogleCode repository. While Dru Sellers and I initially did some proof of concept work, this day marks the decision to go forward with a standalone .NET messaging framework.
MassTransit was started as a collaborative effort to provide a lightweight messaging framework on MSMQ for .NET applications. Both Dru and I needed a framework for asynchronous messaging to address some work-related application requirements. While MSMQ is provided out of the box, it doesn't directly encourage some good distributed application practices such a loose coupling. Our goal was to abstract the messaging aspects so the services could be built to deal with plain old objects (POCOs) instead of lower level transport messages.
Originally, we both looked at NServiceBus as a way to make this happen. I've followed Udi's blog for a while and have really gained a lot of knowledge from his posts and presentations. However, our lack of experience in Spring.NET, along with a general lack of understanding of all the complexity of such a framework led us down the path of building our own framework.
So that's how MassTransit got started. A year later we're still improving the code and providing useful functionality for developers to build loosely-coupled asynchronous applications. We've even harvested some common functionality (such as the service host, which is now a standalone project Topshelf), and plan to harvest out some additional features in the near future. The great thing about building open source software is the cooperative nature -- even on similar projects. We all learn from each other and build that knowledge into tools that other developers can use and learn from as well.
Let's assume that we are doing the appropriate amount of testing during our development process. If we include TDD, test automation, test engineers and customer acceptance testing, we should find the majority of the bugs in our system before they are released. However, not every bug will be found. There will be some situation that no one thought about before. There will be some special circumstance on someone's computer that hasn't been accounted for. There will be some client data that does fit the expected variance, despite the data being valid. The point is, there will be something that breaks after we deliver the software. Worse yet - it doesn't even take delivery to find bugs. What happens when the software gets to customer acceptance and the customer says that something is wrong, broken or whatever? We simply must account for the inevitable bug fixes and emergency patches in our system.
Our current kanban board, with all it's pipelines and queues, hasn't addressed the need to address problems. But before we get into any changes to the board, we have to define and create the culture of quality that we need in our team.
A Culture Of Quality
There are many different aspects of quality and many different ways to view and interpret quality. The individual specifics, as always, come down to your team, the project and the needs of both. Even with these variances, though, there are a few key concepts that should be found in any culture of quality, including Whole Team / Collective Ownership and Zero Defects.
Collective Ownership
I've talked about this concept before (see above link) and would recommend reading those prior posts. One thing I would like to add, though is that collective ownership can only success when the team takes their individual egos out of the equation. We must be able to accept criticism as a way to improve ourselves and our team. When we let go of our ego, we can be honest with ourselves and others, enabling everyone to own every part of the system.
Zero Defects
This is a subject that I have not talked about before, but is prevalent throughout the continuous improvement philosophies that I subscribe to. Wikipedia lists four principles of Zero Defect methodologies, all of which are paramount to our culture of quality.
Quality is conformance to requirements
Defect prevention is preferable to quality inspection and correction
Zero Defects is the quality standard
Quality is measured in monetary terms – the Price of Nonconformance
Don't be confused by "requirements" in item number one, though. In the world of software development, the word "requirements" has many meanings - not simply the feature list or functional descriptions set forth by our customers. Our teams and processes have certain requirements that are imposed on top of, and into each of the business requirements for the software. These often include the use of source control systems, test driven development, principles like S.O.L.I.D., etc.
Quality Checks in Kanban
Collective ownership and zero defects are only the tip of the iceberg. There is so much more to a culture of quality and so many different aspects of quality to account for. However we define quality, though, our ability to create a culture of quality is necessary for our kanban system to work. Without it, we lose the continuous improvement and elimination of waste that defines Lean. With it, though, we can introduce some specific tools to our process and improve our kanban system by having it handle the errors that are found in our systems.
"a system to notify management, maintenance, and other workers of a quality or process problem"
When an issue is found in our system, we need to notify the team immediately so that the problem can be taken care of. The idea in a manufacturing line is to allow a worker to stop the line when a problem is found. In our grocery store example, andon could be invoked by a shelf stocker noticing a loose nut or bolt on the shelf and then notifying a maintenance person. In software development, andon can take many different forms. We report our issues list during our daily standup. We create issue tickets in our issue management system. If we're lucky and work in a company that supports the idea of a team room, we may just need to look up or turn around and let the team know that we have problems. We could even place an actual red flag on the desk of our developers, testers, customer representatives, etc., and have them raise that flag when they see a problem. Any of these ideas, plus many many more, can all be our andon system.
Andon itself is not intended to be an all encompassing electronic system with metrics and reports and yadda yadda yadda. It needs to be simple. It needs to be easily employed by anyone on the team. And it needs to mean something to the team. If a team member throws their andon card out on the table, the culture of that team needs to be ingrained with the knowledge that work may stop until the problem is addressed.
There's so little to andon, yet so much more than what I've described. However andon is enabled, it is critical to our zero defect policy in software development.
Jidoka
AKA "Autonomation", AKA "Automation with a human touch", AKA "intelligent automation", AKA ...
"Autonomation prevents the production of defective products, eliminates overproduction and focuses attention on understanding the problem and ensuring that it never recurs."
I've talked about Jidoka in previous posts and would recommend reading them, at this point.
I don't have much else to add, other than to say that Jidoka and Andon go hand in hand. Automated build servers (such as CCNet, TeamCity and many others) can often combine Andon and Jidoka for us by giving us instant visual feedback when something is broken. I've also recently set up BigVisibleCruise in my team area, giving even the casual observer the knowledge of whether our builds are broken or not.
Applying Andon and Jidoka to Our Kanban Board
Once we have the concepts of Andon and Jidoka in our team and culture, we can use these tools to generate issue cards and then look at a few possible changes to our kanban board to account for them. The three basic methods that I have seen used include:
Creating an Emergency Fixes pipeline
Tacking a smaller bug notice onto an existing card
Putting a Bug card in the backlog
I'm sure there are other alternatives, too. In my current team, we use the first and third method and are considering the second one as well.
Options two and three essentially require no change to our kanban board. Implementing option two is a distinctive way of visually attaching a bug notice to one of the cards in our system. This could be done with little bug stickers, little red cards, or any other visual indicator that the team agrees on. Option three also needs something distinctive. Since we are creating an entire card for the bug, though, the entire card should be distinctive. I would recommend using a card that is colored red to signify issues. I would also recommend prioritizing the bug to the top of the backlog queue, when using option three. This will ensure that the bug gets worked as quickly as possible.
Option number one can also make use of number two and/or three. When we move a card into the Emergency Fixes pipeline, we may want it to be distinguishable as an issue by tacking on our bug symbol or by using a colored card.
Emergency Fixes Pipeline
Depending on the complexity or severity of the bug, we may want to include Analysis and Customer Acceptance in our Emergency Fixes. With andon and jidoka in mind, we will want to ensure that we fix any emergency issue immediately. This is not always possible, however. The customer may decide to delay the fixing of an issue for whatever reason. This leads us to only needing a single pipeline for Emergency Fixes, letting us set our limit to one.
We can easily add an Emergency Fixes pipeline to our kanban system, placing it directly underneath our existing WIP pipeline. This special pipeline can be designated with a name, color code, or other marks as needed.
If you are supporting production releases, you may also need to include a Delivery queue specifically for emergency fixes. This would allow multiple fixes to be compiled into a single patch release. There are other configurations to this, of course. As always, you will need to find what your specific team needs and create your process to suit.
Where Do We Go From Here?
With an Emergency Fixes pipeline in place, our kanban system is now set up to handle just about every situation that we will encounter. However, this does not mean that our system is perfect or truly complete. No process, no matter how well defined it is, is worth anything if the people running the process do not believe in it. I've said it before and I'll continue to say it - never stop improving your process. Always be mindful of waste, friction, smells, problems or whatever you want to call it. Inspect, adapt and continuously improve your process. Perfection is a journey, not an end-goal.
Stay tuned to my Adventures in Lean series, as I continue to explore the various aspects of lean software development in my own team and company culture.
C# 4.0 brings the idea of named parameters to C#. While optional/default arguments are of questionable value (this is from my VB.NET days), named parameters can really clear up the meaning of a method call. We're already faking named parameters, as seen here in the ASP.NET MVC codebase:
Obviously the above example isn't compile-time safe and comments lie to you, so it will be nice to be able to provide named parameters, especially when the number of arguments grows in a method call. Something to look forward to.
This year, 2008, was a year that saw many a new term or expression get ingrained in the minds of us .NET developers. Quite a few I'd rather not see in the next year, as they've overstayed their welcome. Some are catch-phrases, some are misapplied concepts, and others fall into the "make my brain hurt" category. Regardless of where they came from, here are ten .NET things I'd like to see make a graceful exit in the new year:
1) Open Spaces
I love me some open spaces, as I've had some great experiences with both the Austin ALT.NET Open Space and the recent KaizenConf open space. But somewhere along the way, a great idea got usurped, strangled, mangled and mass-produced into some kind of buzz-word hippie-fest where we sit around in circles and sing kum-by-ya. There's a book on the subject, yet, just like Agile, a non-agenda for a conference became associated with Open Spaces. CowboyConf != Open Space. What comes after FooBar Conf? Wait, I know, it's ScheißenConf.
2) Any MS ORM
First was the EF Vote of No Confidence, then the realization that EF was worse than we thought it was, then a little LINQ2SQL love, then a sad realization that L2S was going away. A popular, widely used, commercially supported ORM for .NET already exists. It just doesn't come from the left coast.
3) Gloryhounds
Speaking of MS ORMs, has anyone else noticed the breeze blowing from all the hot air surrounding the new "experts" in the nascent technologies coming out of Redmond? If it's not in Beta yet, you can't be an expert unless you're on the dev team. Being an expert in a product doesn't mean you're an expert in the field, that's two entirely different purviews. Any time a new acronym rears its ugly head, you can bet there are several book deals, speaking engagements, articles and consulting gigs lined up to take advantage of a yet-to-be-proven technology. It would be amusing, if it didn't drown out the useful conversations.
4) LINQ 2 Your mom
LINQ query expressions (not just the extension method operators) opened a whole new world of internal DSLs for .NET developers. Unfortunately, the compiler hooks to open up the "from...where...select" goodness were not made public, so the really interesting boo-like applications were left in the dark. Instead, we get treated to weirdness like LINQ 2 Amazon and LINQ 2 WoW. What was that Jurassic Park line? "You were so preoccupied with whether or not you could, you didn't stop to you if you should." Unless you really understand what the LINQ operators are doing under the covers, and what the underlying IQueryProvider object is doing underneath the covers, you're just creating a hot mess.
5) FooDD
We have enough acronyms driving our design. DDD, TDD, BDD, SausageDD, let's call the whole thing off. Unless you can define what these concepts/architectural styles describe, imply, infer in one volume, let's just not talk about it. Underscores in a method name don't count as a sea change, paradigm shift, quantum leap or revolution. The only caveat is if there is a Big Blue Book on the subject, which means it's a game changer. Cherish that bible.
6) Feeding the trolls
Productive: (adj) Yielding favorable or useful results; constructive. There are certain folks in our community that, when provoked, will actually respond to your inanity. Do us all a favor, just shut up, and don't provoke.
7) Fluent interfaces
Yes, you found the magical mystical extension method! It's a miracle! Now put that hammer down, my face is not a nail. Just like #4 in this list, we've taken a useful idea in internal DSLs, and fouled it up just like you knew we would. You know what's a great DSL? HTML. If I have to have two dozen characters, parentheses, angle brackets and percent signs to create "<form>" tag, something went awry. Clever is rarely simple, and unless that fluent baloney improves the situation, you're a glorified code-sturbater.
8) The BCS
Nothing to do with coding, except that computers help decide who is in the NCAAF championship, where millions of dollars are at stake. One thing can be certain, Mizzou will never, ever vie for the title. Ever.
Nor Texas Tech.
Just thought I'd throw it out there, as I know someone reading this has the pull to make it happen.
9) Fear
It's no coincidence that one of the XP values is Courage. Though we pride ourselves in pushing the envelope and branching out, why are we the quickest to bash a new concept? If you signed the EF VoNC without even looking at EF, you're subtracting, not adding. Walk a bit in those other shoes before dismissing the framework, tool, concept or idea. Courage is trying something new despite all your inclinations not to. Think TFS is garbage? Try it out. Think SVN is for pinko FSF weirdos? Give it a week. Funny how the loudest protests come from those with the most ignorance.
10) Bold typeface in blog posts
One of my bigger pet peeves is anything in bold. It's a cheap trick to grab attention, yet it always works. Yes, Atwood does it all the time and although it grabs attention, it's the blogger equivalent of that dork that "quotes" "all" "his" "words". The last thing we need is another cookie-cutter Atwood knockoff.
11) Top ten blog posters that can't count
The worst offenders of all are those morons that create top-ten lists to grab attention and readers, yet can't count. Oh wait...
I’m really trying not to be negative with this post. The people behind Oxite are good folks and don’t deserve any hate. They have made a mistake, though. A mistake I think needs to be corrected and requires some immediate action.
My advice, if anyone cares:
Oxite should be pulled immediately until the larger issues (including and especially the major security vulnerabilities) can be addressed satisfactorily.
Oxite should NOT be used as any sort of Best Practice or official guidance by Microsoft. The Oxite folks have been VERY open and clear that this is NOT anything official or supposed to be recommended guidance. Unfortunately, though, many WILL take it as that no matter how many disclaimers they have to click though.
If you are not familiar with ASP.NET MVC or MVC in general, you should avoid Oxite for the time being as there are several anti-patterns that may set you off on the wrong footing in the future.
I would prefer not to go into any specific problems Oxite may have. From my days as a consultant, I know that this will be taken as gospel by many and used off-the-shelf with little modification to build many production web applications. This could be a minor disaster for many companies and other organizations who may be the unwitting victim of its problems. This may seem overly dramatic, but if you have not spent any significant time consulting in the .NET space and aren’t aware of things like PetShop or the various ASP.NET quick start applications then trust me, it could become that bad – and fast.
The folks who are involved with Oxite’s development are open to communication and are engaging the community and are working with everyone to try to balance the needs of everyone. However, until its most major issues (including significant security vulnerabilities) can be addressed, I think it would be best to pull it or lock it down on CodePlex to prevent it being referenced by the community and any more confusion spread.
We all have an opportunity to improve the .NET space here and I think we should take this opportunity. ASP.NET MVC will soon be released, and I’d hate for the first major impression of its usage from Microsoft be problematic.
Finally, I appreciate the efforts of the Oxite-involed folks and the sincere attempt at openness and contribution. This is a significant contribution and we are very thankful for this. As much as many members may be upset about Oxite, underneath, I think everyone is appreciative (though we/they may have a bad way of showing it) that this even happened in the first place. This is definitely a step in the right direction. The next step, I think, is to crank up the quality a little more so we can all have our cake and eat it, too!
And on the subject of the deficiencies of attributes, there are a few more things I'd like to accomplish, but cant. First on the list, generic attributes:
// Boo C# compiler, boo!!!
public class GenericAttribute<T> : Attribute
So many times I'd like to have some kind of generic attribute, whether for validation, for action filters, the list goes on and on:
error CS0698: A generic type cannot derive from 'Attribute' because it is an attribute class
Well that's helpful! It gets worse. Let's try a more interesting attribute value for an attribute that takes a value in its constructor:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class FineThenAttribute : Attribute
{
public FineThenAttribute(int value)
Most of the time, I'll put a hard-coded value into the constructor. Sometimes, I'd like for that value to come from...somewhere else:
public class PrettyPlease
{
public const int Five = 5;
public static int Four = 4;
[FineThen(6)]
[FineThen(Five)]
[FineThen(Four)]
public void Method()
The first two compile just fine, as the values passed in are constant values. The third attribute does NOT compile, however. I get yet another roadblock:
error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
One time I tried to get extra fancy with attribute decorators. Silly me! This attribute definition compiles just fine:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DelegateTypeAttribute : Attribute
{
public DelegateTypeAttribute(Action jackson)
But it's impossible to use! None of these attribute declarations compile:
public class WithACherryOnTop
{
[DelegateType(() => { })]
[DelegateType(MatchesAction)]
[DelegateType(new Action(MatchesAction))]
public void Method()
{
}
private static void MatchesAction()
Blech. Every time I try and do something mildly interesting with attributes, blocked by the CLR!
I've recently had reason to ask questions on the Oslo and WCF forums and in both cases my posts got responses quickly (which is more than can be said for the WCF REST starter kit forum which is dead as a doornail). However in both cases a strange thing then happened, someone else immediately marked the answer given as being THE answer to my question.
So instead of the person asking the question getting a chance to decide if the answer was suitable, or whether they wanted more information (in both cases I did), a higher authority decided (presumably the person providing the answer). Why does this matter, well apart from anything else answered questions get a tick when displayed in the list and who in their right mind is going to want to help answer an already answered question?
To me this seems like a big community anti-pattern, but it all makes sense when you read the sticky post on marking answers in the WCF forum. One key line is:
Our forum gets 'measured' based on how many unanswered questions are in it at any time and we work hard to keep those numbers to as low a level as possible. By marking answers, others get a more accurate understanding of how well (or badly) things are going on the forum.
Incentivise people to mark questions answered and thats what they do, who whould have thought?
Mind you on the right handside of the front page of the forum you also get a list of the "Top Answerers" which is also an amusing idea and probably not one I'd want to see on any forums I use regularly.
Unit tests, with TDD in particular, are the most efficient way I've found in creating behavior for my application. For lasting value, beyond just the safety net of "if I change something, will something break", requires extra discipline, and a more refined manner in which we go about doing TDD. One of the most frustrating aspects of TDD done wrong is dozens of unit tests that provide no other value than they might fail.
Back when Scott and others were refining TDD into Context/Specification BDD-style, I remember him posing the question, "if we actually treat tests as documentation, what is the result?". For a lot of unit tests, that documentation is a muddled, miserable mess. Nothing can be more frustrating than a failing unit test that provides zero insight into why the test exists in the first place.
My first year or so of doing TDD produced exactly that, a mess. No insight into the what or why of my system's behavior, but merely a retrospective look on what each individual class did. But by adding a few rules, as well as personal guidelines, I've noticed my tests have started to provide what I really wanted – a description of the behavior of the system. These rules injected that value in my tests that would have otherwise made the tests just dead weight, code I avoided after I wrote them.
Rule #1 – Test names should describe the what and the why, from the user's perspective
One way to do this easily is the Context/Observation(specification) naming style. I'm not the greatest at explaining exactly the BDD style, I'd rather defer to JP Boodhoo, Scott Bellware's article, Aaron Jensen and Raymond Lewallen on this one. But the general idea is that an outside developer should be able to read the test/class name, and clearly understand what the intended observable behavior is, for a given context. Here's a bad, bad example:
[Test]
public void ValidationShouldWorkCorrectly()
Validation should work correctly. Hmm. "Correctly" is in the eye of the beholder. "Correctly" depends on the circumstances. "Correctly" depends on your definition of "correct". The kicker is, if this test fails in the future, how will I know if it is because the test is wrong or the code is wrong? I won't. And at that point, I have to make a judgment call on whether the test is holding its water or not. Sometimes, I'll just make the test pass, sometimes I'll remove the test, and sometimes I'll spend a lot of wasted time trying to figure why the heck the test was written in the first place.
That's perhaps the most frustrating aspect. A unit test that was supposed to provide value when it failed, instead only caused confusion and consternation.
Rule #2 – Tests are code too, give them some love
Whether you think so or not, you will have to maintain your tests. You don't have to model your tests like you would, but duplication matters in your tests. Do yourself a favor, right now, go order the xUnit Test Patterns book. TDD is a craft, and the xUnit book is a How-To. Veteran or neophyte, you'll learn a new angle that you didn't know before. One thing it showed me is that tests are code, which I have to maintain, and showing them love pays almost just as well as it would refactoring production code.
Refactoring tests does many things for you:
Eliminates test smells such as brittleness, obscurity or erraticism, and more
Provide insight into common contexts and behavioral connections (if several tests have the same setup, then their assertions/observations are related somehow)
Reduces nausea
I hate, hate long, complex tests. If a test has 30 lines of setup, please put that behind a creation method. A long test just irritates and leaves the developer cross-eyed. If I don't have long methods in production code, why would I allow this in our test code? A test has three parts: Setup, Execute, Verify (and sometimes Teardown). Following the Context/Specification test pattern already groups these three parts for you, so you can't get yourself in trouble.
Bottom line, tests are code, love them, and they'll love you back.
Rule #3 – Don't settle on one fixture pattern/organizational style
This assumption killed me for a quite a long time. For some reason or another, I always assumed that I should have a test fixture pattern of One Class, One Fixture. One problem of course, this makes understanding behavior of the system as a whole, and of its parts, quite difficult. Systems with hundreds of classes aren't very easy to see how the pieces fit, and finding usages and following control flow just doesn't cut it. But aren't our tests supposed to be documentation? Aren't they supposed to describe how the system works?
If you're blindly following one fixture per class, that ain't happening.
One fixture per class leads to some pretty crappy test fixtures. I've seen (and created) test fixtures literally thousands of lines long. That's right, thousands. We would never, ever, ever tolerate that in production code, why is our test code exempt? Simply because we assumed that there is one pattern to rule them all. Well, I don't construct every object with a no-arg constructor, why should I tie both hands behind my back with One fixture pattern?
Or better yet, why just one organizational pattern? Do unit tests have to match the existing code base file for file, class for class, just with "UnitTests" somewhere in the namespace? That creates absolute insanity.
Sometimes classes have a lot of behavior that belongs in one place. Big fixtures can indicate I need to refactor...unless it's my fixtures that are the problem. Repositories that provide complex searching are going to have a lot of tests. But do yourself a favor, look at alternative grouping, such as *gasp* common contexts. The really cool thing about exploring alternate organization is that it fits perfectly with Rule #2. Explore other organizational styles and fixture patterns. Try organizing by user experience contexts, not strictly by classes.
When you start seeing behavior in your system not through your classes' eyes, but from the expected user experience, you're on the road to truly valuable, descriptive tests.
Rule #4 – One Setup, Execute and Verify per Test
Another side-effect of blindly using one fixture per class are tests that either:
Have a lot of asserts
Have a lot of Setup/Execute/Verify in one test
Tests should have one reason to fail. Asserting twenty different pieces isn't one reason to fail. If we're following Rule #1, that test name is going to get very, very long if we try and describe all of the observations we're doing. Have a lot of asserts? Pick a different fixture pattern. Test fixture per feature and test fixture per fixture are great for breaking out separate assertions into individual tests. The better I can describe the observations (from the user experience side), the more the code being created will match what is actually needed.
The multiple execute/verify in a single test is also indicative of assuming one fixture per class. Here's one example:
[Test]
public void ValidationShouldWorkCorrectly()
{
var user = new User();
user.Username = " ";
user.IsValid().ShouldBeFalse();
user.Username = "34df";
user.IsValid().ShouldBeFalse();
user.Username = "oijwoiejf^&*";
user.IsValid().ShouldBeFalse();
}
Blech. Not only does the test name suck (which with this many asserts, did we expect any different?), but I have zero insight into the different contexts and valid observations going on here. What if the second assertion fails a month from now. How exactly am I to know if the test is wrong? Or the code is wrong? Another headache.
Whatever test fixture pattern you go with, you have to stick with one Setup Execute and Verify per test. If your current fixture pattern doesn't allow you to adhere to this rule...change patterns.
Keepin' it clean
Tests can be documentation, but only if you try. If you're in the "write and forget" category, your tests will become a deadweight, some even causing negative value. Thousand-line test fixtures, hundred-line tests, incoherent and illegible tests, bad test names, all of these both contribute waste and detract from the maintainability of your system. So what, a test failed. Congratulations. But can you understand why it failed, what behavior is being specified, and why it was important under what circumstances? If not, what value are your tests giving you, except for a future headache?
I'm currently knee-deep in NHibernate custom listeners, for the purpose of adding auditing to our application. Besides current documentation being plain wrong on the subject (I'll update on the solution in the future), I hit a rather frustrating snag around the instantiation of my custom listener. One of the shouldn't-be-frustrating-but-yet-it-is side-effects of committing fully to Dependency Injection and Inversion of Control Containers is all the code out there with "extension" points that don't allow custom factory implementations. Sure, your framework allows for custom Floogle providers. But how does it create the IFloogleProvider implementations?
In the NHibernate code, I found this snippet that instantiates custom listeners, which are configured through an XML configuration file:
public void SetListeners(ListenerType type, string[] listenerClasses)
{
if (listenerClasses == null || listenerClasses.Length == 0)
{
ClearListeners(type);
}
else
{
var listeners = (object[]) Array.CreateInstance(eventListeners.GetListenerClassFor(type), listenerClasses.Length);
for (int i = 0; i < listeners.Length; i++)
{
try
{
listeners = Activator.CreateInstance(ReflectHelper.ClassForName(listenerClasses));
}
catch (Exception e)
{
throw new MappingException(
"Unable to instantiate specified event (" + type + ") listener class: " + listenerClasses, e);
}
}
SetListeners(type, listeners);
}
}
One. glaring. problem. It uses Activator.CreateInstance to create the instance, which internally calls the default constructor. As a developer for custom listeners, this means that we need to define a no-argument constructor:
public class AuditPreInsertUpdateEventListener : IPreUpdateEventListener, IPreInsertEventListener
{
private readonly IUserSession _userSession;
public AuditPreInsertUpdateEventListener(IUserSession userSession)
{
_userSession = userSession;
}
public AuditPreInsertUpdateEventListener()
: this(ObjectFactory.GetInstance<IUserSession>())
{
}
When doing constructor injection, you normally don't create this constructor. Frameworks like ASP.NET MVC, WCF and others provide hooks for custom factories or instance providers. Containers receive a request to instantiate a component, and the container will create the dependencies, call the right constructor and pass those dependencies in.
From a developer's perspective, it's very helpful not to have to define any unnecessary no-arg constructors, as it muddies code. There is at least one solution out there, such as the Common Service Locator project. Now, NHibernate does allow programmatic configuration, so I do have the option to create the instances myself and pump them into NHibernate. All I've really done is eliminated the possibility of using XML configuration, which isn't too fun if you're doing things like XML manipulation as part of your deployments.
For framework developers, something like Activator.CreateInstance should be a red flag, that maybe we should provide alternate means of instantiation. As IoC containers become more mainstream, I think we'll see more changes in major frameworks to support containers out-of-the-box. Until then, pointless dual constructors it is.
People haven't really heard from me in a while, and there's a few reasons for it, but I'm about to talk about the major one.
Sometime around the Kaizen Open Space in Austin, just a little before actually, I stopped being able to look at my computer screen. On an average day, 5 to 10 minutes looking at the screen and I wanted to gouge my eyes out. I was getting severe headaches. I was extremely tired, or at least, my eyes felt like they were. I was irritable. My eyeballs itched. It sucked man.
So that meant very little computer time on most days. No twitter. No blogs reading or writing. No writing code. Basically I kept the time limited to email that I needed for work, and the bare minimum time in visual studio. Since I'm all manager-y now, I don't get to write a lot of code anyway, so that kind of just worked out. During that time a new WoW expansion came out, and trying to keep up with my friends was a chore, and most of the time I was online I was actually not looking at the screen. (Which is a shame, because Blizzard put a lot of work into it and it's very visually stunning.) When I did have to spend non-trivial time in the IDE, I just dealt with the pain.
So this has actually been happening off and on to me since late 2004. At one point I bought grocery-store reading glasses that seemed to help just so I could write code and get through the day. But the problem kept going away after a couple of weeks, and, me being me, I just let it go. But this time it was way worse than ever, and going on 2 months duration. I broke down and finally went to an optometrist (with much prodding from a close friend).
Now comes the part of the story where I start coming to grips with the ravages of time. Having spent all my life with perfect vision, I was unprepared for an eye test where I couldn't read the bottom two lines of the chart. The tech actually got impatient with me because I stubbornly sat there trying to will my eyes to focus on those letters, but it didn't happen. Long story short: I had somehow gone from perfect vision to nearsighted, farsighted, and a slight astigmatism. Were I the designer of the human body, nearsighted and farsighted would cancel to an acceptable middle state. Anyway, I now am bespectacled at all times except when sleeping. Advancing age and upwards of 15 hours of computer time per day were to blame said the doctor man, and so my glasses also have some special whosamawhatsit on the lenses specifically for computer work.
Were it not for the fact that I need the computer to live I might have been content to let this eye thing go until they got fed up and leapt to their deaths leaving me with gaping sockets. But now, well, last week I paired all day 2 days in a row and was ready for more. And the headaches are gone. And I don't feel tired anymore (not from sitting around on the computer anyway). And while I'm still not completely adjusted to them (my eyes are still pretty fatigued by the end of the day), I know the glasses are helping. And I'm kicking myself in the ass for ignoring the problem for so long.
Your health affects your livelihood brothers and sisters of the sedentary knowledge-worker persuasion. I know when I put on a few pounds it's reflected in my productivity and I can guess what the scale will say by my average level of energy change over the course of a few days. And when I'm not getting enough exercise my mood is unpredictable, my irritability and anxiety are high, my posture suffers and my time at the keyboard becomes physically painful. And when I eat poorly for a few days my code quality measurably suffers. And when my eyes don't work, well, I'm not good for anything at all.
So, in this upcoming time of annual stock-taking and resolution-making, this is my reminder to you and me that your health matters, and your productivity as coders and managers and members of society is very closely linked to your physical well-being, so keep it in mind. And stop pretending you aren't getting older, and make those doctor appointments to keep things in order. You are the most legacy system you'll ever work with, so you need to take extra care to keep it performing optimally.
The Domain-Driven Design book (or, the Blue Bible), is chock-full of patterns. Software patterns, team patterns, integration patterns and so on. As a consequence, many readers might assume that DDD requires these patterns, that you must apply these patterns, and not following these patterns means that you're doing DDD.
But DDD is an architectural style, not a blueprint for building applications nor a pattern cookbook. Because DDD is an architectural style, we can't make any of the following assumptions when applying DDD:
Implementing certain patterns implies we're applying DDD
Applying DDD means we implement certain patterns
One question Rob Conery asked me during a conversation on DDD was, "How do I recognize an application built with DDD?" We've already noted that you can't look towards a set of patterns, so how do we recognize one? A DDD application is one whose design is driven by the domain, hence "Domain-Driven Design".
If I look at a clean domain model, well-factored with explicit responsibilities, I as a lay person could make no judgment on whether the application followed DDD or not. If however, I talked to the domain experts, learned about their domain, learned how the domain knowledge was distilled, I would then go back and look at the application to find if it models the domain. If the development team calls a concept an "OrderForm" and the domain experts call the concept a "ShoppingCart", then immediately we see an impedance mismatch. The team is not sharing the same model language with the domain experts, losing the benefits of a Ubiquitous Language. They are likely not following DDD.
Another tactic to recognizing DDD is have both the domain experts and team explain the domain. Counting the number of clarifications and special cases, "well, except, but" and "we" versus "they" provides a good indication that the domain experts and team are not on the same page.
The patterns laid out in the DDD book are a guide to help achieve the true goal of DDD: a shared model expressed as software. Concepts like Entities, Repositories and others are in place to reinforce the architectural style of DDD by defining explicit responsibilities of recurring patterns. Like other pattern languages, the DDD book creates a common Ubiquitous Language for practitioners of DDD, both lowering the barrier to entry and creating a basis for comparing notes between disparate teams and developer communities.
DDD is certainly easier to implement with the patterns described in the DDD book, but they are not required. We can use the Active Record pattern and follow DDD. We can use the Entity Framework or LINQ to SQL and follow DDD. We can use hand-rolled ADO.NET, constrained to a 5-year-old legacy application, and follow DDD. We can eschew Services for eventing, and follow DDD.
DDD is an architectural style that encourages model-driven design and a domain-driven model. Following this style is following DDD, and merely implementing patterns only indicates that we can implement patterns.
In part 2 of my Kanban in Software Development series, I talked about completing a kanban board with queues, order points and limits. We saw how to take a complete development pipeline and work with a team, its processes and its bottlenecks. In the end, we had a kanban board that could easily represent the processes of the fictional team that we outlined.
One of the questions that I've often asked about a kanban board is how anyone would know when work in one column is done and ready to be pulled into the next column. For example - if a kanban card is sitting in the Analysis column, how does a developer know when that card is done so that they can pull it into Development and start coding it? I found the answer to this question when I was at the Kaizen Conference in October. Jef Newsom did a workshop on kanban and we ended up with this same question, and a solution.
A Pipeline for Analysis - WIP and Done
To facilitate the visualization of the difference between work in progress and work that is ready to be pulled to the next column, we can use the concept of a pipeline and split our existing queues into a WIP and Done step. For example, we want developers to pull work from the Analysis queue into the Development pipeline. We can show which cards are ready to move by splitting Analysis into sub-columns of WIP and Done.
When an Analyst is ready for work, they would pull from the Backlog into the Analysis / WIP column. When the analysis work is done and the card is ready to go into development, the card would be moved into the Analysis / Done column. Since we are wanting to maintain the concept of a queue for the overall Analysis column, we have create the WIP and Done subdivisions as a pipeline (noted by the dashed line). This allows us to keep our order point (3) and limit (5) in place for Analysis, and know what work is ready to be pulled into Development.
Applying Pipeline per Queue Across The Board
Not every queue needs to be a pipeline.
Consider the Backlog - the customer is placing the prioritized list of features in this column. The cards in this column exist so that the analysts will know what work needs to be done - not because any work needs to be done in this column, explicitly.
The Delivery column may not need a pipeline, either. If the delivery process is composed of sending an installer package to the customer, then there is no real work to be done in this column aside from sending that package. However, if there is some specific integration work (say, changing a web.config file) that needs to be done, we could include a WIP and Done pipeline for delivery. For this simple example, we'll say that there is no configuration change needed. Let's assume that the installation package changes all the needed configuration files based on user input.
With all of this in mind, we can apply our WIP and Done pipeline to the Analysis and Customer Acceptance column