Hacker News new | ask | show | jobs
by mikekchar 2616 days ago
I like TBD -- a lot. However there are a couple of problems with it. If your team is not collocated in a time zone then you'll one one guy (me, for instance) who will push 8 hours of development into trunk without anyone else getting a chance to look at it.

The same thing happens if you have someone who just "disappears" for a day or two and effectively has a feature branch. You need to have discipline on your team to push often (I like to push at least every 20 minutes).

I also tend to think that continuous deployment with TBD is risky. It depends on how good your automated acceptance tests are, but I tend to like to do a manual sanity check before deployment. It's a lot easier when you are not working on a moving target.

Finally, sometimes you just have to break something in order to change its direction. This forces you into a feature branch if you are doing continuous deployment.

We've occasionally experimented with having an "integration branch" that acts like trunk but isn't deployed. You can then time your trunk deployments, potentially cherry picking from the integration branch. It seems like a good solution, but I've found it to be more trouble than its worth most of the time.

Having said all that, my preference would be to abandon continuous deployment and instead have regular deployment (say once a week or once every 2 weeks) with a mechanism for hot patches. Then force everyone to work mostly core hours and have continuous integration (with commits coming in every 5 minutes or so). In my experience this has produced dramatically better results than feature branches.

However... On my team it is impossible (not least because I'm 9 time zones away from the majority of my team mates). So feature branches are an acceptable second best.

1 comments

> (I like to push at least every 20 minutes)

That sounds extreme to me. What kind of development do you do that makes this possible? I rarely finish something within 20 minutes. Often, I'm thinking about the right way to do something for a day or longer before I decide to push some results. (UPDATE, before I even start to write some code!)

Intermediate results are fine as long as the tests are passing. If you push, then your teammates will see what you are doing and one of them can give you advice if they think you are going in a disadvantageous direction.

If you hold the code out for a whole day, there is no way for anyone else to know what you are doing (unless you interrupt them to tell them, or they somehow know to ask you). On a well functioning TBD team with true CI, everybody knows what everybody else is doing because they are constantly looking at diffs when they pull trunk.

But yes, it is extreme ;-) It's one of the 12 XP practices (continuous integration). Interestingly, the original idea behind CI servers was that when you push to trunk, you were never sure if there would be an integration problem. So if someone pulled trunk, they might get garbage. So the CI server was there so that you could get a visual indication of whether or not it was safe to pull trunk. And if it went red the whole team would instantly take a look to see what happened. It's a team based approach rather than an individual approach.

I'd even go as far as to say that any code that was written in the span of 20 minutes can't possibly be good code, and doesn't deserve to be in master. The code quality and commit history must be pretty terrible in a project like this.
If you want to see some typical code from me, here are the commits from an experimental side project: https://gitlab.com/mikekchar/testy/commits/master

Some caveats: I was experimenting with a different way of doing OOP in JS. Here is a description of the design: https://gitlab.com/mikekchar/testy/blob/master/design.md There is also a coding standard that I was following: https://gitlab.com/mikekchar/testy/blob/master/coding_standa... It's not one that I advocate, it was one that I was experimenting with.

Some of the code in there is not great. Some of it is OK. It's not a big project, but it will give you an idea of the scope I use when I make commits. I use a very conservative approach when programming -- I don't pull everything apart and then try to build it back up. Instead I refactor everything and make incremental improvements. Every commit should improve either the quality of the code or add functionality. Especially in this project, I was building a test framework, so I didn't have a test framework to work with. This meant I had to use an even more conservative approach than normal. However, like I said it should give you a good idea.

Perhaps you think this is bad code. I don't think it is. It's got a strange style (because that was the point of the exercise), but generally it was quite nice to work with. There are 2 pretty nasty hacks that I made in order to get the framework bootstrapped. I would have improved them eventually, but I ended up ending the project early. If I were to really criticise my work here, I would say that my commit messages are pretty awful. Interestingly, the TODO items that I check off in the actual commit are quite good IMHO. Probably I should cut and paste them, but... it's a personal project in my spare time... I was being lazy :-P

I guess I'm responding to your comment mainly to hopefully open your mind to different ways of doing things. Maybe you'll be able to see it, maybe you won't. One of the things I've found in this job is that there are a lot of people who are stuck in "It's either my way or it's crap". Your comment seems to indicate that you might be one of those people. But in the case you are not, I hope you'll find the code interesting.

I've worked on small projects and I've worked on big projects (I once "owned" a million lines of code!). The style I use now evolved based on my experiences. My basic approach is to look at a piece of code and try to find a general strategy for what I want to do. If I don't know the code, that can take a long time, but once I've figured out what I'm doing, things can go pretty rapidly.

I make a TODO list of what I'm planning to do. Then I look at the code for a minute or two and ask myself, "Can I get there from here?" If the answer is "No", then I ask myself, "What would I ideally want?" Then I write that down in my TODO. Usually it's a fair number of things.

Normally those facilities require pure refactoring (i.e. changing the code in a way that doesn't change behaviour). I try to break up my challenge in such a way that I make an improvement to the code, and that keeps the behaviour intact. Sometimes before I start I need to write tests to document the current behaviour.

So a typical session would be: Write test(s) that are lacking. Check in code. Refactor code to provide facility(s) that I'm going to want. Check in code. Make a behavioral change with tests. Check in code. Then go back to my TODO list to get the next step.

I will leave "bad" code in the build -- sometimes for a very long time, if I don't have a good idea for how it "should" look. Even if there is a "good" way to represent it, I'll often put it off if I don't know that this "good" way is going to fit with the direction the code is going. Overworking a piece of code often leads to unintentional inflexibility and sometimes good looking code adds constraints that you don't need. However, because the code looks good, nobody will refactor it and remove the constraints, leading to overly complex code.

If you've gotten this far, you can see some of the challenges for TBD with this method, though. Every change has to keep the system completely functional! This means very deliberate and very careful modifications. It's difficult, but there is plenty of upside. IMHO there is more upside than downside by quite a margin. YMMV (and I won't tell you that you must be a crap programmer simply because you do things differently than me ;-) ).

Edit: I went through some of your commits on https://github.com/tshatrov/ichiran It's interesting to me that the commit size is not really that different than mine. There are a couple of places I would have split it up into 2 or 3 chunks, but we're not talking about order of magnitude stuff here. I'm curious how long you spend on a commit. Nice project, BTW. I'm not a stranger to building that kind of tool ;-) I actually built an English parser in FORTH once. I also built: https://github.com/mikekchar/JLDrill (which actually is awful code... and it doesn't actually run any more thanks to bitrot).

Well, I won't judge personal open-source projects (where there's usually only one contributor) on the same level as large collaborative projects where code quality and commit history actually matters. Ichiran is not a typical project because most of commits (especially recently) are "data" commits and not "logic" commits. I do run tests before every commit, but if there's no programming logic changes I can bump it into prod right away. Commits that actually change the logic of the program are tested and dog-fooded locally for days before I even upload them to github. I also use feature branches for "big" features so that I can fix bugs in master if I happen to discover them, while continuing to develop a feature in parallel. Because I don't have much free time to develop my personal projects, a big feature might take weeks or months to get merged in, but I'm not in a hurry!