This is the best response I’ve ever seen to this question, and I’m glad to see such pragmatism from an industry leader like Kent Beck.
These days, there is a certification for everything. Almost every discipline in software development has several different certifications that you can get if you attend a training class and then take a test that verifies that you understand the book definition of a process or language. This totally misses the point.
In some industries, certification matters. I’m glad that my doctor has to go through 12 years of school and thousands of dollars in student loans in order to get his M.D. If someone can make it through that, I have confidence that they know what they’re doing.
The bar for software certifications is much lower. All you have to do is pay a few thousand dollars for a training class and then take a test that shows that you paid attention in class and understand the basic concepts.
What do we think we get out of these certifications? A basic understanding of the principles, maybe. The problem is that those things are the easy part of software development.
Here are some of the things that I actually look for when hiring people:
- Ability to listen to users
- Understanding your team members
- Motivation and purpose
- Attitude
- Passion
- Ability to think outside the box (as opposed to being certified that you know that you how to think inside the box)
- Learning ability
- Problem solving skills
I feel that one of my greatest strengths is the ability to make it up as I go. Sure, I might have my Agile bag of tricks, but every project and environment is so different. When we inevitably encounter a problem, the hard part is finding the right solution for it, and no formula or certification is going to tell you the right solution to every problem.
Certifications aren’t all bad, if you spend a week learning learn how to be a “certified Scrum developer”, you’ll learn TDD and good OO practices and other things that will help you succeed. We can argue about whether it’s worth the money, but you are going to learn some good stuff.
The point of all this is that (in my opinion) some of them most important qualities in a team member are less quantifiable things like attitude, passion, and the ability to think outside the box. These are the things that I want to strive for, and the only “certification” that you can get for this is experience.
If you’re a developer, do you have your own personal development database that you can recreate at the touch of a button?
If you said no, you’re not alone. In fact, I’ve been in that situation on many projects, where the entire team shares one big development database that is a backup of production, and all schema changes need to be coordinated with the other developers on the team. Usually things are this way because back in the day someone didn’t create a way to have local databases.
We were in the situation and we made the investment to have someone spend a week or two taking a copy of production, deleting all of the data from tables that weren’t lookup tables, and then creating a way to run all of the new SQL scripts against the small baseline copy. Now I can recreate my development database at the touch of a button.
The benefits of this are obvious, but since many people haven’t made this investment yet, let me list them anyway:
- I can hack up my database and not worry about affecting other developers
- I can hack up my database and then start over if I screw something up (as opposed to piece things back together so that the rest of the team can keep working)
- Automated tests that run against the database run MUCH faster
- No more confusion when someone else on the team changes some important piece of data without telling you
- I can check out any revision of the code and create the database that existed at that point in time
If you don’t have a local, recreateable database yet, make the investment. You will reap the benefits many times over and you’ll be so glad you did.
One of my favorite tricks around changing how a team does something is to get other people to drive the change for you.
This especially applies if you’re coming into an organization as an outsider. Most people are initially somewhat skeptical of outsiders and you need to earn their trust. This sometimes takes a long time, and you might want to change some things before you’ve built up the political capital to drive it yourself.
When I started on my current project, all of the QA testing was done manually, and QA people weren’t involved in the process at all until after the code had been written. As a result, they would get features to test and not have any idea of what they had to test, and many times they couldn’t trust that the requirements were even up to date.
The solution that I was hoping for was to get QA people to meet with developers and BAs before the code was written so that they could come up with a test strategy and acceptance criteria. That way they would have input up front, and developers could automate all or most of the acceptance tests, which would save QA a lot of time. But I didn’t want to bring it up myself.
So I would ask questions in meetings. We all agreed there was a problem, so I would ask everyone what ideas they had to fix it. Eventually someone would give the answer I was looking for. “That’s a great idea!”, I’d say, “How do you think we should do that?” Now it wasn’t my solution, it was someone else’s. That person feels good because they came up with a good idea (that eventually ended up working), and since that person is actually on the team and doing the work, they might have more credibility than an outsider like me.
I would much rather have someone else get the credit for coming up with the ideas, because I think that it gives the idea a better chance of success, and when it works, it encourages people to try and think of more ways to improve things. If one person comes in and tries to drive and enforce all of the change, it’s very easy for people to discredit that person (maybe even just in their mind) and try and fight the change. But when the ideas are coming from multiple different people on the team, now you have more and more people buying in because they’re the ones coming up with the ideas!
When I think of a “coach”, I think of someone who helps other people find the path to success. You can try to push them in that direction and they might turn around and fight you instead. Or you can help them use their own ideas and expertise that they already have to find their own way.
If you’re a developer, you probably aren’t extensively involved with requirements gathering, but they affect you dramatically because you have to read requirements and turn them into code. So how would you like to have requirements written so that you have all the details that you need to implement the feature and easily write acceptance tests (hopefully automated)?
I have ideas but only some answers, which is why we’re talking about this on Thursday at the Columbus ATDD Developers Group. We’ll be talking about questions like these, among other things:
- How can we structure our requirements to help us come up with our acceptance criteria?
- What requirements should we have other than our acceptance criteria?
- What can we do to help BAs make sure that they have all of the details that we need to write tests and write the code?
It’s a fishbowl discussion so we all get to figure it out together. I think it will be fun. I feel like there are some dots that I’m having trouble connecting when it comes to requirements gathering so hopefully we’ll turn on some light bulbs.
The meeting will be Thursday, August 2 from 11:30-12:30 at the Quick Solutions office, 440 Polaris Pkwy., Suite 500 in Westerville. Please RSVP so that we know how many people are coming.
If you want to change something in your organization, that must mean that there is some problem that needs to be fixed and a solution to fix the problem. That’s obvious, right?
Maybe it’s obvious to you. But is it obvious to others?
If other people on the team don’t see that there’s a problem or if they’re OK with the status quo, it’s going to be very difficult to get them to change. For example, let’s say that your team does not do automated testing and you want to get developers to start writing unit tests. The problem is that you have lots of bugs and it’s scary when you have to refactor the code.
But wait a minute, do other people think it’s a problem? More than that, do they think that your solution will be better than the status quo? That’s a completely different question! Maybe the developers on the team have all been getting good reviews from their manager. They might not like the bugs and the scary refactoring, but they might not think that introducing TDD will fix the problem, or they might think that it’ll be more work to learn TDD than just deal with the code without tests.
You need them to both see the problem and buy into the solution (man, this is getting hard). So maybe you go and write unit tests around some part of the system. Then later when another developer needs to change the code, you show them how easy it is to run the tests and see that the code is still working. Now maybe they’re more open to your solution because they can see the benefits of it and see that maybe it won’t be as hard to implement as they previously thought.
Until you can get people to see that there is a problem and that your solution is viable, you’re probably not going to have a lot of success getting them to change.
If you want someone to change, you have to not only give them time to change, but you need to show them that you will be there to support them when they need help. They might be worried that they’ll starting learning the new way and then you’ll leave them out to dry without any help to get them the rest of the way.
The other day I was making a change to a part of an application that I don’t deal with much using a framework that I’m not an expert in. It wasn’t very hard to figure out, but I didn’t really enjoy it. I hate feeling like something is taking me way longer than it’s supposed to just because I’m not the expert in the application or technology. I’m sure you all can relate to this.
Now think about having to do something completely foreign to you, like a new language, platform, or technique that you’re really not good at. Or maybe you’re trying to change the way that your business analysts write requirements or your QA people test software. We can criticize people for being fearful of change, but we’ve all been there are some time.
If you’re the one who knows what they’re doing when it comes to the new whatever you’re doing, look really hard for opportunities to help people. Most people are reluctant to ask for help (maybe they have egos, they think you’re too busy, or they just don’t want to get up out of their chair). Instead, ask people how they’re doing today. When they mention that they’re struggling with something, go help them with it, and then offer to help them again if they need it.
Some people are definitely more adverse to change. If you’re the one proposing the change, chances are you are not as adverse to change as others. You have to try and put yourself in their shoes. They have good, logical reasons in their mind to not do what you want them to do. If you can empathize with them (or at least attempt to), you’ll be more in tune with their fears and what you can do to help them through it.
There are many people on software development teams that are trying to change the way that their team works, whether it’s a new process, a new technique, or new way of development software. Yet so many of them never see lasting change come about.
You can try to drive change or encourage people to change, but the people on your team have to feel like they have some room in order to try and make the change. If they feel that there is a risk of failure because changing the way they work will lead to poor results, then they won’t take the chance.
Stop the fire fighting
I’ve seen many teams that feel like they’re in endless fire drill mode. When you’re in these situations, you have very short term thinking because you feel like you’re always solving short term problems. Sometimes there are fires, but ultimately what we want is more long term thinking. But in order to get that long term thinking, you have to give people some stability and peace in their day to consciously think about doing things the right way instead of doing whatever it takes in order to fix the problem at hand.
This is easier said than done. It takes someone awhile to switch from short term fire fighting mode to a long term mindset. For me, someone may say that the fire fighting is over, but until I can go a week or so with some stability, I’m not really going to believe that I’m going to have space in order to think differently.
This requires you to rethink how you plan your capacity. It probably means that you need to either do less work and get more people to help get the work done. Either way, you need to stop lying to yourself and saying that you can do as much as you’re doing with the team that you have.
This is where making the workload visible is important. Put everything, and I mean everything, up on a board. People should see what you’re working on now, what’s next, and what’s in the backlog. Put technical debt and refactoring tickets on the board too. When someone asks why those are there, explain how doing those tasks will allow you to provide more value and be more productive. If someone asks why you’re not getting as much done as they would like, you can show them exactly why.
It may take discipline, but if you slow down just a little bit to think about what you’re doing and how you can best do it, you can turn things around.
If you’re a developer, why do you do the work that you do? What’s the goal of all of the frameworks, databases, code, and tests that we swim in every day? I’ve been doing this professionally for ten years now, and I’ve noticed an interesting progression, and it wasn’t one that I had pursued originally.
Early on, I wanted to work with new technology. The goal was to do cool stuff with the latest technology and find new, better ways to do what used to be harder in the previous year’s hotness. Working at a consulting company was great for this. I got to do new projects every 6 months that often were greenfield and we usually got to pick the technology. Now we were smart about it and we weren’t just doing “resume builder” projects where to tried to use some new framework for the wrong purpose. We were delivering value. Everyone would always hope that they would land on that cool project using the latest stuff, and whoever wasn’t on said project would want to talk to everyone on the project and see what they were doing.
Two years ago I joined a Ruby on Rails project and spent a year in the Rails world. This was the pinnacle of hot technology (at least at the time). I loved how elegant the Ruby language was, the Ruby gem ecosystem, and the Ruby community’s focus on quality and testing.
Eventually my time on that team came to an end and I came back to .NET. I have nothing against .NET, but in terms of geek cred, many people would consider .NET a step back from Ruby (but that’s not the point).
What I noticed from my transition to Ruby and back is that no matter what the technology, the code isn’t what’s important. What is really important is how we interact with users and how we can structure our process and teams to best deliver quality software in less time. We need to value people over the tools that we’re using.
The longer I’m in this business, the more I realize that software development is all about people. It’s about using technology to help improve the lives of the people who use our software, that somehow we can use our coding skills to help them be more successful at their job. It’s about the people that we work with on our team, it’s about helping them feel everything that comes along with working alongside others to help the team achieve a common goal. It’s about looking out for those team members who are feeling overwhelmed by their workload and struggling to hold on to their confidence.
I still geek out on code, and I’m still glad that I get to spend most of my workday writing code. The means may be the same, but the ends have changed.
Software applications typically deal with two things — data and behaviors. The behaviors of the application use and modify the data and represent the business processes that we model using things like code and databases.
We all know that data is important. Most people think of the data as being very important, and often applications will have a very data-centric feel to them. The app may have some representation of the schema (e.g. using an ORM, creating business objects that mostly have the same properties as a database table). This is all well and good. But many applications struggle because they don’t stress the importance of the behaviors when writing the code.
The Wild West Data Access Strategy
I believe that the following simple rule should apply:
No data should be modified unless some behavior is requiring you to modify it.
If we don’t have some business reason to change data, then we shouldn’t be doing it. I’ll explain this by first showing you how not to do it.
Take ORMs for example. I like ORMs. There’s no reason to write ADO.NET code anymore, there is a much easier way to do data access.
The problem with ORMs is that you can load up any object from the database, change any properties of the object that you want, and then save it. This is very convenient, but too often people don’t make it clear why they are changing the data. You see this when people have huge “manager” classes (e.g. OrderManager) that contains a whole bunch of methods that load, save, and modify data. The problem is that when you have to modify code in those applications, it’s hard to do so because you don’t know what other things might be using that code and it’s not always clear why the code was written in the first place. Sure, maybe my IDE will tell me what methods call my method, but it might not tell me what behavior required that code to be written.
This can get even worse. I’ve used NHibernate on many projects and I’ve gotten to know it pretty well, but NHibernate has this concept of FlushMode. In NHibernate you create a “session” (which is different from the “session” in-memory cache in web frameworks). Within a session, you can load up objects from the database and NHibernate will keep track of what objects are dirty. The default FlushMode in NHibernate is Auto, which means that every time you do anything that accesses the database (be it a call to save or even a query), it will save all dirty objects to the database. This leads to incredibly brittle code. I don’t ever want my data to be modified unless I do it for a very specific reason, and I certainly don’t want data updated when I do a query! (You’re better off with FlushMode.Never, which means that you have to explicitly tell NHibernate to save dirty objects.)
Note: It sounds like I’m ORM bashing here, but I typically like to stay away from stored procs unless I’m doing something that requires SQL (like a complicated search query). I really don’t like any business logic in stored procs because now my application is very tightly coupled with the database. It’s much easier to manage and test business logic in the application code. If you don’t like the heavy handed ORMs like NHibernate and Entity Framework, try “micro-ORMs” like Simple.Data.
A Better Way
How you do your data access actually isn’t the issue here. What I really want to talk about is how to structure your application code to emphasize the behaviors that your applications are doing, which usually involves some data access. Everything needs to driven by some business process that needs to be done. For me, this usually starts with an acceptance test, which may or may not be automated (in my code, it’s usually automated).
Scenario: User deposits money in an account
Given a bank account
When the user makes a deposit
Then the balance should increase by the amount of the deposit
Then I have some class that is going to do this specific task.
public class DepositCommand
{
public IRepository AccountRepository { get; set; }
public void Execute(IDepositModel model)
{
model.Account.Deposit(model.DepositAmount);
AccountRepository.Save(model.Account);
}
}
On my current project, we like having lots of little command classes like this. Each class has a very specific purpose that can be linked back to a business requirement (because we write our requirements using the same command names as the code). We sometimes string a bunch of these commands into a “workflow”, which is nothing more than a series of commands run to complete a larger task.
Back in the day, I would just have big classes like “AccountManager” that would have a bunch of methods on it. When I was on a Ruby on Rails project, we didn’t have to use dependency injection (because Ruby is awesome like that), so our business model objects contained lots of methods that would do things, but these model objects could get really really big. In either situation, I prefer creating smaller command or query classes that either modify something or do some query.
All I’m really doing is rearranging around my code, so what’s the big deal? It’s much cleaner with command classes in my opinion because that class has one specific task. Those command classes often have private methods that help do the work. If I had a huge AccountManager class or a big model object in Rails, it’s not always clear which private methods go with which public methods, or what might be affected if I change them. In a small command class, if I change something in a private method, I know that it can’t affect anything outside of that class. Not only that, everything in my code and my tests is pointing back to some business requirement that is telling me to do something.
What I’ve realized is that the when I place more emphasize on the behaviors that I’m trying to implement in my code, the more I change my code to reflect those behaviors, even down to how I structure my code. By structuring my code in this way, I’m constantly reminded of the behaviors that I’m trying to implement and the reasons why I’m writing the application in the first place.