Thursday, May 28, 2009 |
|
|
Think your web applications are safe from cross site scripting? Maybe, maybe not. Why take a chance? I recently put together some notes for a presentation on cross site scripting, or XSS for short. I have decided to share some of the information, because I believe keeping a few thoughts in mind as we develop and test will go a long way when it comes to preventing attacks. Cross Site Scripting – What is it? Cross site scripting occurs when a web application gathers malicious data entered from a user, with or without negative intent. XSS can be achieved by exploiting locations in source code where users are able to input data, and the proper preventative measures have not been implemented to format and validate the inputted data. In other situations, session cookies and other sensitive data can be accessed by injecting malicious data and ultimately hijacking or impersonating a user’s account. There are three main types of XSS according to Wikipedia, so I won’t bother rephrasing. Visit http://en.wikipedia.org/wiki/Cross-site_scripting for more information. The most common technologies and languages used for XSS are JavaScript, VBScript, ActiveX, HTML, or Flash’s ActionScript. Not only do we need to protect our server code, but we need to think about our client code as well. Prevention of Cross Site Scripting The vast of majority of XSS attacks can be prevented by identifying the user input locations within the web application and ensuring the source code handling these has proper measures in place. From a developer’s perspective, this means ensuring all data inputted from a user is properly encoded to remove HTML and script markup to be replaced with text that all browsers can process. A simple example in C# is to use the HttpServerUtility.HtmlEncode method to convert all HTML markup characters into their text equivalent. For example, if a user were to supply the input for a textbox with the following, “This is my <b>bolded text</b>.” The end result of the HtmlEncode method would result in the following, “This is my lt;bolded textgt;.” This is important because it removes HTML markup, which could be malicious. For example, “This is my text. <script>alert(‘This is an attack’);</script>.” This example is passing a JavaScript alert to open a modal popup on the screen to display to the user. In addition to HTML inputted data encoded on the server, encoding data on the client can be equally important. JavaScript HTML elements can have two attributes, InnerHTML and InnerText. InnerText will render text, not HTML, so it is the safe option. InnerHTML can be used to inject an XSS attack because it can render user inputted HTML, including script. Ensure InnerHTML has the necessary string formatting to protect against this vulnerability. Cookies are another vulnerability to XSS attacks. If any part of the website issues cookies and an XSS access point is discovered, it is now possible to steal cookies and private information from the application’s users. If the cookie can be accessed, so can the information with it. Users can be impersonated, and site credibility will be lost. Encrypted web sites (SSL, HTTPS) are at risk just like their public counterparts. SSL sites appear to be protected, but it is possible to execute the same XSS attacks, they just happen over an encrypted connection. To protect our web applications, we need to be aware of the XSS vulnerabilities common to attackers and place defensive measures to ensure user confidentiality and confidence. Without becoming an expert on XSS and security, it is possible to develop safe, reliable applications by understanding XSS and the vulnerabilities exposed by our applications. What to Look for in Source Code Execute a simple search in source code looking for certain keywords is a good starting point. Many of the XSS bugs I have seen reported could have been prevented with the simple measures. Ensure HTML input is properly encoded on the server using HtmlEncode. Ensure HTML input is properly formatted on the client using string.Format and InnerText. In source code and wherever, look for the following vulnerabilities. - InnerHTML
- InnerText is not supported by all browsers but the two can be found together. Look for where the strings are originating and if they are properly formatted/encoded.
- SetInnerText()
- JavaScript’s Eval()
- Assigning of strings to page titles, control titles, ect.
- Sometimes we take request object data and immediately process it and render it on the client.
- Check the URL parameters passed in.
- The Request object
- Request.Params
- Request.Forms
- Request.QueryString
- Using HtmlTextWriter or any variation
- RenderBeginTag()
- AddAttribute()
- RenderEndTag()
- HtmlWriter.Write()
- Cookies
- Where are we using them and how are we handling them
Searching for these keywords within source will be a decent starting point for discovering XSS vulnerabilities Microsoft Anti-Cross Site Scripting Library V3.0 Beta Feel free to use a Microsoft API designed for XSS prevention within your code. http://www.microsoft.com/downloads/details.aspx?FamilyId=051ee83c-5ccf-48ed-8463-02f56a6bfc09&displaylang=en Closing Notes – because this topic can go on forever There are tools to help assess if your site is vulnerable. Search for them online. Whether or not you think you need third party APIs to help you write defensive code is entirely up to you. You can always write the code yourself. Cross-site scripting (XSS) can be damaging to a company’s credibility and can cause myriad undesirable effects for individual users. XSS is preventable. Familiarizing oneself with the smells of XSS is a valuable tool to posses as a developer and a tester. At a minimum, educate your developers and testers on the target hot-spots mentioned within this post. References and Resources http://en.wikipedia.org/wiki/Cross-site_scripting http://www.cgisecurity.com/xss-faq.html http://ha.ckers.org/xss.html http://www.owasp.org/index.php/Cross_site_scripting |
|
|
|
|
Friday, September 26, 2008 |
|
|
I am reading "The Software Architect's Profession: An Introduction," by Marc T. Sewell and Laura M. Sewell. I am not writing a book review with this post. Instead, I would like to highlight some similarities between the two disciplines. Whether we are building with brick and mortar, wood, steel, or computer code, the roles and processes are analogous. The role of the architect is important for both, but when it comes to software, the architect often goes unfulfilled. Compared to architecting and constructing homes, hospitals, and skyscrapers, architecting and developing software is new to many of us. In our minds, whether we understand the processes required to erect the Empire State building or not, most of us possess an intuitive understanding of the distinct roles of the architect, scientist, engineer, builder, electrician, and plumber. We realize that buildings provide shelter, make our lives easier, and consist of rooms specific to living activities. We have living rooms, family rooms, meeting rooms, workout rooms, kitchens, ect. If we want to add on a garage, screened-in porch, or modify an existing room, the architect needs to plan for this in his/her design. When it comes to software and the processes required to plan, design, develop, and test, many of us lack the intuitive knowledge of what is, or should be, necessary to build software. Just like a building, software makes our lives easier and consists of rooms, such as chat rooms, document libraries, art studios, financial planning, shopping, and home buying to name a few. If we want to add on a new room or modify and existing, the architect needs to plan for this in his/her design. It becomes easier to see how buildings and software are similar and how the roles specific to each appear to be obvious and necessary. A building needs an architect, a builder, an electrician, and so forth. Software, similarly, needs an architect, a developer, a tester, and so forth. Ask yourself this, "how many buildings (homes, schools, hospitals, malls, ect.) can I think of that were built without an architect?" Hmmm... I probably cannot think of any, or I should hope the answer is zero. Now ask yourself, "how many software applications were built without an architect?" This one I can answer more easily - several. I try to convince myself that so-and-so was "acting" as the architect on this or that project, but the nature of it is, too many software projects are built without a dedicated architect. Why is it that we feel like a building requires an architect, but that software can get by without it? Is it because over centuries and millennia, we have been exposed to the processes required to construct buildings on a daily basis? Whereas, since software is comparatively new, the processes and roles required are not fully defined, or engrained in us, or we have yet to see centuries worth of catastrophic errors from omitting these roles? "Blaming software failure or difficulty on 'changing requirements' is merely symptomatic of the lack of true architecture." As owners and builders see what is being built, they realize what is incorrect and begin to make modifications to align their initial expectations with the reality before it is too late. "It is equally erroneous to blame software failure on poor management. Even the best managers cannot produce a satisfying result from a bad design or a lack of design." Without this post becoming tiresome and long-winded, this book draws some good comparisons between the nature of building structures and software and the roles necessary for each. Do you have an architect in your organization? Is he/she only an architect, or is he/she sharing this responsibility? Why? |
Friday, September 26, 2008 8:42:42 AM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Wednesday, July 30, 2008 |
|
|
The marker interface is an interface that is empty. It does not implement any properties nor methods. It is used to mark the capability of a class as implementing a specific interface at run-time. In languages that do not provide support for associating metadata to a class, this approach can be useful. In C#, metadata attributes are available to apply to a class, and according to the .NET Framework 3.5 Design Guidelines for Developing Class Libraries, marker interfaces should be avoided. When I first noticed these marker interfaces in project I immediately thought it was a code smell. It just did not seem "right." Why provide an interface that defines nothing? Why provide a marker interface that implements a non-marker interface? Obviously there must be a reason for this? Two sources encourage me to avoid using marker interfaces and to use attributes in C#. Interface Design and .NET Type Design Guidelines - Interface Design. There advice is to avoid this... public interface IFooAssignable {} public class FooAssignableAttribute : IFooAssignable { // ... }
And to embrace this approach...
[FooAssignable] public class Foo { // ... } public class FooAssignableAttribute : Attribute { // ... }
There appears to be more work involved in writing "good" code.
If I am using "marker" interfaces, I can do this...
if(foo is IFooAssignable) { // ... }
If I am using attributes, I can do something like this...
object[] attributes = foo.GetType().GetCustomAttributes(false); foreach (string attribute in attributes) { if(attribute == "FooAssignable") { // ... } }
Or, thanks to Jarod Ferguson's suggestions on using extension methods and LINQ, I could have this...
public static class AttributeExtensions { public static bool IsAttributedAs<T>(this object obj) { if(obj.GetType().GetCustomAttributes(false).Where(x => x is T).ToList().Count == 1) return true; return false; } } // Then wherever I want to check for the attribute marker... if (foo.IsAttributedAs<FooAssignableAttribute>()) { // ... }
At this point, while "marker" interfaces are a code smell to me, I am still on the fence when it comes to using them versus custom attributes. I will more than likely tend to favor the attribute approach, unless I can prove that the cost of reflection is too expensive for my situation. I admit, I will do what I can to omit marker interfaces, perhaps by using some other interface where possible.
What are you doing in situations like this? Can you offer me a more elegant solution? |
|
|
|
|
Thursday, May 01, 2008 |
|
|
I have been doing code reviews frequently this past week and have been remarking on the naming conventions of test methods. In a effort to try and find the rules of BDD naming conventions, I came across Dan North's introduction to BDD, which is a great starting point, and a blog post by David Laribee that has made a good impression on me. You can read up on BDD to learn more, this post will not go into detail about it. From what I gathered from David Laribee's article, I like this. I REALLY like this. By changing namespace, class, and method names, the behavior of each spec (test) is clearly revealed. In a larger suite of tests, if there are failures, I can more easily see what is failing and what trends, if any, are resulting in my failures. Before, I would name my test method names to describe a behavior, "Some concept should do this when given that." Getting the namespace and class name involved provides a more legible test result. While reviewing a test case for a peer, I took this approach and arrived at the following scenario. I am changing the names of the methods to hide details. The original test method was "FilterToEndPointTestReport." Making this more readable, using my previous approach, we arrived at "FilterShouldUpdateStatusOnReportWhenDefaultFilterValueIsChanged." Great, that is better, but... Applying the approach described in David's post, I now have this. 1: namespace Specs_for_Filters 2: { 3: public class When_default_filter_value_is_changed : FilterTestFixture 4: { 5: [Test] 6: public void Endpoint_should_be_updated_on_report {} 7: 8: [Test] 9: public void Endpoint_should_be_updated_on_grid {} 10: 11: [Test] 12: public void Endpoint_should_be_updated_on_chart {} 13: } 14: 15: public abstract class FilterTestFixture 16: { 17: // provide common functionality that will be used 18: // among behavior-driven filter test classes. 19: } 20: }
When my tests run, their resulting output is more legible. This approach helps me to think about my tests in terms of behavior rather than implementation. In my opinion, my test cases are now more abstract and more succinct. |
Thursday, May 01, 2008 11:48:23 AM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Thursday, April 17, 2008 |
|
|
I was in a design discussion today and mentioned the need for a singleton object in our solution. Further along in the discussion I was trying to find a word that describes the opposite of a singleton, but alas, I struggled to find a word that may or may not exist. I just referred to the inverse object as a "new object." As I pondered this later in the day, I considered adjectives describing the nature of objects. They can be many things, but two concepts that popped into my head to classify them were "complex" and "simple." I started playing with the words and making them resemble singleton. "Complexton" did not sound right to me. I should mention that I was washing my hands as I was contemplating this. I lifted up my head, looked into the mirror, and thought, "SIMPLETON." The opposite of a singleton is a "simpleton." If the opposite of a singleton is not a "simpleton," then what is it? Until I find a plausible answer, I will try and insert this new term into my next design discussion. |
Thursday, April 17, 2008 8:41:34 PM (Mountain Standard Time, UTC-07:00) | | Design | Technology
|
|
|
|
Tuesday, April 08, 2008 |
|
|
Duplicate code to me is wrong. Writing duplicate code to me is like using poor grammar. If I am unaware of it, I am none the wiser. However, if I knowingly use poor grammar or duplicate code, I feel bad.
After seeing too many duplications across methods in one or more classes, I decided to investigate a way to remove these. I am always looking to remove duplicate code, even code that shares similarities, I look to refator. Removing duplications is important to adapt more easily to change. When a code change is required, we should only have to make it in one place. The following article will show two relatively simple means to address this code smell, delegates and an Aspect-Oriented approach.
The example I am using in this article is seen below. It is a unit test class, StackFixture class, and it is extremely trivial. This is a typical unit test taken from Test-Driven Development in Microsoft .NET. I have added the logging functionality as an easy means to show how these types of DRY violations can occur. While the duplications in this example deal with logging, they could pertain to other, more complex, functionality as well. The approaches to removing duplications across methods in this article can work with these simple scenarios, as well as more complex ones.
Take for example this sample test case. Each test method logs a message before and after executing the test logic. This violates DRY. We want to keep our test logic in our method, but factor out the duplicate logging. Again, if we were not logging, but doing some repetitive logic, we could factor that out as well.
1: [TestFixture] 2: public class StackFixture : AbstractBaseFixture 3: { 4: private Stack stack; 5: 6: [SetUp] 7: public void SetUp() 8: { 9: stack = new Stack(); 10: } 11: 12: [Test] 13: public void Empty() 14: { 15: Log.Info("Starting Empty test"); 16: 17: Assert.IsTrue(stack.IsEmpty); 18: 19: Log.Info("Ending Empty test"); 20: } 21: 22: [Test] 23: public void PushOne() 24: { 25: Log.Info("Starting PushOne test"); 26: 27: stack.Push("first element"); 28: Assert.IsFalse(stack.IsEmpty, "After Push, IsEmpty should be false."); 29: 30: Log.Info("Ending PushOne test"); 31: } 32: 33: [Test] 34: public void Pop() 35: { 36: Log.Info("Starting Pop test"); 37: 38: stack.Push("first element"); 39: stack.Pop(); 40: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 41: 42: Log.Info("Ending Pop test"); 43: } 44: 45: [Test] 46: [ExpectedException(typeof(InvalidOperationException))] 47: public void PopEmptyStack() 48: { 49: Log.Info("Starting PopEmptyStack test"); 50: 51: stack.Pop(); 52: 53: Log.Info("Ending PopEmptyStack test"); 54: } 55: }
Remove Duplications with Delegates
Quite simply, we can remove our method duplications using a delegate, in this case, the System.Action delegate. Thanks to Ayende for helping me understand this option. We create a method, TestMethod (as shown below), and add it to our StackFixture class. The method takes two strings (string beforeMessage and string afterMessage) and the Action delegate, representing the test method logic. We will call this method within our test cases.
1: public void TestMethod(string beforeMessage, string afterMessage, Action action) 2: { 3: // before 4: Log.Info(beforeMessage); 5: 6: // invoke our method 7: action(); 8: 9: // after 10: Log.Info(afterMessage); 11: }
Then, in our tests, we replace the following test method...
1: [Test] 2: public void Pop() 3: { 4: Log.Info("Starting Pop test"); 5: 6: stack.Push("first element"); 7: stack.Pop(); 8: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 9: 10: Log.Info("Ending Pop test"); 11: }
With the same method using our delegate approach.
1: [Test] 2: public void Pop() 3: { 4: TestMethod("Starting Pop test", "Ending Pop test", 5: delegate 6: { 7: stack.Push("first element"); 8: stack.Pop(); 9: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 10: }); 11: }
We can replace each of our test methods with the same TestMethod using the System.Action delegate. It will then easy to omit our before and after strings replacing them with "action.Method.Name," or some other intelligent logic to determine what to log.
This approach works well, but delegates are often difficult to understand. If this solution suits your needs, make sure the implementation is easily maintainable. What is nice about this approach is how simple it is. There is no need to reference any assemblies outside of the .Net framework, i.e. no third party dependencies.
The Aspect-Oriented Approach
Aspect-Oriented Programming (AOP) is an entirely different animal. It certainly deserves more than just a blog post. Please read more about it online. This article will not explain the details of AOP.
If you are reading this, welcome back. I will assume you are now familiar with AOP. There are several options for AOP frameworks. Some frameworks I have used are Spring.net, Castle Project, and PostSharp. The former two provide IoC capabilities as well. I suggest using a well-supported framework, one with community support and frequent updates. Investigate for yourself, there are several nice options available.
AOP with Castle DynamicProxy
Hamilton Verissimo put together a good sample using Castle's DynamicProxy. It is a nice, clean implementation.This worked fine for me and would work well in other situations. However, in my scenario, if I were to use this approach, I needed to have each of my test classes extend from MarshalByRef. In addition, I would need to modify the underlying NUnit framework to create my proxies in order to provide advice. Since I could not do the latter, or did not want to investigate, I searched for other AOP options.
The DynamicProxy aproach to solving your AOP needs is a great option. It just did not work in my situation, only because NUnit executes each of my methods. I would need to somehow intercept the creation of my test class, create a proxy of it, and execute the test methods on it.
AOP with PostSharp
Gael Fraiteur's PostSharp is a great option for AOP needs. It is extremely clean and easy to use. It is the simplest AOP framework I have used. I suggest watching Gael's video tutorial.
The first thing I needed to do, besides downloading and installing PostSharp, is to add two references to my project, PostSharp.Laos and PostSharp.Public. After that, I create a simple class extending OnMethodInvocationAspect, called LoggingMethodInvocationAspect.
1: [Serializable] 2: public sealed class LoggingMethodInvocationAspect : OnMethodInvocationAspect 3: { 4: private ILogger log; 5: 6: public LoggingMethodInvocationAspect(ILogger logger) 7: { 8: log = logger; 9: { 10: 11: public override void OnInvocation(MethodInvocationEventArgs eventArgs) 12: { 13: // before 14: log.Info("OnInvocation Before proceed"); 15: 16: // invoke 17: eventArgs.Proceed(); 18: 19: // after 20: log.Info("OnInvocation After proceed"); 21: } 22: }
At this point, all we need to do is apply our aspect on target methods. The "AttributeTargetMembers" attribute can use wildcards. This tells the AOP framework to only intercept those methods in the "MathService" class that start with "Test." Below is the sample where I specify the target assembly, target type (class or classes to intercept), and target methods to intercept. There are many features beyond what I am showing so do further investigation.
1: [assembly: ClassLibrary.SampleInterfaces.LoggingMethodInvocationAspect( 2: AttributeTargetAssemblies = "ClassLibrary.UnitTesting.Sandbox", 3: AttributeTargetTypes = "ClassLibrary.UnitTesting.Sandbox.MathService", 4: AttributeTargetMembers = "Test*")]
Finally, my StackFixture class now looks something like this. Notice that the duplicate logging logic is now removed and each test method is prefixed with "Test" in the method name. This is so that PostSharp can filter what methods to intercept.
1: [assembly: ClassLibrary.SampleInterfaces.LoggingMethodInvocationAspect( 2: AttributeTargetAssemblies = "ClassLibrary.UnitTesting.Sandbox", 3: AttributeTargetTypes = "ClassLibrary.UnitTesting.Sandbox.MathService", 4: AttributeTargetMembers = "Test*")] 5: 6: [TestFixture] 7: public class StackFixture 8: { 9: private Stack stack; 10: 11: [SetUp] 12: public void SetUp() 13: { 14: stack = new Stack(); 15: } 16: 17: [TearDown] 18: public void TearDown(){} 19: 20: [Test] 21: public void TestEmpty() 22: { 23: Assert.IsTrue(stack.IsEmpty); 24: } 25: 26: [Test] 27: public void TestPushOne() 28: { 29: stack.Push("first element"); 30: Assert.IsFalse(stack.IsEmpty, "After Push, IsEmpty should be false."); 31: } 32: 33: [Test] 34: public void TestPop() 35: { 36: stack.Push("first element"); 37: stack.Pop(); 38: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 39: } 40: 41: [Test] 42: [ExpectedException(typeof(InvalidOperationException))] 43: public void TestPopEmptyStack() 44: { 45: stack.Pop(); 46: } 47: }
The end result, a StackFixture test class with duplicate logging logic removed. The PostSharp AOP framework post-processes the compiled assembly and inserts itself, easily providing points of interception.
The PostSharp approach does involve a third-party dependency, but I feel like it is cleaner than the delegate approach. Gael informed me future versions of PostSharp will provide a more configurable solution than adding the [assembly ...] reference for the aspects, perhaps an XML configuration option. This can be done today, but involves some work.
Whether you use delegates, AOP, or some other approach, remove duplicate code wherever possible. I am happy to use either approach in my projects. There are tradeoffs to either solution, so investigate for yourself. |
|
|
|
|
Tuesday, April 01, 2008 |
|
|
Craig Neuwirt recently started a blog focused on NHibernate, as mentioned by Ayende. NHibernate is an ORM tool I have used on current and past projects and it is something I feel I would like I want to study further. So far, Craig is walking us through NHibernate from the ground-up, with the latest and greatest. I anticipate this being an informative blog to follow.
The NHibernate FAQ Craig Neuwirt Hibernating Rhinos |
|
|
|
|
Friday, March 14, 2008 |
|
|
This is a nice example using the new ASP.NET MVC framework. It is a clone of the Digg site, so it shows some more practical functionality, well beyond "Hello World." Not that there are not other practical examples out there, but the site goes into good detail on the MVC framework. |
|
|
|
|
Sunday, March 09, 2008 |
|
|
Boise Code Camp 2008 was awesome. Thank you to David Starr and his wife, Eleanor, for taking ownership of this event and dedicating many months of their time to make this a reality. Thank you to the presenters for having the passion and desire to present technologies and practices, both new and not-as-new. Thank you to the many volunteers who put in countless hours to help coordinate the weekend's events. Thank you to the campers for attending and making this year's code camp a success. I am sure everyone will be blogging about all the great sessions they attended at code camp. I enjoyed all of the presentations I attended, and I am excited to explore some new material. I want to share a few thoughts on my presentation dealing with Model-View-Presenter in ASP.NET after listening to Scott Hanselman's session on the ASP.NET MVC Project. I may have the percentage incorrect, but Scott mentioned something like it is predicted that only 10% of the ASP.NET community currently using Web Forms will adopt and use the MVC framework. The MVC framework is an addition to ASP.NET, it is not a replacement. What this means is that Model-View-Presenter will still be a viable pattern to implement with your ASP.NET applications, and it is not going away. ASP.NET Web Forms will not be going away either. Use MVP to get your third party controls under test. Use MVP to provide that separation of concerns in your legacy applications. Use it entirely or in conjunction with the MVC framework. It is all about testability. Glenn Block presented on the Web Client Software Factory, and what pattern does this implement? Model-View-Presenter. I am providing my presentation and source code (3.67 MB) from my talk on MVP. It will be available via the Boise Code Camp site as well. Again, thank the many individuals and their families who sacrificed their time to bring to the local community this years code camp. Around the office's water cooler on Monday, I will be able to say, "and this one time, at code camp..." |
|
|
|
|
Saturday, January 05, 2008 |
|
|
Recently I was developing some unit tests that had a dependency on a third party library and I found the adapter pattern applicable. I have decided to share what motivated me to apply this pattern since it is common dilemma. In addition, I am providing some general information on the adapter pattern that I hope will be useful. My initial need for the pattern occurred when I was using SubSonic, an open-source data access layer that uses the active record pattern. SubSonic's implementation of the active record pattern relies heavily on static methods to access data, which is not always necessary. In addition, I use RhinoMocks, an open-source unit testing framework, to help with my testing. With RhinoMocks, static methods cannot be mocked. The adapter pattern paid for itself by providing me a common interface with a third party library and encapsulating active record's static methods. SubSonic is a powerful option for data access and I recommend trying it out. In my situation, SubSonic and RhinoMocks fail to play nicely together due to static "Fetch" methods. In my application, I can retrieve all of my products, or a single product, using SubSonic like the following code below. 1: IDataReader dataReader = Product.FetchAll();
2: Product product = Product.FetchByID(1);
In my service layer, I call the static method "FetchAll," using something similar to what is shown above. If I want to write a unit test for this class, I need to write more code to get this static dependency resolved. I could use TypeMock to mock this static method, but I choose to use RhinoMocks, and since RhinoMocks cannot mock static methods, I need to consider refactoring. I am using a third party library, and while I do have the source code for it, implementing the adapter pattern is easier than rewriting SubSonic for what I need.
Adapter pattern to the rescue
The adapter pattern converts the interface of a class into an interface that clients expect (dofactory.com). The client expects what is defined by the target interface. The adapter implements the target interface and is composed with the adaptee. The adaptee receives receives all the requests from the adapter. Below is a UML diagram depicting the relationship among the objects.

The adapter pattern is useful in situations where:
- Two or more classes are doing similar things but have different interfaces
- You are using a third party API or framework that many clients already use
- You are using a third party API or framework and you do not have access to modify its source code
- You are using static methods that need to be mocked for unit testing using RhinoMocks
In my situation, SubSonic provides data access functionality that I need to encapsulate behind an interface that my clients expect. This will in turn make it easier for me to allow other data providers to participate in the future. Before refactoring, my service class's GetAllProducts() method calls the static method Product.FetchAll(). After refactoring, I move the Product.FetchAll functionality into its own class, ProductDAO. I now pass a reference to ProductDAO into my service layer class. This I can easily mock with RhinoMocks.
1: public class ProductService
2: {
3: private IDomainDAO dataAccess = null;
4:
5: public ProductService(IDomainDAO dataAccess)
6: {
7: this.dataAccess = dataAccess;
8: }
9:
10: public IList<ProductDTO> GetAllProducts()
11: {
12: IDataReader dataReader = dataAccess.FetchAllByName();
13: IList<ProductDTO> productList = new List<ProductDTO>();
14:
15: while (dataReader.Read())
16: {
17: int id = int.Parse(dataReader["ProductID"].ToString());
18: string name = dataReader["ProductName"].ToString();
19: productList.Add(new ProductDTO(id, name));
20: }
21:
22: return productList;
23: }
24: }
My service class, ProductService, now only references an interface called IDomainDAO, which is my "Target." My "Adapter," ProductDAO, implements that interface. ProductDAO has a reference to the "Adaptee," SubSonicProductDAO. My ProductDAO delegates its requests to the adaptee.
1: public interface IDomainDAO
2: {
3: IDataReader FetchAllByName();
4: }
5:
6: public class ProductDAO : IDomainDAO
7: {
8: SubSonicProductDAO adaptee = new SubSonicProductDAO();
9:
10: public IDataReader FetchAllByName()
11: {
12: adaptee.FetchAll();
13: }
14: }
15:
16: public class SubSonicProductDAO
17: {
18: public IDataReader FetchAll()
19: {
20: return Product.FetchAll();
21: }
22: }
In the example above, I implemented the adapter pattern as outlined in the UML diagram. I did not actually need to create the adaptee since I am using static methods. I could have just had my adaptor's FetchAllByName() function call Product.FetchAll(). I wanted to stick to the pattern.
The unit test exercising my ProductService's GetAllProducts() method looks like the following. With RhinoMocks, I can mock my target, IDomainDAO. At some point, a unit test will be needed that will test that static method. It cannot avoid being tested forever. I would feel comfortable testing this in a separate integration test project so as not to violate the rules of unit testing.
1: [Test]
2: public void GetAllProducts_ShouldReturn_ListOfProductDTOs()
3: {
4: using (mocks.Record())
5: {
6: IDomainDAO dataAccess = mocks.DynamicMock<IDomainDAO>();
7: dataReader = mocks.DynamicMock<IDataReader>();
8:
9: Expect.Call(dataAccess.FetchAllByName()).Return(dataReader);
10: Expect.Call(dataReader.Read()).Return(true);
11:
12: Expect.Call(dataReader["ProductID"]).Return(1);
13: Expect.Call(dataReader["ProductName"]).Return("My Product");
14:
15: Expect.Call(dataReader.Read()).Return(false);
16: }
17:
18: using (mocks.Playback())
19: {
20: IList<ProductDTO> productList = new List<ProductDTO>();
21:
22: Assert.AreEqual(0, productList.Count);
23:
24: productList = service.GetAllProducts();
25:
26: Assert.AreEqual(1, productList.Count);
27: }
28: }
Code Smells Indicative of the Adapter Pattern (thanks to Industrial Logic)
Alternative Classes with Different Interfaces
Occurs when the interfaces of two classes are different and yet the classes are quite similar. If you can find the similarities between
the two classes, you can often refactor the classes to make them share a common interface.
Duplicated Code Smell
Duplicated code is the most pervasive and pungent smell in software. It tends to be either explicit or subtle. Explicit duplication exists in identical code, while subtle duplication exists in structures or processing steps that are outwardly different, yet essentially the same.
Oddball Solution Smell
When a problem is solved one way throughout a system and the same problem is solved another way in the same system, one of the solutions is the oddball or inconsistent solution. The presence of this smell usually indicates subtly duplicated code.
The adapter pattern often works in conjunction with the facade pattern. While the adapter adapts objects, the facade is used to adapt systems. I will not go into more detail for the facade pattern. Perhaps it will become a separate post.
In my situation described above, I really needed the adapter pattern to help me bypass the issue with RhinoMocks not allowing me to mock static functions. If you have static functions in your code and they are proving difficult to test, determine if they are necessary and/or refactor them. |
|
|
|
|
Saturday, December 29, 2007 |
|
|
I am not a build engineer, but I do enjoy architecting systems to help make the software build process better. I work in a start up for various reasons, one of which is the opportunity to solve wide ranging business problems. Recently, I put on my build engineer's hat and dedicated some time to improving our software build process, stepping outside of my immediate comfort zone.
I rely on a number of tools for our continuous integration practices. One of which is CruiseControl.NET, the other is NAnt. Both of these tools use .NET technologies and are ports from their Java projects, CruiseControl and Ant. Besides Lucene.Net, what .NET projects are not better than their Java cousins? Just kidding, take it easy. In addition, CruiseControl.NET integrates with a number of technologies to improve the build process. NAnt, MSBuild, NUnit, FxCop, and FitNesse are just a few. With NAnt and MSBuild, we can call more applications as well, like TypeMock, BeyondCompare, and other necessary applications for our system.
As I mentioned, I am not a build engineer, but I get the opportunity to play the role. Our continuous integration process uses a number of free and open-source projects because they are widely supported and proven technologies, and the price is right. As our developers commit code into our SCM system (we use Subversion), the CruiseControl server checks for updates and begins the build and verification process. Helping with this process is NAnt, an extremely helpful .NET build tool.
What I like most about NAnt, and probably the primary reason for this post, is that I can leverage my knowledge of C# to write functions to aid in the process of building better products. CruiseControl uses XML config files, where projects are created, properties are configured, dependencies are defined, and much more. In my scenario, I have the CruiseControl config file calling my NAnt build scripts, which are also written in XML. Fortunately, I feel confident in my XML skills, so this is easy for building basic projects and adding to them.
The NAnt build scripts are used to define how the project is built. As NAnt is executed, it calls a build script. A typical scenario of actions defined in the script could be to check out the latest code, clean the build environment, build the project, test the project, and deploy the project with necessary configuration files (app.config, web.config, ect.). CruiseControl notifies the development team immediately on the build’s status - pass or fail.
What I set out to do, and where NAnt helped me the most, is with versioning my assemblies and deploying to a common location. Versioning of the assemblies requires more control over my build scripts. In this instance it requires incrementing the Major.Minor.Build.Revision version in my AssemblyInfo.cs files for all projects before the build, and rolling these changes back anywhere during the process if the build should fail.
Discovering how to call C# functions within NAnt increased my ability to do more and saved time. NAnt has a number of predefined functions that can be used to make life easier, and it also has the ability to create custom functions that can be written in any number of .NET languages. The ability to write custom functions made my life much easier and gave me the control I needed to do more for my automated build system.
Defining custom functions looks like the following.
1: <script language="C#" prefix="CSharp"> 1: 2: <code> 3: <![CDATA[ 4: 5: [Function("HelloWorld")] 6: public static string HelloWorld() 7: { 8: return "Hello World"; 9: } 10: 11: [Function("GetIncrementedBuildVersion")] 12: public static string GetIncrementedBuildVersion(string buildVersionFile, string svnRevision) 13: { 14: // Read in a file 15: System.IO.FileStream fs = new System.IO.FileStream(buildVersionFile, ... (more code here) 16: 17: // Increment file version number 18: version++; // you get the idea 19: 20: // Return incremented version 21: return version; 22: } 23: ]]> 24: </code> </script>
Calling the custom functions now looks like this in NAnt scripts. I am using an "echo" element simply to call my method, HelloWorld, and echo "Hello World" back to the screen. I use a "property" element to return the value of my GetIncrementedBuildVersion method and save this for latter use in my scripts.
1: <echo message="My Hello World Message is ${CSharp::HelloWorld()}"/> 2: <property name="incremented.build.version" value="${CSharp::GetIncrementedBuildVersion(master.build.version,svn.revision)}" />
Custom functions are pretty powerful and they certainly saved me a good deal of time, and in a start up, this is gold. Being a build engineer is a fulltime position and I quickly learned this over the past two weeks. These are a few of the tools I chose to use to help me improve our software build process.If you would like more detailed examples of CruiseControl configs or NAnt scripts, I would be happy to provide those, just email me. I did not want to become that detailed in this post. |
Saturday, December 29, 2007 1:22:08 PM (Mountain Standard Time, UTC-07:00) | | Design | Tools | Xml/Xsl
|
|
|
|
Sunday, December 02, 2007 |
|
|
Multiple Inheritance and Mixins |
Sunday, December 02, 2007 10:37:39 PM (Mountain Standard Time, UTC-07:00) | | Design | Technology
|
|
|
|
Monday, November 19, 2007 |
|
|
Tracking down an unhandled exception |
Monday, November 19, 2007 11:19:14 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Wednesday, November 07, 2007 |
|
|
Implementing MVP in ASP.NET |
|
|
|
|
Friday, October 26, 2007 |
|
|
Reduce Javascript function naming collisions in ASP.NET |
Friday, October 26, 2007 9:59:34 PM (Mountain Standard Time, UTC-07:00) | | Design | JavaScript
|
|
|
|
Monday, October 01, 2007 |
|
|
A handy little cheat-sheet, free from Industial Logic |
Monday, October 01, 2007 9:21:21 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Monday, September 24, 2007 |
|
|
|
Monday, September 24, 2007 6:02:32 PM (Mountain Standard Time, UTC-07:00) | | Design | Tools
|
|
|
|
Sunday, September 16, 2007 |
|
|
|
Sunday, September 16, 2007 7:42:52 PM (Mountain Standard Time, UTC-07:00) | | Design | Misc
|
|
|
|
Sunday, August 26, 2007 |
|
|
Event-driven MVP in ASP.NET |
|
|
|
|
Sunday, April 29, 2007 |
|
|
Applying the Observer Pattern in ASP.NET |
|
|
|
|
Monday, February 05, 2007 |
|
|
Integrating Monorail into an ASP.NET WebForms application |
|
|
|
|
Wednesday, January 17, 2007 |
|
|
|
Wednesday, January 17, 2007 9:49:32 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Tuesday, June 06, 2006 |
|
|
This concludes my OO presentation notes |
Tuesday, June 06, 2006 8:53:49 AM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Thursday, June 01, 2006 |
|
|
More on my OO presentation, what is abstraction? |
Thursday, June 01, 2006 1:30:31 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Tuesday, May 30, 2006 |
|
|
More from my OO presentation, what is composition? |
Tuesday, May 30, 2006 8:42:33 AM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Monday, May 29, 2006 |
|
|
More from my OO presentation, what is polymorphism? |
Monday, May 29, 2006 3:16:54 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Friday, May 26, 2006 |
|
|
More on my oo presentation, what is encapsulation? |
Friday, May 26, 2006 1:28:50 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Monday, May 22, 2006 |
|
|
More from my OO presentation, what is inheritance? |
Monday, May 22, 2006 10:10:56 AM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Friday, May 19, 2006 |
|
|
More notes on my OO presentation, what is a class? |
Friday, May 19, 2006 8:41:39 AM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Tuesday, May 16, 2006 |
|
|
Part of my OO presentation notes, what is an object? |
Tuesday, May 16, 2006 1:04:47 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Monday, May 15, 2006 |
|
|
My upcoming notes on my object-oriented presentation |
Monday, May 15, 2006 8:16:26 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
Sunday, May 07, 2006 |
|
|
Something to consider when using the static keyword |
Sunday, May 07, 2006 12:39:10 PM (Mountain Standard Time, UTC-07:00) | | Design
|
|
|
|
|
|
|
| Archive |
| June, 2009 (1) |
| May, 2009 (1) |
| April, 2009 (1) |
| March, 2009 (1) |
| February, 2009 (2) |
| January, 2009 (1) |
| December, 2008 (2) |
| November, 2008 (1) |
| October, 2008 (1) |
| September, 2008 (1) |
| August, 2008 (1) |
| July, 2008 (2) |
| June, 2008 (1) |
| May, 2008 (1) |
| April, 2008 (8) |
| March, 2008 (8) |
| February, 2008 (2) |
| January, 2008 (1) |
| December, 2007 (2) |
| November, 2007 (2) |
| October, 2007 (4) |
| September, 2007 (3) |
| August, 2007 (1) |
| July, 2007 (2) |
| June, 2007 (1) |
| May, 2007 (2) |
| April, 2007 (2) |
| March, 2007 (1) |
| February, 2007 (1) |
| January, 2007 (3) |
| December, 2006 (1) |
| November, 2006 (1) |
| October, 2006 (2) |
| September, 2006 (1) |
| August, 2006 (1) |
| July, 2006 (2) |
| June, 2006 (3) |
| May, 2006 (9) |
| April, 2006 (1) |
| March, 2006 (4) |
| February, 2006 (2) |
| January, 2006 (3) |
| December, 2005 (4) |
| November, 2005 (4) |
| October, 2005 (3) |
| September, 2005 (5) |
| August, 2005 (7) |
| July, 2005 (5) |
| June, 2005 (5) |
| May, 2005 (7) |
| April, 2005 (3) |
| March, 2005 (6) |
| February, 2005 (7) |
| January, 2005 (9) |
| December, 2004 (4) |
|
|
|
|
| About |
Powered by:
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
© Copyright 2010 MuellerDesigns.net
Sign In
|
|
|
|