Date: Jan. 15th, 2009
Attendance: 14
I’m going to try to start taking notes at our CinARC meetings in order to document the great discussions we are having. If you don’t come to CinARC and you like what you see (or you completely disagree with our discussion points) then you should be coming to give your input. We meet the third Thursday of each month at MAX Training (6:00 PM-8:30 PM).
CinARC is usually an open discussion forum for topics related to software architecture. We put up a list of topics from the previous meeting, solicit any new topics and take a vote on which topics we want to talk about. People can add topics at any time. The first few meetings were held using a Fish Bowl format; however, since we have a smaller crowd lately we’ve just been using an open format.
Note that what follows are notes of the highlights that I was fast enough to capture. It represents a collection of thoughts from 14 people over two hours of conversation. Obviously it is not comprehensive.
How to Architect for Virtual Environments
This topic was geared towards if people were utilizing virtualization in their production environment, and if so, were they doing anything specific in their architecture for it.
A general hand showing in the attendees showed that only a few were even virtualizing anything in their production system. Most everyone was utilizing virtualization of some sort for either development or testing (even if it was just for personal development). This caused the topic to turn more towards the “why aren’t we doing more of this in production?”. Several people indicated that using virtual servers for your front end web servers or services made a lot of sense. In this manner you could scale easily if you had the horsepower in your virtual hosts to keep adding nodes. Of course, this is one of the benefits of a Cloud environment where you can scale “infinitely” (or as infinite as your cash is anyway).
One of the members of the group indicated having issues virtualizing a SQL server database. They indicated that it worked correctly, but tuning became almost impossible for them. A few people had seen SQL Databases virtualized and were not necessarily having the same issue. It would have been interesting to have someone with a deeper background in virtualization to flesh out this part of the discussion.
A final thought on the virtualization was that some vendors will not support their products in a virtual environment. This could be an issue if you call in for support and once they find out that you are running in a virtual environment they simply point at that being the problem without digging any deeper.
NHibernate, HQL and Abstractions
This topic was suggested because one of the attendees was working on a project in which the Architect had decided to create a facade (described as a helper) in order to hide the complexities of HQL. This had the side effect of causing some of the more advanced functionality of HQL to be hidden from the developers since they were tasked to use only the helper. If they needed to expose some additional functionality that HQL provided they then had to go update the helper to expose it.
Overall the reaction by the group was mainly that this was a BAD idea. One statement was made that if an abstraction layer is causing you pain, or if it is leaky in any manner, it is probably not doing you any good and is a bad abstraction. One solution mentioned was to use LINQ to nHibernate in order to provide the abstraction instead of a manually updated helper. This also allowed the abstraction of nHibernate session, which the helper was allowing to leak upwards into the design.
The topic then turned to the concept of how many layers people commonly had in their application. In answer to this it was stated that layers should grow organically. If you are following TDD some layers will occur simply because you are creating seams in which to inject testing, such as the Data Access Layer/ORM being abstracted. Others will occur because a vendor provides a poor or bloated API and a facade is a good way of abstracting that.
Automated End to End Testing
This topic actually started out with a LOT of different threads: How were people managing integration tests, How do you test JavaScript, and the how are people organizing their tests. We broke the last thread out to it’s own discussions topic and tackled the other two. The first thread was really on how to handle automated integration tests that took too long to run while actively working on the code (for example, a developer doing a local build). The answer was to utilize your Continuous Integration to handle this by running the integration tests less often than the unit tests. For example, a developer may run all unit tests on their local build and check things in once all the unit tests are green. Then, the CI might kick off and run all the unit tests AND the integration tests, or perhaps the integration tests are just run once an hour/day if they are really time consuming or intensive. The testing framework should have some way of segmenting the unit tests from the integration tests, such as categories (NUnit, MbUnit, XUnit, etc. ) or groups (MSTest).
The second thread to this topic really centered around integration testing of JavaScript where you were literally testing page behavior. The question was, do you test your JavaScript? If so, do you use all the browsers you support to do that testing? This led to a pretty interesting discussion. Here are the main points covered:
- Use a JavaScript Framework to deal with as much of the cross-browser differences as you can. For example, if you use JQuery to do something, you can assume that JQuery has tested that it works across browsers so you don’t have to. Frameworks that provide their own unit tests with the distributable are probably a good option here since you can see the coverage for yourself.
- Do you really need mocking for JavaScript given it’s dynamic nature? The answer here was absolutely. A few people used a mocking tool for JavaScript testing to test AJAX calls and provide the extensions for performing asserts easily in their test code. Two JavaScript test frameworks mentioned by name were TestCase and FireUnit.
- To deal with actual walk through integration tests where page transitions and such were involved tools such as Selenium and Watir/Watin (Watir for generating the tests in Ruby and Watin for generating the tests in .NET, though both can be used to test just about any web application) were suggested. It was noted though that if you have a large number of these walk through tests then it may be an indication that you don’t have enough smaller unit tests. They could also indicate you are testing the maintaining of state and not behavior of the web application.
- The last item for this thread was “is all this work for automated UI tests even worth it?”. The answer here was not very clean. Most people didn’t find bugs by using these types of tests, but they worked well for regression testing. Also, you had to adopt the attitude that these types of tests would require a lot more overhead in maintaining than normal unit tests. The UI is almost always evolving and would like impact tests like these. It really boiled down to that it might not even be worth the overhead here and there were really no strong opinions either in MUST having them or NEVER having them.
Organization of Unit Tests
This topic was spawned by a third thread to the topic of Automated End to End Testing. After a quick discussion of how people were dividing up their unit tests and integration tests into categories to control how often they executed, it quickly turned to how are you grouping your tests. This lead to most of the people indicating that they grouped around a class. For example, if you an Account class there may be an AccountTests class that contained all the tests for account. However, another option was proposed: Behavior Driven Design (BDD). Several people out there, including our own Phil Japikse, has stated that “BDD is TDD done right”. Using BDD allows you to organize your tests into contexts, behaviors and expectations.
In BDD your focus of organizing tests becomes on behavior, not code location. It also is worded in a “Given …When … Then” or “If … When … Should” manner. In a BDD approach you’d see something like the following:
public class Given_An_Account { }
[TestFixture]
public class When_Withdrawing_Funds : Given_An_Account {
[TestMethod]
public void Should_Return_NSF_Notice() {
//…test code here….
}
}
Note that there is a class called Given_An_Account. This class would setup any sort of context that was required, such as getting an account ready to work with. Then the When_Withdrawing_Funds class inherits from the context and has it’s test methods. When you execute this from a test runner you’ll see a nice Pass/Fail on exactly what the issues is. This is more readable and easier to follow once you come back the system after some time or for the next person who has to maintain the system.
This line of discussion also led to specification languages to aid in BDD. According to one attendee RSpec is the specification language that rules them all and everyone is just trying to mirror what RSpec does in some manner. It will be interesting to see if people adopt RSpec as a specification language for .NET when IronRuby becomes more prevalent. Will the other specification test frameworks die off?
That’s all
We have lots of topics still on the docket for other meetings, and anyone can add new topics. Next month we will be doing something a little different in that Dan Rigsby from Indianapolis will be coming to speak on Oslo. He’ll give a 30-40 minute talk on Oslo and then we spend the rest of the meeting eating pizza and having an open discussion around the merits of Oslo (or something else if we tire of that topic).