The intersection of technology and leadership

Category: Development (Page 16 of 18)

Starting a new development project

I’m a big believer that if software projects aren’t set up correctly at the beginning, it potentially puts a lot of drag on the team going forward. This doesn’t mean planning everything meticulously before implementing it. Rather, its mean experimenting and evaluating whether the tools you choose give you the things you need for your project. When I set up new development projects, here’s some guidelines I try to follow:

  • Check out and go – Contributors should not need to install 10 applications, four plugins and configure special settings in order to start developing. I’ve successfully tried techniques like checking in your build tool (like ant) alongside your code, with windows and unix executables (go.bat, go.sh) that enable people to get consistent feedback quickly. On one project, we had all of the tools checked into a different subversion module and we ran a configuration script that set up the environment variables we needed to start developing. Eclipse allows you to bundle up all your plugins you need. If you don’t want to check things into source control, put it onto a standard share accessible to everyone. If you do need to install specific applications, list the details so they can run through it like a checklist (although prefer this as a last option).
  • IDE (un)bound – If you need to open your IDE to assemble your final executable, you’re far away from the ideal situation. It’s important for me that you can build your application in both your IDE and from the command line. Doing this early in the project helps raise issues about what can and can’t be done with your toolset.
  • IDE friendly – Having said that, it’s important that developers can debug easily, and so ensure that your code works with the environment and tools of your choice
  • Determine the testing strategy – Work with your QA to understand what things you will test, and to automate or try to automate. Determine what tools they might need to properly test your application.
  • Great example test cases – Trying to automate unit and acceptance tests is important to try before you have your final application (as the design may change to accommodate better testing). Your scripts should look neat and concise. If you have 100 lines of setup, 100 lines of test, imagine if you then need to write 1000 more of these and the nightmare your code will be to maintain.
  • Have a consistent code style – Strive for collective ownership. Having code that looks completely different from each other will detract from this. Define code format style early (where curly braces go, etc). Spend more time discussing the more interesting standards that may actually have an impact on your project (when, where and what to log, how to handle exceptions).

Keeping regular expressions readable

It’s easy for regular expressions to become one long string, involving lots of (round/square) brackets, backslashes, and other random symbols. It’s concise, yet often at cost of readability. We’ve recently been using a pattern that works well for us, where we’ve broken the expression down into its important constituents, still defined as a single string, but with a brief explanation for each part. Here’s a simple example:

Instead of public static final String SPECIAL_PATTERN = "(\\w)+-([a-zA-Z0-9])+-([a-zA-Z])+/\\w+" we modify the declaration slightly so it’s

public static final String SPECIAL_PATTERN
  = "(\\w)+" // at least 1 letter, number or underscore
  + "-([a-zA-Z])+" // dash with at least one number or letter 
  + "-([a-zA-Z])+" // dash with at least one number or letter 
  + "-(\\w)+" // dash with at least one letter, number or underscore

In our situation, applying Extract Constant or Extract Variable I think would have reduced readability so is a nice tradeoff of conciseness with readability.

Treat your App.config like a global variable

I remember looking at a few codebases in C# and it surprised me how many people encapsulate some of their system well, yet treat their application configuration as a different thing. Many times I’ve seen code that looks like: ConfigurationSettings.AppSettings["DatabaseConnectionString"]; alongside the thing that is using it. In fact, I often see this code repeated in various parts of the system wherever anyone needs to draw on application configuration.

Global variables are bad
Most good programmers seem to realise that most global variables are bad, yet this is exactly what I think accessing the application configuration is like. If you want to change the way your configuration is loaded (i.e. programmatically or from a database) think of how many places you now need to change it, let alone how it effects the order in which you instantiate objects.

My advice: Separate the use of configuration from where it declared
I try to follow the pattern isolating the configuration into a single class depending on the access method, such as:

  • DatabaseBackedConfiguration
  • FileBackedConfiguration
  • DefaultInMemoryBackedConfiguration

Each of these classes them implement several roles depending on what configuration they might provide such as:

  • HibernateConfiguration
  • ApplicationConfiguration
  • ArchivingConfiguration

Having smaller roles makes it clearer what sort of configuration is really needed for a particular consumer, and it allows me to change the decision about how that configuration is now provided to it. It enables me to do things like specify different environment configurations and do so in the method that I prefer.

Defensive programming depends on context

I remember stepping into a heated discussion with two developers who just couldn’t agree whether or not they should be writing their code defensively. One of them argued they should always be checking for null, checking for illegal input and throw appropriate exceptions before doing anything with it. The other argued that they should not because of the amount of code that would add to every single method. I think I understood where they were both coming from and suggested that they were both correct though under different circumstances. One of them asked me to explain, and considering I see this argument resurfacing again here and here, I thought I’d post my thoughts.

