In skiing, there’s a concept called the “fall line.” The fall line just means down. But it doesn’t mean “towards the bottom of the hill,” it just means what is immediately down from the exact location you’re at - if you dropped a ball, or poured some water, which way would it go?
This is important in skiing, because you have to stand perpendicular to the fall line if you don’t want to keep moving.
There’s also a fall line in development. The fall line in development is simply what is the easiest thing to do at the time to solve the immediate problem. This can also vary by individual knowledge level.
In C, if you want to add some function, the fall line is just to declare it before you need it, and go on your merry way. If you need it multiple places in the same file, put a declaration at the top of the file. Only if you actually need it in another file is there any reason to expose it via header.
C++ is kind of opposite in this aspect - if you want something to be a class member, it has to be included in the header. So a lot of little internal methods that, in C, may have been completely hidden from the world become exposed, at least to the extent that they’re in your header. Yes, you can do things like separate implementation classes, but that’s, again, adding more work.
Because of this, I firmly believe that in any kind of API development, you want the easy thing to be the safe thing to do. If something takes more effort to do, people will avoid it unless they absolutely need to do it.
Sometimes, the easy thing to do in a language, or application, isn’t the right thing to do. Sometimes it’s the wrong thing to do. And the typical answer to that is to add process, and force people to do the right thing.
I’m going to suggest that all process can do is add inefficiency, and by doing so, change the fall line of development.
That’s not necessarily a bad thing - if the fall line leads you to write bad code, then adding inefficiencies to gain later benefits can be very useful!
But, there’s two things to keep in mind:
First, if people don’t understand the purpose of the process, they’ll just follow the steps of the process while continuing, essentially, the same underlying behaviors. Imposing a process alone will generally not change the mindset of anybody. If you’re really looking to get a change in behavior, you’ll have to do that through education.
Secondly, the reason that process works is because it adds inefficiencies, and people will avoid inefficiencies. The more heavyweight a process is, the less it will be used. If your checkin process takes a day to navigate, then people will avoid checkins, and do them in large batches. And that might partially defeat the purpose of your checkin process in the first place.
You should always use the minimum process that you can, and use process deliberately to add inefficiencies. The goal of a process should never be to get people to do what they should do, but rather to get people to not do things that they shouldn’t.
I’m a big TDD proponent. I would never suggest that somebody institute a TDD process that was mandatory. If you don’t “get” TDD, then all you’ll do is write bad tests, and make the unit test suite less usable to me, without even getting any of the benefits.
Instead, I’d make a process (probably as part of the build) that ran the appropriate suites, and make some kind of check to make sure they were either run prior to checkin, or immediately afterwards.
Yes, I want people to write tests. But the best way to get them to do that is by example, and showing them how useful the tests can be. What I don’t want is for people to break the tests, rendering them useless. And, I don’t want poorly written tests that are likely to fail due to configuration issues, or take forever to run.
If I make users manually run tests, it’s another process that they have to do - they’ll put it off as long as they can. And if there’s a break, they’ll probably have worked well past the original error, and have to rework a lot of code in order to get everything to work again. They’ll end up hating the unit tests, and the quality of the suite will degrade.
If the tests are in another directory, developers will have to sync two directories, and switch directories to build/run tests. Again, this will make them run them less often.
By making the tests run as part of the build process, I make it hard to break the tests. If the tests break, you don’t get a successful build. Now, you have to circumvent the build to get anything done. If it’s your change that broke the tests, it’s probably easier to just fix your code, since you’ll have to do it anyway.
And, if the tests are part of the build, slow or failure prone tests will become painful for everyone - as long as it’s easier to move the tests to the appropriate suite than it is to circumvent the build, they’ll do that.
Post a Comment
You must be logged in to post a comment.