Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Saturday, May 16, 2009

Do you really need to test that?

We all know Kent Beck. The co-creator of JUnit, one of the founding fathers of the Agile Manifesto, author of several eXtreme Programming books, just to highlight a few. Now that Kent has spent a decade telling us all to test everything... now he says, it is ok to skip testing.

I'll let that sink in a bit.

What he is basically saying is that it is ok for the kids to play in the street, if they feel that it is safe. Of course Kent is a big kid, so he will use his experience to determine if it is ok for him to play in the street. But what about the kids that don't know better? You know who they are. They are the kids that climb the tree without thinking about how they are going to get down. They are the kids that lock themselves in the closet without thinking about how they are going to get out.

Kids will be kids. They will make poor decisions if you give them the chance. That is why there are parents. Our job is to make sure that they don't make stupid decisions. Or perhaps we let them make bad decisions to teach them a lesson, just as long as we can control the environment to ensure that nobody gets seriously hurt.

So now is the time to decide if you are a the parent or a the kid. And if you think that you are the parent, half of you are probably wrong. That is the nature of the child, to think they know everything.

One way to measure if you are the parent or the kid is to use the Dreyfus Model of Skill Acquisition. If you follow Andy Hunt, you may have seen him speak and write about this. The model is basically a set of five stages that you progress through from novice to master. It helps explain why novices need lots of rules, and why experts don't think they apply to them.

On the Dreyful Model I often rank myself at a 4 1/2, depending on the subject matter of course. It can be an interesting exercise to rank yourself on the scale, then let your friends rank you to see if you meet your expectations of greatness. Likely you won't, but that is ok, it is in our nature to be overly self-confident.

Now back to testing. Is it really ok to skip testing? Kent thinks so, but I wonder if the followers of the TDD "faith" think the same. In many shops there is no ambiguity, there are only absolutes. You must test they say, but do you? Kent Beck thinks it is a judgment call.

Now I don't have the right answer other than there is no black and white, instead it is all gray. You should acknowledge that, and not immediately attack someone who says that they didn't write a test. Instead ask them their reasoning. Perhaps it is a good reason, perhaps not, but don't come to conclusions.

Wednesday, May 13, 2009

Software Craftsmanship

It has been a while since I sat down to write something, but that is because I have been caught up in learning. In March I presented at ETE in Philadelphia, and during my stay there I met a programming hippy Corey Haines. Corey was just like all of us, writing code for his day job, and like some of us enjoyed it. In December he lost his job, and with some money in the bank and a lot of free time decided to invest in himself. He began what became to be an adventure in pair programming, He now spends his days travelling the country, pair programming with anyone that will give him a place to stay and some code to work on. His journey is inspiring.

Now, this isn't a story about Corey, it is about software. In particular it is about good software. Corey, like many of us cares about the quality of his code. In his case he cares so much that he decided to pair with perfect strangers in order to increase his knowledge. While many of us can't afford to travel the country like Corey, or just find staying with strangers frightening, we find other ways to increase our knowledge.

So this is a story about writing good software. It is about craftsmanship. In December a manifesto was drafted. It was drafted by professional programmers that felt the Agile Manifesto didn't go far enough. They stated that working software was good, but well crafted software was better. That responding to change, while a virtue, isn't as good as steadily adding value. Out of this congress came the Software Craftsmanship Manifesto. It is a declaration of professionalism and quality, and I have put my name to it, along with thousands of others.

So what? So some coders put together a web page, called it a manifesto, and a bunch of other coders bought into it. I think it is more than that. I think our craft is changing, for the better. The best I have seen it described is in a presentation by Uncle Bob Martin. I recommend that you take a look, it is well worth the 60 minutes spend watching the video.

References:
http://www.infoq.com/presentations/craftmanship-ethics
http://www.infoq.com/news/2009/03/software_craftsmanship
http://manifesto.softwarecraftsmanship.org/
http://www.phillyemergingtech.com/
http://agilemanifesto.org/
http://www.coreyhaines.com/
http://en.wikipedia.org/wiki/Pair_programming

Wednesday, December 24, 2008

Developing Applications more Efficiently

Your boss walks up to you and says, "we need to be more efficient". This seems reasonable; efficiency lowers costs, and assuming you don't sacrifice quality, who in their right mind would argue that this is a bad thing. But now think about it a little. How can you improve efficiency without being able to measure it? And how do you go about measuring efficiency when it comes to building software? That is what I want to discuss today.

The opening sentence in Tom DeMarco's Controlling Software Projects says, "You can't control what you can't measure". Robert L. Glass counters this in Facts and Fallacies of Software Engineering arguing that this is a fallacy. Both are well respected practitioners and authors in the field. So who is right?

Digging deeper into metrics you find the word "subjective" used a lot. DeMarco in his book Deadline even says, "don't sweat the units - while you're waiting to achieve objective metrifications, use subjective units". And then there is the cost of gathering these metrics. Robert Glass notes in his book that studies at NASA-Goddard found the cost gathering and processing metrics to be 7 to 9 percent of the project. Even though there are those that say that metrics provides a valuable benefit, from the outside it feels like that they are losing efficiency in order to measure a subjective value.

I am not dismissing the value of metrics, but I am arguing that it might not always be the best approach. For small teams working on small projects it may be difficult or impossible to define a "function point", one of the popular metrics used for analysis. Perhaps there is an alternative. What if you measured efficiency by the perceived value of changes in procedures. It is still subjective, but does not carry the overhead of other methods.

I think it may help to understand my thinking if I provided a concrete example. Let's say that most of the work you do are small browser-based applications, and each of them is constructed in a similar manner. They typically all use Hibernate and Spring, use the same security framework, always use Velocity for generating emails, use JNDI, external properties for configuration, and a dozen other similarities. Now let's say that you do this often enough to know that it takes about 45 minutes to setup a new project, and that you will probably build 20 or so applications like this in the next year. So we could reasonably put a number of 15 hours spent per year on setup, and that number is much higher if you need to teach others how to do the setup. Based on this, if you spent a couple of hours building a prototype project, or perhaps a couple of them, you have become more efficient.

Obviously a savings of 15 hours per year isn't spectacular, but that is one small change. What if you can make small change like this every week? All of a sudden we are talking about nearly 800 hours per year, or roughly five months of developer time. Again, we are talking about each small team, so this is considerable. And your small team didn't get any smaller, so this gets compounded because the team can now complete more projects.

Again, I am not dismissing the gathering of metrics, I am just looking at the problem from a different perspective. Instead of measuring output I am measuring the savings due to added efficiencies. If I can introduce measurable efficiencies without degrading product quality, I don't need to know what my output is in order to know that things are more efficient.

Author's Note: Thought is an ongoing process. I can't conclude with any certainty that my theories are accurate. Accuracy can only be measured by real world use. If you have different conclusions, either in theory or practice, I would like to hear them.

Thursday, July 31, 2008

What do you think "great software" means?

I am always looking for new ideas and new ways of doing things. Today I find myself reading Head First Object-Oriented Analysis and Design, and in chapter one it ask you the question, "what do you think great software means?".

Ok, I'll take a stab at that.

Great software does what the customer wanted, and a little bit more. From the user's point of view it should be simple, reliable, and easy to use.

One of my more successful applications was a issue tracking system, similar to Jira, but with less bells and whistles and no admin interface. Internally we also used a monolithic application that was purchased for about $250,000 with another couple hundred thousand spent on training, support, and custom development. It took some time, but in the end the home-brewed application won out, but not because of it's superior feature set. The application gained popularity because it was easy to use (and easy to teach someone to use), did exactly what we needed, and could be customized to fit our exact future needs. That expensive behemoth on the other hand wasn't completely suited for what we needed to do, and could not be customized to do exactly what we needed, but it was as close as we could get. This inability to meet our specific needs meant that it was a source of frustration by the people that used it.