Defensive Programming

Scenario A: Dealing with those outside of your circle of trust
Let’s say you’re working in Team A, developing an API for the greater public. It might be as big as a core platform development API, or an opensource library. Either way, it’s not possible to learn how everyone is going to use your API and not enough to simply document it because some people will not read all the documentation. Programming defensively helps consumers understand how your code was meant to called because there is no single way you can ensure your clients have the same understanding, regardless of the amount of documentation you put together. They lie outside of your sphere of influence. The longer the release cycles, the greater the risk someone might use your API in a way you hadn’t intended. This is the situation the authors of the .Net Framework Guideline worked under and as such you’ll see they’re emphasis on defensive programming. You don’t always have to do it in this situation, you’re just more likely to.

Scenario B: Dealing with those inside your sphere of influence
You might be working closely with another team, either in your organisation or in another one, writing an API for them to consume. Do you write your code defensively? I think it depends on how much influence you have. If you have enough influence that both parties understand the contract well, and your release cycles are reasonably fast, you may not have to. If you have long release cycles, or your relationship with the other team is more like the general public (you have no idea how they’re going to use your API), you may choose to program more defensively to provide faster feedback for your clients. I try to use this as the last resort when I’m in this particular situation.

Scenario C: Inside your own team
I rarely find good reasons to program defensively for code that I will ultimately write. It doesn’t really make sense for me to add in additional lines of code where I can easily test all the execution paths of the final code.

Conclusion
This advice is in constant practice. Even when you’re working under Scenario A, it’s only your external APIs that you are probably interested in programming defensively. Delegating to all other private or internal members will often be in the context of Scenario B or Scenario C. Remember the rule that ‘Context is King’, so ensure everyone understands that context before jumping to a particular conclusion about what you should or should not be programming defensively.

Unhelpful Error Messages in Maven

What’s wrong with this: “Cannot execute mojo: resources. It requires a project with an existing pom.xml, but the build is not using one.”

How about? What are you talking mojo to me for? What is going wrong and how do I fix it?

Perhaps something like this would be a better error message: “Maven is looking for the pom.xml file and cannot find it. Maven assumes this file is in the directory you are running it from. If you are running Maven in a different directory, perhaps you might want to use the –file switch.”

UnFIT for use

It always amazes me at how many people misinterpret FIT (Framework for Integrated Testing) and I guess it’s based on the way that it’s been marketed. I’m not exactly a big fan of FIT and the biggest reason is that people don’t really understand what it’s best for, and use it all over the place where it’s not very appropriate more so than people who do know what they’re doing with it. In the last month, I’d heard statements such as “FIT is good for driving tests below the UI layer”, “FIT is great for acceptance tests”, or “We use FIT all the time”. Please stop this!

Let’s have a look at this table I put together that compares FIT and JUnit. Of course, this comparison also applies when comparing FIT to NUnit or one of its other close brethren (TestNG, etc):

JUnit Comparison Versus FIT (Framework for Integrated Testing)

Let’s get this straight: The only thing FIT is good for, is using it as a tool to help communicate with a customer. That’s it. It’s terrible for writing automated test suites, FIT encourages terrible programming habits, IDEs offer very minimal tool support and many developers don’t seem to really understand, nor want to understand how it works. I’ve seen a test suite where developers deployed FIT tests to a web container because “it was HTML” and they thought it had to be deployed for it to run. Grrrr.

The biggest barrier for FIT is that it requires a lot of education around how developers best use it, how they use it to help aid communication, and then understanding how to maintain it. Unfortunately I’ve never seen the payback you get from investing this time that’s better spent directly trying to improve the communication gap. I think it’s because the conventions used to bridge HTML to code aren’t natural and, without spending the effort to really help developers understand it, quickly leading to a whole mess of tightly coupled code and eventually, test coma.

The recommendation
I’d use FIT sporadically to help bridge gaps between the team (analysts, developers, testers) and the customer – especially for data driven examples. Acceptance level tests in JUnit should be refactored to a point where it’s understandable to customers (i.e. using as much of their language as possible). If you decide to go down the FIT route, refactor mercilessly to split out what the FIT fixture do and how they do that (some sort of driver, component, etc). In my experience, the latter should be immediately usable in another test framework, and in fact, should be what you’re striving to reuse in that other test framework.

Losing my London .Net Users Group virginity

About 60 people (only of which three or four were female) crammed into a tiny room near Red Lion Square last night for the London DotNet Users Group meeting. I have no idea what the normal turnout rate is, though I guess the topic (TDD) probably drew quite a lot of people. Three people presented and the meeting ran for a total of three hours until 9:30pm at which point, we left for the pub and stayed until closing.

