Over the years I have noticed a lot of agile anti-patterns during projects. Wrongly used agile approaches, dogmatic use of agile approaches, agile-in-name-only. Recently I have presented a talk at a number of agile and software development conferences that demonstrates patterns of agile misuse. These conferences include Agile Open Holland (Dieren), Camp Digital (Manchester), GIDS (Bangalore), ACCU (Oxford) and Jazoon (Zurich). Anyway, here’s the slide deck. Enjoy.
as the Channel 9 website says: using real-life code examples Sander will demonstrate how to model, generate and build smart use cases and introduce the positive impact smart use cases have on your layered software architecture.
Anyway, here’s the video for my DevDays 2011 session:
From April 12-14 the next edition of Microsoft’s MIX Conference will take place in Las Vegas. I’ve sent in two proposals for the Open Call. Today heard that both proposals made it through the first cut, which means they’re open for public voting (you don’t have to be registered). It would be great if you would cast your vote for my proposals on how smart use case can drive web development, and on how frameworks can kill your projects.
Proposed talk 1: How smart use cases can drive ASP.NET web development
Use cases have been around for many years describing the requirements of software development projects. By developers, use cases are often seen as too abstract and too complex to develop code from. That is, until now.
- Please vote for this session at
During this interactive talk speaker Sander Hoogendoorn will demonstrate how to model, generate and build smart use cases. This great technique allows projects to model use cases at a much more pragmatic, and low-granular level, that can be implemented straightforward and directly into our applications, such as ASP.NET or Silverlight web application. The speaker will introduce both the positive impact smart use cases have on your layered software architecture, as well as the design patterns required to implement smart use cases. This talk comes with many real-life code examples.
Proposed talk 2: How frameworks can kill your projects
When it comes to .Net development, more and more frameworks enter the market. Both from Microsoft and from open source. think of ASP.NET MVC, Castle, WF, Entity Framework, Unity, Linq2SQL, ADO.NET Data Services, WCF, nHibernate, Spring.NET, CSLA, NUnit, Enterprise Library or ADF.
- Please vote for this session at:
Once a project chooses to apply one or more frameworks, trouble begins. What if you require features that aren’t implemented in the framework? What if you decide that another framework would have been better and want to switch halfway your project? What if the author of your favorite open source framework suddenly stops developing? What if the framework contains bugs or omissions? And what if a new version of the framework is released that is implemented totally different? These and many more everyday problems will cause your project to come to a halt, or at least make you perform serious refactoring.
During this highly interactive talk Sander Hoogendoorn, chief architect of Capgemini?s agile Accelerated Delivery Platform, and member of Microsoft?s Partner Advisory Council .NET, demonstrates pragmatic architectures and patterns that will help your projects to stay away from framework issues, and how to keep code independent of framework choices. Sander will present models of layered architectures, and apply bridge patterns, managers-providers, dependency injection, descriptors, and layer super-types.
Of course, the speaker will illustrate these insightful patterns with lots of demo?s and (bad) code examples using blocks from Microsoft?s Enterprise Library, NHibernate, Log4Net, and the Entity Framework. Delegates benefit by learning how to improve the structure and quality of their software architecture and code, and how to avoid the pitfalls of applying frameworks to .Net software development.
On November 25 and 26 I will present the 32th edition of an intense two-day workshop on the pragmatic use of UML modeling techniques (and beyond) with lots of hands-on exercises.
Participants modeling activity diagrams with smart use cases
During this workshops we will go through the following subjects in depth:
- A brief introduction of UML and its modeling techniques
- A pragmatic YAGNI approach to modeling business processes and requirements.
- Modeling hierarchical and chronological business processes.
- Modeling traditional and smart use cases.
- Modeling activity diagrams (for use cases).
- Identifying test scenario’s for (smart) use cases using activity diagrams.
- Modeling the user interface.
- Modeling class diagrams.
- Domain driven design.
- Interaction modeling. Bringing together an applications structure and behavior, based on a pragmatic use case driven software architecture.
- Modeling service oriented projects using smart use cases.
- Modeling in agile projects.
- A brief introduction to model driven software development.
[Session ARC205 at Microsoft TechEd Europe 2010 in Berlin]
Use cases have been around for many years describing the requirements of software development projects. From a developer’s point of view, use cases are often seen as too abstract and too complex to develop code from. Until now, that is.
During this interactive talk, speaker Sander Hoogendoorn will demonstrate how to model, generate and build smart use cases.
This great technique allows you to model use cases at a much more pragmatic, low-granular level, enabling them to be implemented simply and directly into applications such as ASP.NET or Silverlight. Using many real-life code examples, the speaker will introduce both the positive impact that smart use cases have on your layered software architecture, as well as the design patterns required to implement them.
To cut to the chase, those of you who have worked on enterprise or service oriented projects before already know this. These types of projects are characterized by a large number of organizational, functional and technically complicating factors. Enterprise software development projects are surrounded by a large number of complicating characteristics and challenges:
- Many different stakeholders. Projects have many different parties in the organization that are involved. Often such project realize goals for different departments or divisions in the organization. As an example I once coached a project that served 22 different departments. Quite often these departments or division try to achieve overlapping or even contradicting goals.
- Business processes. In general enterprise projects (re-)implement (parts of) business processes that are key to the organizations success, rather than building a straightforward web application.
- Complex software architectures. Most likely, enterprise projects implement business processes in a complex IT landscape or architectures. Think of landscapes that host many different applications all tied together.
- Many external dependencies. Often, such complex IT landscapes contain components that are outside of the organization. Services that run outside the corporate firewall, with other parties. A well known issue to agile projects is that of availability. We need the new version of the service in this iteration, but the other party runs a waterfall project that will not deliver this year.
- Changing requirements. In enterprise projects, requirements change continuously. Either by changing insights during the project, but more often due to changing legislation or regulations.
- Many different types of deliverables. Traditionally these projects count many different types of deliverables. Think of service description, user interface, process models, non-functional requirements, workflow, project plans, test plans and many, many others.
- Multiple roles. Large organizations count many different roles that are involved in projects. There are business analysts, enterprise architects, information analysts, testers, release managers, SAP developers, web developers, SAP functional consultants,
Thus these project often become a mission impossible, and fail in large numbers. Such projects are difficult to estimate, therefore hard to plan. For developers it’s tough to build the software, often with many new techniques and technologies, and even worse for testers, these projects are sheer Impossible to test well. This is where a structured agile approach should come to the rescue.
Being agile in enterprise projects
Independent of the approach that is applied, or the agile process that is followed, being successful in agile projects follows a number of key principles:
- Multi-disciplinary teams. Instead of different roles such as analysts, designers, developer and testers working in consecutive stages in a project, all roles collaborate in implementation individual work items from heads to tales.
- Short iterations. Project work in short time boxes, in most cases 2, 3 or 4 weeks. During such an iteration, a number of work items is planned, completed and evaluated – with different terminology in use with different agile processes.
- A small standardized unit of work. Projects requires a small unit of work, to be able to deliver a number of them in a single iteration. Large work items such as traditional use cases therefore do not apply well.
- Testing from day one. Testing is an important discipline during agile projects. Testers are involved from the very first iteration, when the first work items are realized. Note that testing in most projects goes way beyond the obvious unit testing – which is actually a developer technique.
- Continuous measurement. Successful agile projects continuously measure their progress. Since they are always delivering individual work items, measurement in agile projects is easy.
- Continuous (process) improvement. At the end of each iteration not only the realized work items are evaluated, but also the project approach itself is evaluated, leading to highly effective project approaches.
Scrum in a nutshell
When organizations first start with agile projects, Scrum is often the process of choice. At this point in time, Scrum is by far the most popular and best known agile approach. Scrum is a straightforward lightweight agile process that offers a collection of highly applicable principles and techniques for short iterative projects and is easy to understand. It also specifies a remarkable terminology with scrums, sprints and user stories.
In a nutshell, Scrum is characterized as follows:
- Sprints. Projects are divided into iterations, called sprints. In general these are 2 to 4 weeks.
- Backlogs. Work items still to be done during a project reside in a so called project backlog. At the start of each sprint items from the backlog are placed in the sprint backlog. These are the worked items to be realized.
- Sprint cycle. All iterations follow the same simple process, with an iteration kick-off, actual work and a retrospective workshop for evaluation.
- User stories. The main unit of work is usually the user story, although this is not mandatory. This rather informal requirements technique is shared with the agile process extreme programming.
- Planning. In general the project and sprint planning is visualized in task boards, which usually is put up on a wall using post-its. Progress is monitored by using burn down charts, a straightforward diagram that on a daily basis displays the number of points still to realize. A trend line in the burn down chart extrapolated from the points identifies the likely project end date. Again this technique is shared with a number of other agile processes, including Smart and extreme programming.
- Delivery. Every iteration or sprint results in fully delivered products, software or otherwise.
Scrum has proven to be a successful approach in many (smaller scale) web projects. In larger, more complex, service or cloud oriented and enterprise projects, I think Scrum needs to be augmented to fit the project and its environment. Let me explain.
Beyond lightweight agile
When applying Scrum or other lightweight agile processes such as Crystal Clear or the set of lean principles (applied to software development that is) to more complex projects of all sorts, you might recognize a number of shortcomings:
- Business goals. It is often unclear how the work items in such projects (in most cases user stories) link back to business goals, stakeholders and business processes to implement.
- Analysis and design. Although many people in the so-called agile community will now think I’m promoting a waterfall approach, in most agile approaches there are hardly any analysis or design activities or deliverables defined.
For instance, it is undefined how the backlog in a Scrum project is assembled. Let me assure you, in more complex projects some analysis and design is required, albeit not in big-upfront-design mode.
- Architecture. The same argument goes for software architecture. Most agile approaches lack decent software architectural activities and deliverables. Architecture is often assumed as-is. If you’re implementing business processes that run through a systems landscape of over 40 collaborating systems, you will definitively need to design your architectures, but again this need not be in big-upfront-architecture mode.
- Roles. Scrum and extreme programming describe a very limited set of roles that, although looking slick, in most projects does not adhere to the standing organization. There’s often enterprise architects, information analysts, business analysts, middleware developers, application management, testers, release manager. How will a project work with all those roles? There’s a bit more to it than just saying they are allowed to participate in the daily scrum.
- Testing. Apart from the obvious (developer) techniques such as unit testing, the role of testing more specifically – which is essential in larger agile projects – is not very well described in lightweight agile approaches.
- User stories. Although very flexible, user stories are a highly unstructured unit of work, despite efforts in epics or story maps. Applying such an unstructured unit of work may result in low re-use, non-repeatable estimation, difficult to standardize development, testing and measurement beyond the individual projects. In a multi-project environment user stories will block progress and reuse (of for instance metrics and code).
- Delivery cycle. Scrum does not specify the organization of delivery of the products to different environments such as test, acceptance and (pre)production (so called OTAP).
When executing large, more complex, service oriented or enterprise projects, I therefore strongly recommends to overcome these limitations by augmenting Scrum and the likes with additional techniques.
In my personal experience in enterprise projects I have had very good experiences with mixing the agile process Scrum with the best practices from another agile processes called Smart to overcome the drawbacks of the aforementioned approach.
Smart originated from the Netherlands in 1998 and was originally designed to implement best practices for DSDM, an iterative approach that was popular in those days. Later Smart grew out to a stand-alone agile approach that particularly combines well with other more basis agile approaches such as Scrum and extreme programming, but also aligns well with PRINCE2.
More specifically Smart puts accents on aspects in project that are only marginally highlighted in other agile approaches. As an example Smart adds the following accelerators to projects:
- Preliminary iterations. Preliminary iteration types Propose and Scope is where work items are added to the backlog such as a modeling business processes, modeling smart use cases, creating an estimate, creating a cost-benefit analysis, writing a project plan (not that obvious it seems), first-cut software architecture set-up, development environment set-up, project kick-off, team education and first-cut user interface guidelines.
- Smart use cases. Next to the more “non-functional” work items mentioned above, Smart introduces the well-known smart use cases requirements technique. Smart use cases not only model the needs of the user, but also identify workflow and reusable back-end services.
This technique allows for identifying re-use, repeatable and reliable estimation, and very good traceability between requirements, architecture and code, great functional testing capabilities. An absolute must in enterprise projects.
- Estimates. Estimation of size and complexity of a project is estimated and measured in smart use case points, defined on a scale from 1 to 10. Smart use case points of course come from estimating the size or complexity of smart use cases, and is a highly pragmatic and repeatable technique..
- Work item life cycle. Where Scrum’s work item life cycle contains to-do, working and done, in Smart, work items are delivered through a slightly more structured life cycle, that allows for all roles in enterprise projects to be maximally involved in a collaborative manner.
Due to the life cycle, work items need not be broken down in tasks, a cumbersome and highly unstructured elements of Scum. In Smart work items simply move through the stages of the life cycle (in most cases in one or two days), the progress of which can be shown easily on a dashboard.
- Designing. During the daily stand-up meeting, it is decided whether or not a design session is required. This time-boxed design session addresses the design or a single smart use case. Most project will organize this design session directly after the daily stand-up. On a typical time scale, if the stand-up runs from 10:00 to 10:15, the design session runs from 10:15-11:00.
During such sessions all roles that need to deliver input to this particular use case participate. Of course also the developer and tester are present, so all roles create a homogeneous view of the smart use case at hand.
- Smart testing. Working with user stories will normally not result in a very efficient test approach, as user stories do not add structure to the project. Smart describes a standardized approach on functional testing in agile projects of course based on smart use cases.
- Stabilizing iteration. Usually the last iteration of a Smart project or the last one to an upcoming release is used to round off remaining work items, build issues, bugs, and remaining features. This iteration is merely used to stabilize the solution. In Smart this iteration type if referred to as Finalize.
Blending Scrum and Smart
Besides defining an obvious project life cycle, these best practices from Smart blend in really well with the more lightweight approach of Scrum and extreme programming. This leads to the following best practices:
- Initial backlog. The initial backlog of the project is filled with the work items Smart recommends, rather than assuming a user story filled backlog. When prioritizing work items for the first sprint in a mixed Scrum and Smart project, it is very likely that these are picked.
As a result, after one or two iterations, a project plan for the remainder of the project is produced, containing at least an estimate, based on the smart use cases that are also defined during these iterations (of course without any analysis or design, just the diagrams, the ovals and the actors).
- Iteration kick-off. After the initial work-items are cleared from the backlog, the smart use cases become the primary work item type in the project. During sprint kick-off a number of smart use cases is picked to implement in the next sprint.
- Dashboard. The traditional Scrum task board is replaced by Smart’s agile dashboard, containing columns for the stages in the work item life cycle – In Iteration, Designing, Working, Testing, Rework, Accepted. If appropriate additional columns can be added, e.g. when testing is split up in Developer Testing and Customer Testing.
- Points. The progress in the project is not measured in story points, but rather in smart use case points.
- Scrum meeting. The focus of the daily scrum meeting shifts a bit as it is also used to answer the question: what still needs to be done on the smart use case(s) we’re currently working on to get them accepted?
- Design. Host the design sessions as Smart recommends, preferably right after the daily scrum meeting.
- Testing. As the work item life cycle clearly stipulates, functional testing, often done manual is all in a days work. The role of the testers here becomes imminent in the project.
- Finalize. Projects have to decide when to apply a Finalize iteration to stabilize the solution and round up loose ends. Depending on the type of project, these iteration can be the very last sprint, but also can be very well aligned with the organizations release calendar.
This approach of mixing best practices, techniques and tools from Scrum, Smart over the past 12 years has proven to be very successful in a variety of projects and project types, including larger Java and .NET projects. service oriented projects, business intelligence projects, and even packaged implementations.
Moreover, when augmented with more technical best practices from extreme programming, such as refactoring, continuous integration, pair programming, and test driven development (smart use cases are a very good unit for unit testing code) projects are aligned to deliver on-time, on-budget, and with just-enough documentation and fitting (reusable) features. As former US president Bush used to say: failure is not an option.
As agile is becoming more and more mainstream, organization are starting to do enterprise software development project using well-known but fairly basic lightweight agile processes.
In many projects this has lead to surprisingly bad result, baffling the agile Certified Pokémon Trainers who are coaching these projects. The presentation below shows a number of accelerators or technique that projects can apply to tackle the challenges of enterprise agile projects.
Would be happy to hear your comments!
Last week, the Microsoft TechEd North America 2010 took place in the great city of New Orleans. I was lucky to be invited to do a talk on how frameworks can kill your projects.
When it comes to Microsoft .NET-connected development, more and more frameworks enter the market. Both from Microsoft and from open source. Think of ASP.NET MVC, Castle, Windows Workflow Foundation (WF), Entity Framework, Unity, Linq2SQL, ADO.NET Data Services, Windows Communication Foundation (WCF), nHibernate, Spring.NET, CSLA, NUnit, Enterprise Library or ADF.
Once a project chooses to apply one or more frameworks, trouble begins. What if you require features that aren’t implemented in the framework? What if you decide that another framework would have been better and want to switch halfway through your project? What if the author of your favorite open source framework suddenly stops developing? What if the framework contains bugs or omissions? And, what if a new version of the framework is released that is implemented differently? These and many more everyday problems will cause your project to come to a halt, or at least make you perform serious refactoring.
Demos and (bad) code
During this highly interactive talk, Sander Hoogendoorn, chief architect of Capgemini’s agile Accelerated Delivery Platform, and member of Microsoft’s Partner Advisory Council .NET, demonstrates pragmatic architectures and patterns that will help your projects to stay away from framework issues, and how to keep code independent of framework choices. Sander presents models of layered architectures, and applying bridge patterns, managers-providers, dependency injection, descriptors, and layer super-types.
Of course, Sander illustrates these insightful patterns with lots of demos and (bad) code examples using blocks from Microsoft’s Enterprise Library, NHibernate, Log4Net, and the Entity Framework. Learn how to improve the structure and quality of your software architecture and code, and how to avoid the pitfalls of applying frameworks to .NET software development.
It’s a mildly sunny April morning in 2002 when I park my car outside of a huge government agency office in a small suburban city near Utrecht. I am invited for a brainstorm session with the agency’s enterprise architects. Although I do not consider myself an enterprise architect, and explained that upfront, they were eager to discuss their architecture with me. Ok.
After registering at the reception, I enter the meeting room. Now this might be specific for the Netherlands, but the enterprise architects are sitting at an oval table, all equal in our consensus world. “So what is it you’re doing?” I ask, while looking at the architect who looks more equal than the others. Happy to be addressed the architect, bearded and all, stand up and walks to the whiteboard, picks up a marker and starts telling their story.
Rectangles and arrows
While talking our bearded architect starts drawing the different application and systems in their system landscape. Each represented by a rectangle with a three to five letter acronym on the white board. The big challenge for this government agency, so I understand, is to from a tightly integrated system landscape to a service oriented landscape with an enterprise service bus.
Next my bearded friend starts to discuss the connections between the different systems and the enterprise service bus. Here come the arrows! “So we connect each system to the bus, and we will have upgraded our landscape for the future,” the architect smilingly concludes. I nod my head willingly. “Looks good,” I start complimenting the architect. “But,” I continue, “how are these arrows implemented?” “Well, that’s easy,” says the architect. Without saying a word he picks up the marker again and slowly adds the acronym SOAP to one of the arrows on the white board. “That’s all.”
Now, from an enterprise architect’s point of view that might be all, but from a developer perspective drama begins here. I roughly estimate that each of these fancy little SOAP arrows likely represents about 4 to 8 weeks of work – note: it is still 2002. And there are quiet a few of these arrows on the whiteboard; and the view is likely not the complete picture.
Concluding: what might seem insignificant and trivial from an architectural perspective, might be complicated and elaborate from a developer’s and tester’s point of view. Or as Scott Ambler so eloquently puts it: everything works on a PowerPoint slide. And sorry dear architects, it just doesn’t, no matter how brightly colored and great looking your PowerPoint presentation are.
Wouldn’t it be good if enterprise architects actually participate in projects to see in real life what these simple drawn decisions. Actually, it is good. For some years now, in the agile projects I am coaching enterprise architects, business and information analysts take part during the actual iterations. Instead of upfront, untested architectural demands or long review periods afterwards, they actually participate in the design workshops of the project. And you know what? They love it. It’s simply great to actually see directly what comes out of what you so cleverly think of. And even better: you, as an architect are totally rid of these long and cumbersome review period, and you directly get to influence the way the software is built. Please do.
The penultimate goal
Can you do even better? Well, there’s a penultimate goal. In September 2003 I did a talk at a large software development conference in Denmark. During the speaker’s dinner I found myself at a table with some great names in this field – think of Bjarne Stroustrup, Jos Warmer, Kevlin Henney – and even bigger glasses of cool Danish beer. Nerds as we were, by the end of the evening we concluded that this particular conference should have a panel discussion with 42 panel members, and we would name it The Panel at the End of the Universe. Great thinking!
And about an hour and many glasses of beer later, we agreed upon an even bigger contribution to the field of software development. We thought that the penultimate solution to developing software is to be able to generate software directly from the rectangles and arrows in the architect’s PowerPoint presentations. That would sure boost productivity! Then we could actually say that everything does work on our PowerPoint slides.
This post was originally published in .NET Magazine. I re-posted it because of the talk I did at Microsoft’s DevDays 2010 in Den Haag recently. The slides for this talk can be downloaded here.
As you’re probably have been made aware of in abundance, in .Net 3.5 Microsoft introduced a little language feature called LINQ. Although LINQ has been demonstrated at all major and minor conferences, the way LINQ executes queries on already existing types remained slightly less apparent. To this means LINQ introduces a number of new query operators, using yet another new language feature called an extension method.
Download slides from my DevDays 2010 talk on extension methods here.
Basically, there are two sets of LINQ query operators. One set that operates on objects of type IEnumerable and another set that operates on objects of type IQueryable. To implement the methods in these sets, the .NET architects chose to add something called extension methods, and write the required methods as extension methods to the Enumerable and Queryable classes, instead of directly extending these classes – which would seriously pollute the .NET framework.
Defining a simple extension method
Apart from the apparent use of these extension methods in the query operators of LINQ, there is slightly more to it. At first sight, extension methods appear to allow you to extend any class in any namespace with additional functionality. Let’s have a closer look at them by using an example.
One of things I always disliked about working with the DataSet class is that to obtain the value from a column in a row in a table, I’d have to write code that looks at lot like this:
This code is both tedious and poor code however, as it doesn’t do any check on whether the table and row are actually available. As you’ve probably all have written code like this before, you would probably have appreciated a method like Get() on the DataSet class, like I’m using in the following code example, where Get() performs all necessary checks and formatting.
The issue here is that you cannot extend the .NET framework class DataSet to encapsulate this functionality. This is where extension methods come in neatly. With .NET 3.5 I can now write a method such as the following.
If you’ve never seen an extension method before, the first parameter will appear strange to you. The this keyword is added to it to show that this Get() method works on the DataSet class. Although this method is defined as a static method on a class called DataSetExtensions, it is recognized as an instance method on the DataSet class.
Intellisense even recognized my method, and the code comments I’ve added. The only difference between an instance method and an extension method from an intellisense point of view, is that you’ll still be able to notice the this parameter in the signature of your extension methods. Of course, the same goes for .NET framework defined extension methods, like the LINQ Where() method, which also displays the this parameter.
Extension methods and the Open Closed Principle
Doesn’t that look cool? I think so. When I first read about extension methods I immediately thought of a whole bunch of functionality that I could add not only to our own frameworks, but also to open source and even the .NET framework itself. But before bloating out lots of code, let me give you some caution.
My biggest worry was whether extension methods would allow me to break existing framework code. There’s a well known principle that needs to be examined here, which is called the Open Closed Principle (OCP). In short, this principle states that classes should be open for extension, but closed for moderation. In general I think this is a principle well worth living by. So, the big question is: do extension methods allow me to change the behavior of existing classes? What happens if I write an extension method, such as the one below?
The question is, by writing this simple extension method, did I just override the ToString() method for all classes in my applications? Surely, such extension methods would kill a lot of projects really fast. Of course the .NET architects do not allow you to do so. There’s thing or two you should know about how extension methods work, and about how they are compiled.
Compiling extension methods
First, they’re defined within the context of a namespace, Extensions in the example above. To use an extension method on a class in your code, you will need to add a reference to the namespace that contains the extension methods. Without this reference, the method don’t even show up.
Second, and even more important, extension methods are in fact just static methods on a static class, as can be seen in intermediate language (IL). Extension methods only appear in your code editor as instance methods on the target class. The fact that they’re defined as static methods outside of your target class means that in an extension method you can only get to the public properties the target class exposes, but you will not be able to reach the protected and private fields of this class, nor will you be able to define new properties or fields.
Even more important, it is interesting to notice what the compiler does with your extension methods, especially in the case that you would define a method with the same signature as the method in the target class, like with the ToString() method above.
The compiler follows a straightforward rule: extension method always have a lower priority that real instance methods. As a consequence, when the compiler tries to resolve a method invocation it first looks in the target class for methods with matching signature, and consequently in its ancestors, and bind to this method if located. Only if no instance method is found, will it start to look for extension methods with the same signature. Following this convention the ToString() method I’ve defined above will never be called, as the object class defines a method with a matching signature.
Even when I try to create a (very stupid) extension method like the one below, targeting the Equals(string s) method just for matching with a string, the compiler will still bind to the Equals(object o) method from the object class, even if it has a wider scope – it compares with an object, not a string.
This compiler directive satisfies my concerns. Using extension methods, you will not be able to alter any existing functionality. You can not override existing methods, nor get a hold of private or protected fields. In fact, the extension method totally live outside of the target class. So, you’re quite safe.
No worries then?
Well, there’s something else that concerns me about extension methods. The most demo’s I see on extension methods worry me. There seems to be no end to people extending the String class. I’ve seen demo’s that check whether a string is a valid email address, a valid URL, and even extensions that speak out a string using a synthesizer – although I expect good craftsmanship, not really something I long for in my applications.
It’s just that stuff like this should not be extensions to the string class. Unless at least 50% of all strings you use in your code are in fact email address, I would consider a different pattern here, such as defining value objects of type Email, Zip or whatsoever. In general, my concern with extension methods is that it’s such a neat little technology, that it will invite people to use it for all the wrong reasons – just because it’s fun to define an extension method for instance.
Before you know it, the developers in your project will have defined loads of extension methods, to all kinds of framework classes. You should be well aware of the possibilities this offers to break your application architecture and create lots of undesired dependencies. Just take a quick look at the following example.
Here, I’ve added an extension method to the CodeActivity class, which resides in the namespace System.Workflow.Activities. Now my Extensions namespace has a dependency on this namespace, and moreover, also on the underlying System.Workflow.ComponentModel namespace.
However, my previous code example where I extended the DataSet class also resides in my beautiful Extensions namespace. So from this day forward, every time I use my Get() extension method for DataSet, I’m indirectly also connected to the workflow namespaces. Just as an example.
Furthermore, when you define an extension method to extend a type delivered by a framework, you also run the risk that your extension method will cause your code to break if the implementation of that type changes, or if your project migrates to a newer version of that particular framework, of .
Extending framework base classes
On the good side, you will more likely use extension methods that other developers have written, than define your own. Here, extension methods are a powerful features, as applying extension methods does not require any additional knowledge. Most extension methods will be written by frameworks developers, who now will feel enabled to solve anomalies. Or even more likely by developers who feel the need to extend base classes from existing frameworks, both from Microsoft and open source, such as in the following example, that extends the open source frameworks CSLA.
One of the most reused base classes in the CSLA framework is called BusinessBase. It serves as layer supertype for all domain objects in applications built with the framework. The BusinessBase class has the ability to validate its business rules. To this means it stores a broken rules collection that contains references to business rules that are violated during a validation of your domain object.
In some cases, for instance when displaying violated business rules on screen, it can be handy to know which business rules were broken per property. The BusinessBase class however, does not have this ability.
The code example here displays an extension method for BusinessBase that loops through the total collection of broken rules using a LINQ query that filters the broken rules for the selected property (using the property’s name). This method is very useful and powerful example of how developers can tweak the functionality of framework classes. It should come as no surprise that many more such extension methods will become available from the community soon for popular frameworks such as Microsoft’s Enterprise Library, nHibernate, ADF, CSLA and of course for the .NET framework itself.
Handle with care
Extension methods are a language feature that does not really stand out in the crowd, but can be very useful, especially to avoid repetitive work that should have been a feature of frameworks you apply to your projects. However, when developing extension methods you will need to be very aware of the side effects described above. I therefore recommend to implement extension methods sparingly. Under normal circumstances, you will still extend existing types by inheriting from them, even though this requires your developers to use your new class by convention instead of an extended base class. To leave you with a proper quote: “Creativity is a natural extension of our enthusiasm.”