Great software is easy to maintain. By "maintain", I mean that it rarely breaks down and is easy to get running again. By "maintain", I mean that it is easy to customize and extend.

It has been shown in study after study that the cost of maintenance is a huge part of the total cost of a software package. Maintenance includes both keeping the application running and enhancing it. If an application is a "success", you will spend most of your time enhancing the product. If it is a "failure", you will be just trying to keep it running. Happy users want more features, unhappy users just want to use a different application.

Great software is easy to read. A developer can jump right into the code without ever seeing it before and not run away screaming.

If you write an application for your company and you are the only one capable of understanding how it works, then that application is a failure. It may give you a sense of job security, but when you leave the company they may find it cheaper to replace the application you wrote than to try to understand it. I always take the time to look for ways to simplify the code, make the code shorter, make it easy to read and understand. The best code can be easily understood without comments or documentation.

Saturday, March 08, 2008

Review: Project Management with Jira

According to the Jira website, Jira is...

JIRA is a bug tracking, issue tracking, and project management application developed to make this process easier for your team. JIRA has been designed with a focus on task achievement, is instantly usable and is flexible to work with.


I had already been a casual user of Jira, but due to a business need I needed to look into it a bit further. I am rather impressed with the product, so I wanted to share some of my experiences.

Try Before You Buy

Atlassian, the company that publishes Jira really got this one right. Once you register on the site for free you can then download the application and generate a 30-day key. The key is tied to the "server ID", so you need to install Jira first before you generate the key. Once you plug in the key you now have access to the Enterprise edition, fullt functional in every way.

In my case we wanted to get some real-life experience, so we started using it to manage a real project. The project ran longer than the 30-days, but to Atlassian's credit, I went back to their website and generated another key that allowed us to use Jira for an additional 30-days. I did this several times, so you could potentially evaluate the product for many months if you needed to.

Sales Calls - None!

When you sign up on the Atlassian website and generate a product key, you will receive an automatic email from a Jira sales representative that says something to the affect of "call me if you need help". Besides that automatic email, I received no emails or calls from a sales representative. I really appreciated this.

The Install

This was incredibly easy. You simply download the zip/tar, decompress it, and run the start script. Jira has a stand-alone download option that ships with Tomcat and by default uses Hypersonic DB, which for evaluation purposes is all you need. The longest part of the install process for me was downloading the Jira distribution and copying it up to a server.

The Tools - Security

Jira has quite a few options for security. You can manage users locally, or point Jira to an LDAP server (which I have not tried yet). The users can then belong to groups, and users and groups can be assigned to projects. Each project as "users", "developers", and "admin" roles, and you can define what each of those roles mean on a per-project basis. And if that isn't enough, you can create individual issue level security schemes, and specify the visibility of comments and work logs.

In short, the security capabilities will meet all but the fringe use cases. You can read more about Jira's security setup in the Jira on-line documentation.

The Tools - Mailboxes, Workflows, and More...

There are just way too many good features to explain each in detail, so perhaps a quick summary will suffice.

  • Jira can listen to a POP3/IMAP mailbox and auto-create new issues for you.
  • Define workflows, the steps from project creation to completion.
  • Create custom issue fields, with a dozen or so field types built-in.
  • Backup everything to, and restore from XML files.
  • Turn on logging/profiling on the fly to debug Jira performance issues.
  • Built in SOAP and XML-RPC interfaces (although creating a SOAP client to connect to Jira was non-trivial in my case)
  • Run Jelly scripts to perform maintenance tasks.
  • Customize resolutions, priorities, and statuses.
  • CVS (and SVN with a plug-in) integration.
  • Integration with FishEye and Crowd, other Atlassian products.
  • And more...


The easiest way to find out if the tool has the features you will need is to just download it and try it out. For me this provided much more information than just reading the documentation on the Jira website.

Enhancing and Extending Jira