The three presenters for the evening and the topics included:

  • Zi Makki: TDD and the Data Access Layer
  • Sebastien Lambla: The MVP pattern
  • Ian Cooper: Best Practices for TDD

The first presenter covered some techniques for dealing with integration points with a database. I noticed that he used Coderush (all those bright colours and arrows hurts my eyes!) instead of Resharper though I think he was using VS2008. It seems that Coderush also lacks a way of extracting a class into a file for a different assembly or at least it wasn’t used. I’m pleased the presenter used BDD styled should as I’ve found these help focus the person writing the test. He finished with some very useful tips though I was worried by one of his final statements, “Avoid Integration Tests”. I think as a principle, fine. For someone in the early stages of learning TDD (think of the Shu in the Shu Ha Ri), it’s a dangerous blanket statement they may follow as integration tests can be useful points of feedback as well.

The second presenter talked about the Model View Presenter Pattern although after seeing his implementation, and I think it is probably more an example of both the Supervising Controller and the Presentation Model. I find it interesting to see how far Sebastien pushed the databinding features of ASP.Net. It’s given me some thought about how I might actually give databinding another real chance. I’m really interested to see how this works in an update mode in this same world. I also learned here that the Macbook Air isn’t great for doing presentations where you need to write code (the buttons are too small!)

The final presenter, Ian Cooper talked over lots of best practices around Test Driven Development. Ian has plenty of great things to say and one of my only issues was that there was probably far too much content on the slides to cover in just an hour.

One of the other topics that wasn’t covered and I think is important for newbies to TDD is understanding when to or when not to use it. As I wrote in a previous post, if you’re doing TDD all the time, you’re doing something wrong.

I really enjoyed talking to other people who went along and I’ll definitely be back again sometime.

Some notes on C# 3.0

I’ve been playing around with some of the new features of C#3.0. I installed VS2008 and the new Resharper 4.0 EAP available here. I expect most of the Jetbrains EAP stuff to be pretty buggy and I’ve already had it crash on me more than five times today. Still, being able to refactor and navigate around files is worth the buggy trial.

Out of the box support for the new language features looks interesting as well as some of the new tools and refactorings in place. Interestingly, default settings suggests constant use of the new var keyword replacing the class declaration you should be using. I’m a little uncomfortable with this as the default setting though it could be because I’m not used to seeing C# code like that.

I started playing around with extension methods, trying to convert the ReflectUtil I wrote back in this post. After a rewrite, some of the APIs looked a bit better although at the cost of making some private inner classes and delegates public. I’m not sure if I like it yet and still trying to think of some guidelines for when to use it. I think definitely having all the extension methods grouped together would help – either in one big Extension class (if you don’t have too many) or in a [Class]Extension class so they’re much easier to locate. If you find youreself writing StringUtil classes, consider converting them to Extension classes. Right now, extension methods only work on instances, so if you want to be able to add static methods, vote on the topic here. I’m not yet convinced it’s that useful just yet though.

Lambda expressions look especially nice although now it’s just plain confusing how you have three ways to do something and there’s really little benefit out of the two more verbose ways. Use this to replace anonymous delegates with a less verbose method.

If you do Test Driven Development all the time, you’re doing something wrong

I’m a big fan of Test Driven Development, and even more of a fan of Behaviour Driven Development. So it makes me sad to see really great developers adopt these techniques a bit too dogmatically.

Most developers operate in two modes when they’re writing code. Test driven development helps amazingly with only one of them. Use it for the alternative and you’ll quickly become frustrated, hate TDD and never use it again.

What are these modes? Experimentation and, what I call Focused mode.

Experimentation mode’s main objective is learning. It might involve poking at a library, tool, language or framework to understand how it works, how to interact with it, and perhaps understand some of its limitations. You might learn how to configure it, how to deploy it, and even how to test it. If you write code, it usually is throw away code because you don’t apply the same level of code quality because it stops you learning about things quickly. When people apply TDD during this mode, the first normal hurdle is they don’t know where they should be test driving it because they haven’t learned where the cost-benefits payback lies. They spend a long time writing their test only to find out the thing they’re doing won’t work in that way and then sulk over the time spent writing the test.

Focused mode’s main objective is producing something that will be put into production, used by people and extended upon. Here you want to write just enough code to provide the correct functionality. This is the most ideal time to apply TDD. You care about the quality of the code you produce here.

Recognise what mode you’re operating in, and understand where to apply (and where not to apply) TDD to get maximum benefits. In short, avoid TDD during experimentation and use it when you’re focused.

« Older posts Newer posts »

© 2024 patkua@work

Theme by Anders NorenUp ↑