In Search of Source Control’s Holy Grail (part 2)

Hello opinionated lazyweb denizens!  Let’s see if you can help resolve today’s office quandry (or at the very lest, tell us that we suck and we’re doing it all wrong).

Friendly hint: if you know nothing about software and source code control, you might want to go and do something more fun than reading this post. Do you have Pop-Tarts? Go eat some Pop-Tarts.

Okay, this is a little simplified for ease of understanding, but here goes. For one particular family of products, we have a Subversion repository. It contains two products, and a bunch of components that each product depends on. The basic structure looks a bit like this:

repository/
  components/
    component1/
      trunk/
      tags/
    component2/
    component3/
    component4/
    shared_libraries/
  products/
    product1/
      trunk/
      tags/
    product2/

   
Our main requirements are:

  1. During development, we can open multiple products and components together, and edit them together in the IDE.
  2. The a tagged build of a product may only use tagged (not trunk) versions of components.

 

Each component has a trunk and various tags. The trunk has a build script that dumps its output binary (a JAR, in this case) into shared_libraries. These binaries are numbered according to their next version number, so that in the build-up to component1 version 1.1, its build script creates components/shared_libraries/component1-1.1.jar.

Once a component reaches a certain version number, it gets tagged, and its build script in trunk gets updated to output a file with the next version number, e.g. component1-1.2.jar.

Each product builds against properly versioned libraries inside shared_libraries.

This way, during development, we can open the trunk of whatever we like in the IDE, and provided our product build script builds all its components first, it’s always building against the latest versions.

At product release time, we make sure all the components are tagged first, meaning that the versions of the components in shared_libraries that the product has been using will never be modified again. We can then tag the product, safe in the knowledge that if someone checks out that tag in future, it will be set up to build against known versions of the components on which it depends.

My question to the lazyweb is, “is this in any way sane?”

There’s one down-side I can see, which is that in order to build a product, a new user needs to ensure that they have productX and shared_libraries checked out with the same relative path that they have in the repository. They presumably won’t want to check out the whole repository, as that would include every tag of every component, so they’d have to recreate the top levels of the structure manually.

This could be solved by using Subversion’s extern property to embed shared_libraries within the product, thus:

repository/
  components/
    shared_libraries/
  products/
    product1/
      lib/
        shared_libraries (extern)

However, if the product builds against JARs in the externed directory, that breaks the ability to build everything at once during development — turning it from:

  1. Build your components
  2. Build your product against the built components

into:

  1. Build your components
  2. Commit components/shared_libraries
  3. Update product1/lib
  4. Build your product against the built components

Introducing a mandatory SVN commit into every build has got to be a bad idea.

We also can’t make components build straight into a product’s lib/ directory, as we want to keep the components strictly product-independent.

Is there some industry standard or just particularly good solution to this problem that everyone else is using and we just don’t know about? Or have we, in the last couple of hours, produced as good a solution as we’re going to get?

Madness and the TableModel

What follows is a lengthy rant about a particularly annoying situation in some of my code. Programmers, please let me know – is it the toolkit that is mad, or is it me? Everyone else, feel free to skip it! :)

For one of my current Java projects, I am using a toolkit that comes with its own complete set of GUI widgets based on Swing. Swing… and horror.

I was under the impression that managing a table in any sane OO language goes a bit like this:

  1. Create a class that roughly represents, or at least holds the data for, a row of the table.
  2. Create a “Table Model” or some other kind of backing array to hold objects of that class.
  3. Create a Table widget that uses the table model as its data source.
  4. Happily filter and sort away, knowing that the model and the view are completely separate entities.

And if you should want to serialise the data behind the table to disk, and load it again, you can just save and reload the model, then call some update method on the table itself to let it know that the model has changed.

Bring on the horror!