Jira makes it pretty easy to create plug-ins that you can distribute as a jar file and just drop into Jira's lib folder. Each plug-in jar file has an atlassian-plugin.xml file in it that described the nature of the plug-in to Jira. The plug-in may include reports, admin tools, extensions to the project and issue interfaces, or resources like images and CSS files. And not only can you add features, you can also extend existing ones in order to change their behavior.

This is all well and good, but I quickly found some limitations. First, the documentation is typically light on needed information, is buggy, or is a little old. In general I found that I needed to do a bit of searching between the Jira documentation, issue tracking system, and the forums in order to get the information I needed, and it still didn't answer all of my questions. For the rest I took a look at existing plug-ins to see how they had solved the problems.

Beyond the documentation one missing piece I found was that you can't use the Jira persistence engine without tweaking Jira's configuration files. This is problematic for me because I want to stay away from that, as altering Jira's configuration will make upgrades harder as I would need to re-alter the config for each upgrade, and retest the application as well.

In all fairness this is often not needed, as you can often attach arbitrary properties to whatever business object you want. In my case though, the Project object does not support this, so I needed to look at other alternatives for persisting additional project properties.

So mixed results here, but in general Jira plug-in system is pretty good.

If you need to perform customizations that go beyond a simple plug-in, paying customers of Jira can download the Java source code of Jira. This allows you to change the guts of Jira to your hearts content. Of course, this will make upgrading extremely difficult, but it is nice to know the option exists. This is also useful if you want to see what Jira is doing under the covers, making plug-in development a little easier.

The Cost

Software is expensive, especially if it isn't your standard home-user type software. So for what Jira is, it is fairly inexpensive, with options from around $500 to $4000. This also includes a year of upgrades plus email support for a year. This is a deal compared to other business applications.

For open-source teams the deal is even sweeter. You can use Jira for free! This would explain why a lot of open-source projects have adopted Jira.

In Summary

Features great, extensibility not bad, the price good. If you are looking for an issue/bug tracking tool and want a little more than the open-source alternatives, Jira is a great choice.

Thursday, December 20, 2007

Testing Servlets with JUnit

In my day-to-day job I write a lot of unit tests, and I try to test everything I can. Recently though I had written a service that I was unable to test completely. One of the methods in the service had the job of sending an HTTP request to a remote server and responding with the results. For my project I used commons-httpclient to send the request.

@SuppressWarnings("unchecked")
public String sendHttpPost (String url, String queryString)
throws Exception
{
String result = null;

try {
HttpClient client = new HttpClient();
PostMethod post = new PostMethod(url);
post.setQueryString(queryString);
client.executeMethod(post);

result = post.getResponseBodyAsString();
post.releaseConnection();
}
catch (Exception e) {
throw new Exception("post failed", e);
}

return result;
}


If you have used commons-httpclient, this is about as simple as it gets, but I still wanted to have a unit test for it. So the problem became, "how can I test this method when it requires that I hit a web site". After some searching I found that the Jetty servlet-container has a ServletTester class just for this purpose.

In my Maven 2 I included the ServletTester using the following repository and dependency information. I always use Maven 2 as allows other developers to quickly set up their IDE and download all required JARs. If you don't use Maven, you will need to manually download all of the dependencies.

<repositories>
<repository>
<id>codehaus-release-repo</id>
<name>Codehaus Release Repo</name>
<url>http://repository.codehaus.org</url>
</repository>
</repositories>

...

<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-servlet-tester</artifactId>
<version>6.1.6</version>
<scope>test</scope>
</dependency>


With this in place the next step was writing the JUnit test cases. For me I wanted to initialize the servlet-container once, then run a set of tests against it. In JUnit 4 you can use the @BeforeClass and @AfterClass annotations to mark methods that should be executed before and after all of the tests.

public class HttpPostServiceTest
{
private static ServletTester tester;
private static String baseUrl;


/**
* This kicks off an instance of the Jetty
* servlet container so that we can hit it.
* We register an echo service that simply
* returns the parameters passed to it.
*/
@BeforeClass
public static void initServletContainer () throws Exception
{
tester = new ServletTester();
tester.setContextPath("/");
tester.addServlet(EchoServlet.class, "/echo");
baseUrl = tester.createSocketConnector(true);
tester.start();

}

/**
* Stops the Jetty container.
*/
@AfterClass
public static void cleanupServletContainer () throws Exception
{
tester.stop();
}
}


