Warning: this post contains a lot of specialist language and abbreviations. Familiarity with programming or project design is recommended.
I do everything from scratch. This is not wise, and unless you want to get a thorough understanding of everything that annoys you about your programming language of choice, I do not recommend it.
Why? I like building stuff. I like finding out how stuff works. While I often lose interest with the nitty-gritty parts of, say, the JVM (Java Virtual Machine), I take an almost perverse pleasure in exposing why a particular part of Java's Swing library is behaving like a spoilt child. Below is a case in point:
Found the issue with #java - using HTML in JLabels causes a distinct performance hit. It's fine in JMenuBar though. Fugging weird. #gamedev
— Sean H (@Gorbles) June 20, 2014
This was for something simple; organising a game's scoreboard into something that was more visually appealing than a simple text string. Got it working in the end, the result I'm quite happy with:
Score List for WarGames Offline
But it took me something close to half a day to track down (I do this in my spare time; my real job is web development). A lot of people (probably rightly, hah) would blame me for using Java. But to be fair, a lot of language have issues like this. Every language has a list of long-standing issues that haven't yet been fixed (this issue has been documented, as early as 2005, but still not fixed). Maybe Java has more than most, who knows. It's the language I work with at work, it was the one I was taught at university, and I'm too invested in my projects (in Java) to have the time to move even to something as similar as C# (even if Visual Studio is a beautiful, appealing piece of software).
Back to building game tech, which I'm loosely-defining as "anything you can regularly use to help build a game project". Finding these little idiosyncrasies in whatever programming language you use is critically important. I adhere to the adage of "get it working, then get it working nicely", but you do need to ensure that the basic stuff does, in fact, work, and won't fall over when you forget the code it contains and use it for something avant garde later on in your project. I have an IOCore class that I've used in pretty much every single project so far, and all it does it wrap file read/write operations in a single class for ease of use. I first made it four years ago now and it's still managed to go through numerous revisions, optimisations and feature creep (like adding support for read/write byte arrays for hex-editing file headers).
Always document your classes. Every time, all the time.
You have to be sure it works. Otherwise you get fun stuff like your program creating a folder structure four levels deep in My Documents because you accidentally forced it to always create the folder structure if it didn't exist, instead of simply not creating the file in the first place.
- Don't build things from scratch. Unless you really want to, or you're really bored.
- Libraries are not bad things. They're usually made by very good people and do really handy things. Like Google's GSON project - invaluable and let me tell you writing an XML or JSON parser by hand is an awful lot of work. I'd know, I made an XML parser myself. Then I trashed it and rewrote the project to use JSON with GSON.
- Thoroughly test the classes you're relying on.
A lot of this may seem like common sense (and is), but this is a cautionary tale. I've learned a lot from my mistakes, and I'm competent enough with Java that sometimes writing stuff from scratch is actually easier than sourcing an obscure library. I'm currently looking at hit detection, and the only source for convex hull generation I've found is written in C++. The guy didn't give his variable pretty names either (a common trait, I find, with C++ programmers!).
You'll know once you've made a useful class, or a useful piece of tech. Because you'll find yourself using it everywhere. I've got a simple ComboBoxRenderer that I use because the default renderer is ugly as sin. I've got a custom WindowSnapper class for JFrames that closely emulates the native Windows behaviour for it's components. Not sure how it plays out on Mac and Linux, mind. These things are games tech, and will feature in all three (or four) of the projects I'm working on. They're useful. Share them, plug them in blog posts (am I right?), because other people will find them useful as well!
At least, I hope they do. Next time, a showcase on one of my games projects.
I have to disagree with the "Always document your classes. Every time, all the time." recommendation you got there in the image caption. Your package structure and code should explain itself so that you don't need documentation. In a project that spans more than one Java class it becomes a pain of its own to maintain documentation like shown in your screenshot. Those "@author", "@modified" and "@version" data, for one, are complete waste: you can get all that information from your version control system. "@category Backend" should be obvious with the package structure, your class could be in a package named, say, "com.blogspot.gorbles.backend".
ReplyDeleteI find that you should only document solutions that aren't obvious for the reader for whatever reason, like some odd issue of backward compatibility or something. Otherwise you should just use descriptive variable and method names and keep your methods short. At ten lines or so it often becomes difficult to read, and if a method doesn't fit into your screen at once, it's just terrible and should be broken up. When methods are short and consist of calls to other aptly named methods, they are easy to comprehend even if you don't get all the details immediately. No documentation needed there.
I also found it odd that you didn't mention unit tests at all. You did say to thoroughly test your classes, but that doesn't specify any method. Unit tests are another great way to document your code. Say you've got a method that does something with an argument and then returns something. (Wow, that's something, isn't it?) Write a unit test like "@Test public void myMethod_should_return_null_when_given_empty_array() { assertNull(Foo.myMethod(new ArrayList())); }" and there's your documentation! No need to create a javadoc that says "/* @param foobar Some list @return Returns a null when given an empty array */". Now when you want to update it to return something else, you also automatically must update your documentation (i.e. the unit test) or your build won't pass. I've seen too many cases of outdated javadocs over methods describing some parameters and return values that have no connection whatsoever with the method's current signature.
Also, I should add that while I may be against adding Javadocs to your code, I am, on the other hand, a big fan of sequence diagrams for describing interactions between different components or systems. Those are invaluable, I like making them with https://www.WebSequenceDiagrams.com/ (OK, now this looks like a spam post... Well, it isn't.) Other graphs like state machine descriptions are great for understanding complex systems too, but generally I find there's not much need for text-based documentation when you've got an access to the source code.
ReplyDelete