What this toolkit does, allegedly in the name of MVC, is this:

  1. Create a class that roughly represents, or at least holds the data for, a row of the table.
  2. Create a “Table Model”, but completely ignore it.
  3. Name the columns of the table after the internal member variables of the class you have created.
  4. Add each object to the table in turn, watching in agony as it extracts the values of those member variables, and puts them into the table as Strings, discarding the original object in the process.

But wait, what if those member variables are (sensibly) private? Oh, no worries. It uses reflection, each and every time you add an object to the table, to figure out what the getter method for that variable is called.

And then we come to wanting to serialise the data to disk. Well, that could be a problem – the table doesn’t contain the objects we want, only Strings. Oh, no worries. You can give the table a new instance of your object, have it figure out (again, at runtime) which the appropriate setter methods are, and run those to make your object again!

Oh, hey, I hope that object didn’t contain any variables that weren’t in the table. ‘Cos if so, you’re not getting them back.

Luckily in my case, everything I care about is shown in the table, which only leaves the attempt to serialise it.

Now I want to have a single class that nicely encapsulates this serialising business for all tables, regardless of what the objects expressed in that table are. Normally, one could just serialise the TableModel and be done with it, but now we need to dynamically re-make the objects based on what’s in the table.

For a fully encapsulated solution, I really want to be able to just pass in the table and have the serialiser take care of the difficult stuff. i.e. I want to call:

if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
    SerialisedTableFile f = new SerialisedTableFile(fc.getSelectedFile());
    f.save(table);
}

But I can’t, because f.save() now has no idea what kind of object it is supposed to be building. So we need to pass f.save() a template object of the class that it is supposed to be building, the only requirement of which is that it can be cloned to produce the real object that we want to store data from the table in. So we implement the Cloneable interface — except that Cloneable doesn’t actually include clone() for some no-doubt genius reason. (Not sarcasm, I really do suspect that language designers are an order of magnitude more intelligent than I.)

The end result of all this is that I now have an interface that delights in the name ReallyCloneable, which all classes that I wrangle into tables have to implement. And poor old f.save() looks like this:

public boolean save(Table table, ReallyCloneable itemTemplate) {
    boolean success = false;
    try {
        if (file.exists()) {
            file.delete();
        }
        if (file.createNewFile()) {
            ArrayList<Object> items = new ArrayList<Object>();
            for (int i = 0; i < table.getRowCount(); i++) {
                try {
                    Object o = itemTemplate.clone();
                    table.getItemFromRow(o, i);
                    items.add(o);
                } catch (NoSuchMethodException ex) {
                    Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
            out.writeObject(items);
            out.close();
            success = true;
        }
    } catch (Exception ex) {
        Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        return success;
    }
}

I think it’s about time I started buying Bad Code Offsets by Direct Debit.

The Flow

So I spent my day caffeinated up to the eyeballs, loud music playing, churning out documentation until I started spamming Twitter with all-caps weirdness and I started wanting the phrase “COFFEE FOR THE COFFEE GOD! MUGS FOR THE MUG THRONE!” emblazoned on my coffee mug and, frankly, my soul. (Thanks @Bobolequiff.)

@HolyHaddock later tweeted about his much more restful afternoon, but while I can appreciate it being nice, it just seems so much less… epic.

There’s no sensation, for me, like finally achieving the hyperactive nirvana of flow.

It takes caffeine, of course — four cups of strong coffee over the course of the day, each one timed to mitigate the crash from the last. It takes music — the kind of music that doesn’t give a damn about genre or technique, but is brutally designed to hot-weld your eardrums to your adrenal gland with lightning at 150 beats per minute. It takes focus — a single task to be done, no distractions except for the continual background process of the internet’s pulse.

It just accelerates, never stopping. Athletes talk about “hitting the wall”, you reach a point where it hurts so much you just can’t find a way to carry on, until at last you crack it. But there’s none of that, because it’s all in your mind and your mind is hot-wired. It’s a single white-hot moment that lasts for hours but feels like microseconds, where ideas escape your brain at a billion degrees Kelvin and etch themselves into reality.

Sure, I’ll probably explode in a shower of caffeine and adrenaline when I’m about 30. But for now, screw restful afternoons. Eyes wide open, brain set to overdrive. It’s like feeling alive, only more so.

Autonomous Quadrocopter: What and Why?

It’s now been two years since I last did any work involving autonomous vehicles, and I’m kind of disappointed by the lack of that kind of work. Writing software for big data acquisition systems is all well and good, but it lacks a certain something — I just don’t get attached to them in the way that I do to vehicles such as this one.

One could probably argue that developing an odd fondness for robot boats is a bad thing, but unfortunately that appears to be the way my brain is wired. So, onwards!

Since no autonomous vehicle work seems likely to come my way professionally at the moment, the urge is rising to build one in my spare time. This presents a problem, in the form of a lack of time and money.

I’m unlikely to stumble upon a free RIB, jetski or minisub that I could hack about with, and have nowhere to store one anyway, so those are probably out. Cars would be the next obvious choice, but if we had a car to start with, the family may object to me covering it in sensors and filling the boot with computer equipment.

I think we need to think smaller, and my co-conspirator @aefaradien suggested a quadrocopter.

Our first challenge is to specify the parts we want to use, which is the first point at which my expertise starts to become less useful. The natural approach for me at this point is to spend about £20,000 on a cRIO and a bunch of PC104 boards and wire them all up in a big case — not only don’t we have anything like that amount of money, weight is now also an issue.

For the CPU of the device, we considered a cheap Android phone, as this would give us GPS, a gyroscope, WiFi and a camera without spending too much money. However, we would still need to use a separate motor driver board for the propellers, and getting a phone to talk to it could be tricky. @aefaradien raised the issue of reliability, too — a crashed phone means a crashed vehicle. Even with a watchdog timer to reset the phone (potentially yet another board), Android’s boot time is going to leave our precious ‘copter in a ditch somewhere.

An Arduino is looking like a much more appropriate solution, especially as they come with digital and analogue I/O baked in, and readily available “shields” that could drive the motors. However, that leaves us sourcing our own gyroscope, GPS and camera, as well as figuring out how to remotely control the vehicle.

Our notes are available at sparktank.net, and more bloggery will occur as the project progresses.

Announcing: Daily Promise!

After a couple of weeks of development — documented here, here and here — I think I’m ready to call Daily Promise version 1.0.

It’s a site that helps you keep track of your promises day-to-day, giving you a pretty display of which promises you’ve kept when, and letting you compete against your Twitter-using friends to be the best at keeping your daily promises!

For now, you can find Daily Promise at http://dp.onlydreaming.net.

I’ll make the same deal as I made with Dynamic Democracy, but doubling the number so that I can be more sure of it taking off, and that’s the following:

At the moment the site does everything I want it to do, and it’s hosted on a subdomain of my main website, which I have no problem with. What I would like to do is give it its own domain, and start implementing feature requests that people send in. So that I don’t end up spending money on something that’s going to die off quickly, the deal is this: When it gets 20 active users, it gets a domain and some TLC. If it doesn’t make it to that point, it stays like it is.

So if you’d like to help me make something of this site, please start using it, and show it to any of your Twitter-using friends who might need a little help getting healthy, keeping fit or any other goal that Daily Promise can help them with!

Daily Promise: Avatars Everywhere!

After a couple of days and one frantic family-free morning, Daily Promise is getting near completion. Here’s what’s new since last time.

(This is post number 3 in my series on the development of Daily Promise. The others are here: Design Sketches, Coming Together.)

Friends Page

Daily Promise: FriendsHere’s the Friends page – again, almost no deviation from the original design sketch. The friends page pulls in the list of people that you follow on Twitter, matches it up against Daily Promise’s user list, and if any match, they’re your Daily Promise friends! They’re simply displayed in alphabetical order, along with a summary of their performance. Invisible users (see later) don’t appear, even to their friends.

Nicer User Pages

Daily Promise: User PageClicking on one of your friends takes you through to their ‘view’ page (minus any editing functionality). It also shows you their Twitter bio, and how long they’ve been using Daily Promise.

Top Users Widget

Daily Promise: Top Users WidgetThere’s now a “top users this week” widget on the home page, showing the performance of the top 5 users. This resets at midnight on Monday morning.

Spam your Friends!

Daily Promise: Tweet BoxTwitter integration now includes boxes suggesting Tweets you might like to make after each significant activity. Just as promised in the “How does it work” graphic, Daily Promise never posts to your Twitter account without you deliberately clicking a “Tweet” button each and every time. Do no evil™!

Behind the Scenes

A lot of other stuff has changed in the last few days that isn’t immediately obvious to users:

  • Authentication fixed — users using the alternative login weren’t able to do Twitter things. That’s sorted.
  • Account visibility — your account can now be set to invisible, meaning it won’t appear anywhere — top users, friends lists, etc. New accounts are given a prompt to set their visibility before starting to add promises.
  • Account deletion simplified — you now only have one, nuclear, option for account deletion. It erases all traces of you having used the site. Do no evil™! :)
  • Removed promises no longer shown in the history table — ‘cos no-one likes to be reminded.
  • Fill in data for yesterday — when creating a promise, users can opt to enter data for yesterday, giving them something to fill in straight away.
  • History table scrolls — narrow displays can’t fit the whole history table in, so now it scrolls (in reasonably modern browsers).
  • Time zones implemented — we pull the timezone you have set in Twitter, so Daily Promise will roll over to a new day at your local midnight.
  • Crontastic! — we now update stats and things from an hourly timed cron, to avoid extra loading on user-requested pages.

Next Steps

This all brings me to the slightly worrying conclusion that Daily Promise is damn near finished. So, where do we go from here? I’ll have a few more days of bug-fixing and implementing features that people request, and then it’s difficult decision time:

This has been a fun project for the last week or so — does it deserve a domain and advertising, or shall I let it quietly die?

Daily Promise: Coming Together

Despite the lack of response to my earlier post, in which I floated my design concepts for “Daily Promise”, boredom won out in the end and I started coding anyway.

It’s now coming together, and all bar the Twitter-integrated social aspects are largely complete. Here’s how it’s developed:

Home Page

Daily Promise: HomeThe social side — top users, etc. — still isn’t implemented, but there’s a reasonable-looking homepage in there. The main body is taken up with a short description and a big graphic explaining how the site works. Side-bar widgets provide the Twitter login and alternative login (bypassing twitter.com). The site now has a proper name, Daily Promise, and with it a logo and style that is reflected throughout.

Set Up Goals (“Manage”)

Daily Promise: ManageThe “Manage” page has remained almost exactly faithful to the design. New promises can be created, old ones deactivated and deactivated ones can be activated again. A Tweet box appears for the user to announce their new promise, if desired.

Daily Performance (“Enter”)

Daily Promise: EnterAgain, there’s not a lot of difference here between the design and the reality. Each promise has a yes/no choice, and after completing a day’s entries, Tweet boxes appear for the user to let their friends know about their successes and failures. “Winning streaks” aren’t yet implemented.

Performance Log (“View”)

Daily Promise: ViewThere’s no ability to scroll through your history yet, but the default display shows 4 weeks (which scroll if necessary). Just as in the design drawings, the history table is followed by a text summary of how the user is doing.

The “View” page also, with a few additions, becomes a user’s profile page, which is accessible to other users.

Configuration

Here you can set your password for the alternative login, and delete your account. It’s exactly as dull as it sounds.

Friends

That’s my big job for the next few days! It doesn’t exist yet, but it’s now my top priority.

Daily Promise: Design Sketches

Current flavour of the month of some of the geek crowd, “Health Month”, is a social network of sorts on which users compete to achieve certain health-related goals. Each month, each member sets a number of goals for themselves to achieve. Its core mechanic is health points — you start with 10, lose one every time you fail to meet a goal, and players who perform well can heal you.

I’m enjoying my use of the site with three goals this month, but I’d like to step it up and set lots. Unfortunately, having more than three goals costs money. (Not that I think the site’s owners don’t have a right to charge, but it can be a deterrent to users such as myself.) It also currently only allows two “custom” rules per month — beyond that, you have to stick with the pre-defined ones.

Another social health site is Tweet What You Eat, on which users tweet their food intake and have the site, or the community, calculate statistics such as their calorie intake.

Over my lunch hour, I’ve come up with some sketches for a site that sits somewhere between the two. It takes Health Month‘s goals mechanic, opens it up and removes some of the social aspects that in my opinion Health Month doesn’t implement all that well. It also drifts closer to Tweet What You Eat, in that rather than being its own service it piggybacks of Twitter for its social side.

At the moment this is just a fun concept I’m toying with — I don’t really have the time to make it at the moment, I doubt the space between Health Month and Tweet What You Eat is wide enough to make a new site popular, and I feel a little guilty about thanking Health Month for the enjoyment I’ve had by becoming its competitor.

In the notes below it’s dubbed healthi.ly, though as that domain is parked, it’s come to be known as “Daily Promise” instead.

Home Page

Daily Promise Home PageThe home page would largely be a “log in / register” affair, possibly also showcasing successful and popular users in a side-bar (not shown). Big banner text explains the rough concept, with a “read more” link to a full “About” page. On the registration side, we make it clear exactly what Daily Promise does and doesn’t do with access to your Twitter account.

Set Up Goals

Daily Promise Goals PageThe main setup page is where you set your goals. Users can set any (reasonable) number of goals, they can drop and resurrect old ones, and add new ones, at any time. Performance against all the goals is tracked and visible on this page. Adding new goals and dropping old ones can be tweeted, but as with every tweet opportunity, the user is presented with an @Anywhere box that they can freely edit and can choose not to tweet as easily as they can choose to tweet. The tweet links to the list of goals on their profile.

Daily Performance

Daily Promise Daily Performance PageOnce goals are set, the user logs in each day (and can fill in past gaps) with whether or not they have met each goal. Each day’s entry presents some brief statistics, and you get more stats on the week after filling in Sunday’s performance. Very good or very bad performance suggests a Tweet that a user might like to make. The tweet links to their performance log on their profile.

Performance Log

Daily Promise Performance LogThis is a user’s main screen. It displays a chart of passes and fails for the last month or so as green (pass), red (fail) or grey (goal not active) squares. Below the chart, more detailed stats are presented, as well as an encouraging text summary of how the user is doing.

Settings

Most of the core settings such as username, display name, avatar and bio are handled by Twitter. Daily Promise‘s settings probably boil down to privacy (stop me being searchable, delete my account, etc.) and removing annoyances (always tweet on condition x, never tweet on condition y, etc. — all of which have an “ask me” setting by default).

Friends

Daily Promise Friends PageThe user’s “following” list from Twitter is used to generate their list of Daily Promise friends. Avatars, usernames and Daily Promise performance summaries are displayed here. Clicking through to a user’s profile shows the “performance log” page, topped with name / avatar / bio / etc.


So, and interesting idea, or an appalling one? Would you use this? Should I get off my arse and code? Should I have finished the last six things I started before prototyping something new? Your thoughts are, as always, appreciated.

Sea Battle: Of Ships and Submarines

The distinction between surface ships and submarines in Sea Battle has turned out to be a more thorny issue than I originally imagined.

The original plan was to have two classes of vessel, based on their hull types – ship or submarine – and weapons that could hit ships, submarines, or both. A future update could also have included aircraft “hulls”. However, the more I think about the game balance issues, the less I’m convinced that this is a good decision with the tech tree and playing field size that Sea Battle currently has.

Sea Battle’s tech tree, as it currently exists, has four straight “trees” with 10 items in each. By and large, each component that you research is better than its predecessor. (Later hulls are heavier and take longer to build, so small hulls are still useful. However, you would rarely want to choose anything other than the best weapon, engine and radar that is available to you.) Combined with the small playing field, this makes for a fast-paced game of a few minutes, with each player researching and churning out ships constantly to gain the upper hand.

There are a number of reasons why the current tech tree is inappropriate for submarines. Firstly, the weapons that a submarine could have: there’s only two. The Sting Ray torpedo (weapon 8) and Tomahawk missile (weapon 9) are the only weapons appropriate to be fired from a submarine. This would make rushing down the hull tree to submarines pointless unless you’d already reached near the end of the weapons tree — and in most games, you don’t even get that far.

It also creates a UI complication, in that currently, any combination of hull and weapon is permissible. Submarine-appropriate weapons would break that behaviour.

There’s an issue with anti-submarine weapons too. Again, only two (Depth Charge (6) and Sting Ray (8)) are appropriate for use against submarines. But since a viable submarine build wouldn’t exist until Hull 6 + Weapon 8, they would only exist in the late game, at which point Depth Charges just can’t hold their own against other weapons — so why have them at all?

To abuse game theory, the logical choice is for players to build Depth Charge ships when they become available, then hold them in reserve as insurance against their opponent building submarines. But if you see your opponent stocking up on Depth Charge ships, you might as well not bother building subs and just go for better weapons and radar instead. Whoever commits to a strategy first ends up on the losing end.

To cure these problems, perhaps we need to take another lesson from Warzone 2100′s book and have separate tech trees for different weapon types. So rather than one tree of 10 weapons, we have two trees for anti-ship and anti-sub. (And potentially anti-air later.) If we’re going down this route we ought to have different hull trees for ships and subs too. But at this point it’s turning into a rather different game — a slower, more traditional rock-paper-scissors RTS. But these games benefit from larger playing fields, varied terrain and squad-based combat — none of which Sea Battle is particularly well suited to in its current form.

So the question stands: Do I expand Sea Battle significantly to include this extra complexity, on the understanding that I would probably need to rewrite it in something other than Processing and that may consign it to the pile of “projects I lost interest in”, or do I just ignore the issue and for the sake of simplicity not treat submarine hulls as any different from ships?

Sea Battle, now with more Processing

Nearly a month ago now, I blogged some sketches and ideas for a game I felt like writing. masterofwalri made a passing reference to Processing in his comment, and having heard people mention it in the past, I figured I should check it out.

I’m very, very glad I did.

It neatly deals with the issue of what I should develop for. The comments were leading me down the Java path anyway, but Processing’s two-click export to Applet and bundles for Windows, Linux and Mac OS sealed the deal. And it’s easy to program in too — it’s clear that it’s beginner-oriented, but it’s also ideal for simple games like this as it simply removes all the starting faff, like sorting out JPanels and TimerTasks and all the rest. Time will tell if Processing over-simplifies things and stops me doing something I want to do, but for now it is excelling at the main task of high-level programming languages — reducing the amount of brain overhead I need to allocate in order to talk to the computer.

One lunchtime has produced 270 lines of code — which already includes the game area of the GUI, controllable player ships, and the beginnings of AI for the enemy ships.

You can play around with it as an Applet here.

Note: this blog post is old, and the applet now has more functionality than is described here. The next blog post in the sequence is here.

Currently there’s no real gameplay — you can’t build, and ships can’t shoot or be damaged. You can move your ships (starting at the bottom of the screen) around, and the AI ship will hunt yours. Click on a ship to select it (blue circle), then click elsewhere to set its destination. Red lines, when they appear, show when ships would be shooting.

The next block of code will give the ships customised gear, health points, and the ability to attack and sink others. With that will probably come attack animations, which with my lack of skill in that department, will take a while. After that, damageable bases and win/lose conditions, then the build/research system. Finally, graphics tweaks, AI improvements and game balancing will finish it off.

More bloggery will appear once more coding occurs!