The code highlighted in blue is where we start an instance of the server. I created a new instance of the ServletTester, setting the context path and adding a servlet mapping. This alone does not bind the server to a port, for that you need to call createSocketConnector(true), which binds the server to a local port and returns the URL. The port used will be a high unused port. I save an instance of the ServletTester so that I can stop the service in the @AfterClass block, and I save the baseUrl so that I can target it in my tests.

The servlet I added to the container I called EchoServlet. This servlet simply echos the parameters passed to it.

public class EchoServlet extends GenericServlet
{

@SuppressWarnings("unchecked")
@Override
public void service (ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
PrintWriter out = response.getWriter();
Map<String, String[]> params =
new TreeMap<String, String[]>(request.getParameterMap());

out.println("SIZE=" + params.size());
for (Entry<String, String[]> entry : params.entrySet()) {
out.println(entry.getKey() + ":::"
+ StringUtils.join(entry.getValue(), ","));
}
}
}


The servlet takes the parameter map and creates a TreeMap out of it. The TreeMap is needed so that the parameter names are returned in sorted order. Being able to predict the order of the returned keys is required in order to test against the output of the servlet.

To finish things up, I just needed to write a unit test.

@Test
public void testPost () throws Exception
{
PostService svc = new PostService();

String res = svc.sendHttpPost(baseUrl + "/echo",
"foo=bar&baz=%25%26%3D%2F");
String[] resList = StringUtils.split(res, "\n");

assertEquals(3, resList.length);
assertEquals("SIZE=2", resList[0].trim());
assertEquals("foo:::bar", resList[1].trim());
assertEquals("baz:::%&=/", resList[2].trim());
}


After that, run the test and watch it work.

Saturday, September 22, 2007

Grokking Domain Specific Languages

A Domain Specific Language (DSL) is a programming language that is designed for a specific task. Although this definition is overly simplistic, it is good place to start.

As a Java developer I use domain specific languages in every non-trivial project that I am involved in. I use Hibernate, which uses an XML configuration file to map Java properties to data in a database. This XML file is a DSL. This also goes for DBUnit dataset files, Spring bean definitions, and even HTML. If might not be natural to think of a "configuration file" as a DSL, but it is.

For a really good discussion on DSL's and related concepts you should watch Language-oriented Programming and Language Workbenches, a presentation given by Neal Ford and Martin Fowler.

In watching the presentation I learned that DSL's don't always mean that you need to create a new language with a new syntax. Let me show you am example so that you can see what I mean.

The code below is a testing "language" of my own concoction that you would use in a JUnit test. It allows you to easily spin up a Spring config, prepopulate the database with DBUnit, then test the output of a Spring controller.


WebRequest req = createRequest()
.forURL("/app/login")
.usingPostMethod()
.withParams("user", "rhanson". "pass", "r@ckin")
.withSessionAttributes("user", null);

executeSpringController(
"loginController",
usingSpringConfig("applicationContext.xml"),
usingDBUnitData("dataset.xml"),
usingRequest(req)
)
.assertThatViewEquals("loginSuccess");
.assertThatSessionAttribute("user", isNotNull());
.assertThatSessionAttribute("user.name", equalTo("rhanson"));


I'll bet that without providing any documentation for the API that you can easily tell what the test is doing. In the presentation I noted, martin Fowler states that readability is one of the cornerstones of a DSL, and I think this one passes the test.

My DSL is written in Java, I didn't create my own programming language for my DSL. This is beneficial because it makes it easy for any Java developer to understand my DSL, and IDE's like Eclipse will be able to provide code completion, making it even easier to use.

DSL's make a lot of sense for simplifying tasks, in turn reducing the cost of a project.

Some references: