Hacker News new | comments | ask | show | jobs | submit login

An excellent talk, but the thing that I disagree with is his defense of having functions with thousands of lines of code in them.

It's true that breaking up a function into smaller ones just for the sake of it doesn't make sense, but if you have a function that needs to be over 1000 lines in the first place, it makes me think that the code wont be very reusable in future projects.




It's not going to be reusable anyway. It's application code, by the time it's actually polished, featureful and useful to the end-user it's so tightly integrated and full of special cases that you have to consider it a one-off.

Again, as Blow mentions several times, this is a domain-dependent thing. If you are shipping line-of-business code that sits around for 30 years, yes, that kind of polish becomes important. But games don't (typically) have that lifespan. If you want to do an update 10 years later you can remake it with all new assets as well as new tech, and the exceptions to this tend to be on a completely different scale from indie games(MMOs...) So when "in the moment" of bringing the game together you optimize for broad, fast changes, which favors having a bit of lengthiness and redundancy within the source.

Here's an example from a game I'm working on now:

I have some UI code that makes rounded-rectangle frames. I thought, when I first made it, that I might want to customize the look a bit(roundedness, thickness, coloring, etc.) so I parameterized it. As it turns out, I used the same parameters everywhere. So the abstraction wasn't useful. But at the same time, I don't really have a great need to refactor it, because the problem it causes(dirty looking code) is so localized to the instances where I create the frames. It's still there and the customization is possible. If I need something different from a rounded-rect frame I'd be writing completely different code, so it just doesn't make a huge difference.

On the other hand, one thing that I got wrong and want to fix is an architecture problem. I went in with an architecture tuned around a single, serializable scene capable of defining complex entities. But I made a game with a lot of UI/editing screens and one gameplay screen with very simple game elements. So ideally I would have had something with a DSL for defining those rounded-rects and tweens and positioning efficiently, better ways to manage all the scene transitions, a system to iterate on UI quickly(e.g. load a file = restart scene), and a simpler model for the gameplay. As it is, it gets a bit hacky in a few places, and the overall "shape" of the code is likely to be discarded, but I will be able to reuse lots of the pieces if I do a sequel or similar type of game; they'll just be assembled in a different way.


I've had similar experiences with games.

Yes, it's important to make the code clear. Shipping is so much more important than code reusability though. When the lifetime is small, rewriting it to be more modular isn't quite as justifiable as in a long-term project where you actually have the time to get it right.


Pointless internet argument. :) If you have a function that's over 1000 lines, a lot of it is probably cruft or very app-specific which you might be able to reuse part of in other parts of the same project, but code-reuse across projects doing different things is something fairly rare. His reasoning is pretty sound on this, it didn't take long for me to find a 200-line function (to be fair it contains an inner class...) in a million-line+ OSS project I contribute to, but it's Java and doing something very specific that isn't going to be used outside of the project (since it makes use of lots of function calls to other parts of the project) and wouldn't really be used outside of that package in the project. There are places where you could save 5 lines over 3 or so places, but adding a utility function and documenting it usually negates any line-length benefits and doesn't do much for understanding. It can also make things harder for newcomers to figure out what the code is -really- doing, as he mentions.

Of course, 200 lines is one thing, 1000 lines is really long... Especially if it's in the context of a 1000+ line-long class or module. In general I agree with you that modularity is good, I really favor a functional style at heart. :) I think it really depends on the context of use, for function-length. Some people can't stand functions bigger than an 80x24 terminal screen which I think is nuts.

What I disagree with is his defense of not using (correct) data structures. Though if you have to roll your own data structures or they're hard to work with because your language and/or set of libraries suck, that's a problem, especially if you agree with his "optimizing your life" bit. And sometimes what seems like a good data structure actually isn't, which is why people do some analysis before writing code.


Re: the data structure defense. In the context of games, when you first write code you're in a chicken-and-egg situation, where you need finished content to demonstrate both correct behavior and desired performance in your code. So you use the simple structure, which you can rely on, and perhaps put a wrapper around it with methods describing specific functionality, if you have an expectation that you'll come back and rework it eventually. Having done that, you can move on to building/integrating the content and seeing if it meets design goals, and once a performance problem arises, you have a great test case with the correct behavior to work from.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: