Strats and Tacts

This is a blog about strategies and tactics I have learned, mostly from my experience of playing 3D fighting games and reading classic strategy books. Oh... and Java.

Thursday, March 26, 2009

The top 8 reasons I don't use Wicket

A few months ago I knew I was going to make a hobby website. In preparation I decided to learn a new Java web framework. Wicket had a lot of hype around it in the #java channel so I figured I should give it a shot. Along the way, I created 2-3 work projects, 2 practice hobby projects and 2 open source libraries for it. All in all, I spent about 5 months using it and frankly, it was a terrible experience. This article will explain my complaints, but first, I will give you a little introduction to the framework.

In a typical web framework, you write a template that's more-or-less HTML, but with special code to make it dynamic. For example, here's how to print "Hello World" in php:


NOTE: I am NOT saying that PHP is better than Wicket. I'm just EXPLAINING how Wicket works compared to other frameworks and using PHP as an example of another framework.

<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php echo '<p>Hello World</p>'; ?>
</body>
</html>


In the <?php ?> tag, you specify what HTML will be generated. Wicket works in a different way. You mark the dynamic parts of your HTML with a special attribute and specify what it does in Java code. Here's the same example in Wicket:

<html>
<head>
<title>Wicket Test</title>
</head>
<body>
<p wicket:id="message">This is replaced</p>
</body>
</html>


And then in a Java class:

public class HelloWorldPage extends WebPage {
public HelloWorldPage() {
Label component = new Label("message", "Hello World!");
add(component);
}
}


By comparison the html template is simplified: You define the parts that are dynamic but you don't say what the dynamic parts will do. That's done entirely in the Java code. If you learn more about Wicket, you'll see that your Java code ends up looking similar to Swing code (Swing is Java's GUI API).

Before I go on to explain the top 8 reasons to NOT use Wicket, I want to say that there is one situation where I would still use it: If a large part of my webapp functioned like a wizard. Wicket makes it easy to keep track of state from page to page without persisting at each step. With a traditional framework, you have to manipulate the session or use hidden fields to accomplish this.

1. Documentation, documentation... documentation?
By far my biggest complaint about Wicket stems from problems with its documentation. Imagine this: You get stuck on an issue and have no idea why. First you search the official wiki. You try your hardest to find a section to answer your question but it doesn't seem to be there. On the other hand, it's so badly organized you may have just missed it. You guess it's not there and move on to the examples.

The examples can be useful, but there's a lot to be desired. Exercise: Visit http://www.wicketstuff.org/wicket13/ and try to find an example that shows you how to redirect to a different page after you submit a form. I had to ask in the IRC channel to figure out how to do that. It also doesn't help that there are two example pages. One is on the main site, and another (much more useful, I might add) that's on wicketstuff.org (but good luck finding these examples on the wicketstuff.org home page).

Lets say the examples didn't help so you move on to the Javadocs. No help there: The class in question and its methods are barely documented. Take a look at this gem: http://wicket.apache.org/docs/wicket-1.3.2/wicket/apidocs/org/apache/wicket/SharedResources.html At least this time it's obvious the answer isn't there.

Time to move on to the mailing list archives. You discover that Wicket's mailing list is extremely active and is often the only source for answers. Here's the downside to that: 1) A mailing list is not the right environment to learn a framework. A mailing list is for situations where you more-or-less "get" the technology, but are unsure of a few things. 2) It's hard to find mailing list answers by Googling. Think about it, how often do people link to a mailing list threads? Almost never. That leads to poor page ranking and that means the answer to your question, even if it's there, is hard to find.

2. High learning curve
Even if the documentation was well written and complete, Wicket would still be harder to learn than most frameworks. Lets look at how to solve some basic problems using the example above:

How do hide a dynamic tag? component.setVisible(false). How do I dynamically add a class attribute to the tag? component.add(new SimpleAttributeModifier(“class”, “classValue”)); How do I dynamically add a CSS file to my template? webpage.add(HeaderContributor.forCss("/path/to/my.css"); Do you see the problem? It's subtle.

Knowing the answer to one of these does not help you in answering the others and each one of these questions requires you to deal with part 1. On the other hand, as soon as you learn how to write a conditional in PHP/JSP/ROR, you immediately know the answer to all of these questions and many more in the future.

Let's try an example together: How would you make a page's title dynamic in Wicket? Is it webPage.setTitle(String)? Nope, that doesn't exist. In fact, the word title isn't even mentioned in the javadoc. Ok, dead end #1. Perhaps it's webPage.add(new Title(...)); or something like that. Nope, there's no such thing as a Title class. In fact, the word Title isn't even part of any class in the javadoc. Dead end #2. That also rules out something like webPage.add(TitleContributor...); Dead end #3.

So, how the heck do you actually do this in wicket? The only answer I can find is webPage.add(new Label("wicketId", "dynamicTitle");. You add a Label to your page that attaches to your <title> tag and overwrites the text. Duh!

3. Different... not better, but different
In my 5 months with wicket, there was no indication that it was a time saver. Wicket seems more about making a webapp in a different way than in a productive way. Compared to a framework like Struts or Ruby on Rails, Wicket probably decreased my template code by 4x but increased my Java code by 4x. I ended up doing the same amount of work, just in a different place.

If you consider writing template code to be traumatic experience, perhaps you'll see this as a huge improvement. But, if you're like me, you'll think that a webframework should help you write less code. Writing less code has a lot of benefits. There's less to understand, less to maintain, less work to add a feature, etc.

Perhaps these time saving features exist and I overlooked them. Unfortunately, Wicket doesn't have an official list of, "Cool features that will save you tons of time" anywhere, so you'll likely have the same experience as me. But, I did read most of "Wicket In Action" (great book for learning Wicket, BTW), and it didn't change my impression.

4. Lacking 3rd party library support
Getting 3rd party libraries to work in Wicket is more annoying than other frameworks. By 3rd party libraries, I mean external tools that add content to your website that may or may not care about the programming language you use. Things like ReCaptcha to add a captcha to your site, the Facebook API for making a Facebook app, or Rome to add a RSS feed to your site. Fortunately, there are Wicket extensions for these examples (I made the first two), but unless you make your entire webapp from scratch, you're bound to run into others that aren't. With Wicket, getting these libs to work can be painful and confusing.

Lets look at ReCaptcha to see why. With ReCaptcha, you add a <script> tag to your webpage that refers to an external javascript file. When it loads, the script generates a captcha and an input field for you. When the user submits the page, you take the input and ask the ReCaptcha server, "User typed this, is that what was displayed?".

With most frameworks, this is an easy way to add a captcha to a website. With Wicket, it's a challenge. Since you didn't include this input in your template (remember, Wicket needs a wicket:id attribute on input fields too) and you didn't put add(new TextField("recaptchInput")); in your Java code, Wicket is unaware of the input. As a consequence, you can't leverage any framework features. This includes essentials like retrieving the value so you can pass it to the ReCaptcha server.

For those wondering "Why doesn't he just put it in his template and add the Java code?", that won't work: The ReCaptcha script would just generate another input field for you and cause the same problem.

What's the solution? You need to reach into the HttpServletRequest and extract the value by hand. Most frameworks, including Wicket, consider this a primitive way to get data from a user response. Yet, as far as I can tell, it's what you have to resort to.

5. Generate HTML or generate pain
Sometimes you want the server to generate something other than HTML. For example, you may want to generate Javascript or CSS. EG: var message = "dynamicString"; To make the string dynamic, the template would have to say var message = <span wicket:id="dynamicString">localized alert</span>; You have to do similar things in your CSS files to make them dynamic: .highlight { <span wicket:id="highlight">highlight style</span> }

Unless your editor speaks Wicket, this will drive it nuts. Not only will the dynamic bits be more verbose than a typical framework, they'll look more out of place. "Why is this HTML embedded in this CSS file?".



6. Easier to maintain?
One of Wicket's selling points is that it's far easier to maintain than other frameworks because you write most of your code in Java. I think that's debatable. Is 4x more Java code more maintainable (see part 3)? The code you write ends up looking like Swing code so unless you're very disciplined, you end up writing anonymous and inner classes all over the place that share instance variables with the parent class. Once that happens, it's a real chore to refactor them to outer classes.

If you put in the effort to avoid these pitfalls, your code may be more maintainable. But a framework is supposed to facilitate discipline, not put the burden on the developer. With Wicket I found myself thinking, "OK, how can I add that feature without it turning into a mess later?". I'd prefer to just focus on the feature itself. If I wanted to focus on proper discipline, I would've stuck with JSPs and Servlets in the first place. This goes back to the question, "What is this framework doing to make my life easier?"


7. The "Great for web designers" myth
Wicket is supposed to be nice for web designers because it doesn't use template code. You just put a wicket:id="something" on the HTML you want to be dynamic and replace it in your Java code. The end result is your HTML is perfectly understandable by a web designer who doesn't know the first thing about Java. While Wicket may be better than other frameworks in this respect, it still has problems.

For instance, Wicket has non-HTML tags for special functionality with names like <wicket:panel>, <wicket:child> and <wicket:extend>. These won't render correctly in a browser. If you research the last one, you'll see you must violate the "Don't Repeat Yourself" principle to get your pages to render outside the browser in a way that looks similar to its production code.

In general, Wicket is better than most frameworks in this respect. But, when you consider part 5, it can sometimes be worse than most.

8. Search Engine De-optimization
By default, the URLs Wicket uses look like this: http://www.startfound.com/?wicket:interface=:3:::: For a search engine, this is a problem for two reasons:
  1. This URL provides no semantic information
  2. This URL is only valid for that user's session.
This second point is really important: If google indexes http://www.startfound.com/?wicket:interface=:3::::, when users follow the link, they'll be taken to a "Page Expired" error page. It's not a great first impression. You could make your URL look pretty like this: http://www.startfound.com/home, but that requires using a Wicket concept called "bookmarkable URLs". Hopefully, the name is self explanatory but they bring with them a big downside.

There are Wicket classes that won't work with bookmarkable URLs. For example, if you want to use the Wicket "paginator" (think the bottom of Google search results), your URLs have to look ugly. So if you want pagination on your site with pretty URLs, you're going to have to write it yourself. And that goes for a lot of its other APIs.

Conclusion
There was a point while working on my hobby website that I was pulling my hair out dealing with these issues on a daily basis. Finally, I had enough and came to the conclusion that it was smarter to rewrite the whole thing from scratch in another framework.

I chose what I'd consider to be the exact opposite of Wicket: The Stripes Framework. During and since the rewrite, I couldn't be happier with my choice. When it comes to ease of use, quality documentation, simplicity and productivity, I've never worked with a better web framework. Let me state that I'm not affiliated with the Stripes framework, I'm just a huge fan. I have experience with Struts, Ruby on Rails, plain old JSPs and Servlets and, of course, Wicket, and the Stripes framework is by far the best web framework I've ever worked with.

One last note on Wicket: Of all those projects I created while learning it, there was one where I feel Wicket was the right choice (the whole thing was basically a Wizard). So in the end, I consider Wicket to be a hammer in my tool belt. Unfortunately, most jobs I come across require a screwdriver.

You can see my follow up blog post that compares Wicket and Stripes in depth here: http://www.assertinteresting.com/2009/03/why-i-prefer-stripes-over-wicket/

Saturday, March 21, 2009

The difficulty of designing a Final Fantasy-like battle system

I haven't mentioned this before, but in my free time, I've been developing a game. It's a turn based game like Final Fantasy / Dragon Warrior, but you play online with other people. You control a party of people and fight against another party of people. When one character is choosing his ability, game time freezes. Once he chooses his ability, he chooses a target to use it on. Then, time progresses a "tick": he performs his ability and the next character in the queue repeats the process. This is all pretty standard stuff and not too difficult to design. But...

The part that was / is hard for me to design is the concept of an Ability. Let me show you some examples of abilities that will exist in my game. I've highlighted and numbered some key points on each ability that I will discuss in detail:
  • Attack: One of the simplest abilities. When you use this on a target, it causes (1) immediate damage to him. This (2) costs no MP (magic points).
  • Poison: When you use this on a target, he will be (1) damaged over time, when it's his turn to pick an ability. It (2) costs some MP. It's affect (3) lasts a certain amount of the target's turns.
  • Blink: The target of this ability (generally a teammate), cannot be hit by physical attacks. (3) After the 3rd physical attack that misses, the effect disappears.
  • Cover: When you use this on a target (generally a teammate), the (4) user will take damage instead of the target if another character attacks the target (5) with a physical attack. It's effect only (3) lasts until the user's next turn.
  • Reflect: When you use this on a target and another character (5) uses a spell on him, the spell will reflect off of the target and (4) affect the caster instead. Since this can reflect helpful and harmful spells, it can be (6) used offensively or defensively.
  • Defense: This ability (7) halves physical damage, but this can (6) only be used on yourself.
  • Economizer (This is usually an item, but in my game it'll be an ability): The target's (2) MP cost is reduced to 1, regardless of the ability.
  • Bad Breath: This casts (8) mulitiple, and often random, ailments on the target (eg: poison, silence, blindness).
Ugh, that's a lot of bold. So, what did we learn? Well...
  1. Some abilities have an immediate effect, others last for a duration.
  2. Some abilities abilities cost MP, but others don't. And, there are some abilities that alter the MP costs of other abilities.
  3. Some ability's duration is based on the user's turn, some is based on the target's turn. Sometimes it's based on how many times you get attacked. Sometimes it's a combination of these (eg: an ability could last for 3 attacks or 6 turns, whatever occurs first). The possibilities on this are endless.
  4. Sometimes the target of an ability is not the character that gets affected by it. For example; if you cast Fire on someone with reflect, Fire isn't cast on him, it's cast on you!
  5. The trigger of an effect can vary from ability to ability. For example, reflect is only triggered by spells. If you Attack someone who is effected by Reflect, Reflect isn't triggered. But, if that character was effected by Cover, Cover would have been triggered.
  6. Some abilities can only be used on yourself, some can only be used on your enemies and some can only be used on your friends.
  7. An ability's damage is not a constant but can change depending on the other abilities that have been used on the target. Note the similarity between this and #2
  8. An ability can have multiple effects. In other words, sometimes using one ability is like using a combination of abilities simultaneously.
Basically, the Ability is a God class. It could (and should) be able to do almost anything you can think of (and anything you haven't thought of, yet). As you can imagine, it's very hard to design a class with requirements that are basically, "It should be able to do anything".

In my next article, I will talk about the solution I came up with.

Tuesday, March 10, 2009

What are mock objects, why do I love them, and why do I use Mockito?

What's a mock object? Here's Wikipedia's definition:
In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A computer programmer typically creates a mock object to test the behavior of some other object
When you write a unit test, you want to try and focus on testing a single class. But, in any complex system, classes use other classes. So, in that situation, how do you just test one class? You separate class creation from class usage: The class you're trying to test never contains the "new" keyword. Instead, it receives the classes it depends on through it's constructor or setters (the formal term for this is Dependency Injection). So your code that used to look like this:

public void useDependency() {
new Dependency().useDependency();
}
Now looks like this:

public void setDependency(Dependency dependency) {
this.dependency = dependency;
}

public void useDependency() {
this.dependency.useDependency();
}
Yes, there's a little bit more code, but now it's easy to test.

In Michael Feather's book, Working Effectively With Legacy Code, he describes the difference between a Mock and a Fake object. A mock object verifies its own state is correct. A fake object, on the other hand, has its state tested by an external object (typically the testcase it's created in).

Before I discovered Mockito, I got by with Fake objects. Fake objects have some problems though. The main problem is you have to make them yourself. If you need a fake interface, but you're only testing one method, you still have to manually stub out all the other methods.

For example, I'm making a Swing app and when I wrote test cases for my client, I had to make a fake Graphics object. With just stub methods, this class is about 300 lines!

So then I tried JMockit, but I had some major complaints. It's tutorial is horrid and scattered all over the place. Whenever I tried to use it, I always had to open its documentation after realizing I wasn't using it correctly. What makes this worse is it's not easy to discover you're using it incorrectly! If you do something wrong, it'll usually return null instead of throwing an exception. 99% of the time, you pass this null pointer into a setter and you eventually get a NullPointerException in the middle of your test. Why doesn't it fail immediately? Also, it seems like you have to use different API calls for mocking concrete classes vs interfaces (or maybe it doesn't work with concrete classes. Here's a fun exercise: See if you can figure that out on your own. See what I mean by the horrid documentation?). Plus, you need special VM arg to run it.

JMockit has one redeeming quality (that's actually very cool): It lets you inject classes even if you're not using dependency injection. At first that may not seem possible, but check out its "documentation" to see how. For this reason, I would still use this library if I was trying to test crappy legacy code that I was terrified to change in any way.

Next, I looked at EasyMock for about 3 minutes. I couldn't figure it out with that amount of time so I moved on (I know, not a fair review, but at least an honest one).

Then, by luck, I stumbled upon this controversial, unrelated article and in a comment I saw a reference to Mockito. I checked it out and it turns out to be the best of all worlds. It saves you from writing fakes, it's documentation/API is concise, consistent and without ambiguity, it doesn't require extra VM arguments, and, you can learn it in under 3 minutes.

I highly recommend it to anyone who's writing unit tests. It saves me a lot of time while simultaneously making my code more readable.

BTW, if you're already using EasyMock, here's a Mockito article on Mockito VS EasyMock.

Sunday, March 8, 2009

Sticking Tight

In The Book of Five Rings, Miyamoto Musashi has a section called "Sticking Tight".
...When you and your opponents have taken sides and are facing off and it is not clear who will prevail, right then and there you stick tight to the opponents, so that you cannot be separated, and in that process find the advantage...
This is often a very good strategy in video games, too. When I'm playing against someone who's giving me trouble, I often change my goal to get close to him, wait, and see how he reacts. By not attacking, he'll typically respond with confusion, then panic. In the panic stage, he'll hack together a spur of the moment attack which is easy to interrupt.

There is a Soul Calibur player named Semi who often just runs into his opponent after an exchange. This leaves Semi completely vulnerable but it has been the source of many victories. How can he succeed with a strategy that by all explanation is completely foolish?

It's the state of confusion it causes. No one in the right mind would do this so it takes a while for the opponent to realize what's happening. By the time he does, he's already been pushed to the edge of the ring and Semi has a good chance of knocking him out. Not only does this strategy work, it's completely demoralizing.

Wednesday, March 4, 2009

The Art of Sandbagging

Sandbagging in poker is the opposite of a bluff: You try to make yourself look weaker than you really are. This post will explain when and where to use this strategy and follow up with some personal examples of how to win with it.

Lets assume your long term goal is to win an upcoming tournament and you have an opportunity to play against the toughest competitor beforehand. You can use this time to make your opponent think they know how to beat you. You do this by intentionally playing worse than you really will in the tournament.

When you play that person, they will come into the fight with a strategy based on the way you pretended to play. When nothing he planned works, it will be completely demoralizing and surprising to him. Generally, a tournament match doesn't last long enough to recover from this shock.

Here are some real examples I've used in the past: A very important Tekken 4 tournament was coming up and the night before, I played against the person I was most worried about. Every time he threw me or jabbed me (you beat these by ducking) I let it damage me. I intentionally picked these moves because my character had very damaging moves that go under attacks. Naturally, when we played in the tournament, he ended up using the exact opposite strategy against me that he should have, and lost.

The night before a big Soul Calibur 3 tournament, I played some of the people I was most concerned about. My character happened to have very annoying pokes that were hard to interrupt. During these sessions, I played super aggressively and used these pokes whenever possible. Here you can see my goal wasn't to look worse than I was, just that 1) my character has really annoying pokes 2) the pokes are very effective. I believe these people spent the rest of their time trying to figure out how to beat the combinations I was using.

But, during the matches that mattered, these people were trying to beat an exchange that was never coming. I switched my strategy to one of "wait and interrupt". They kept on trying to bait me into poking them and I kept on backing up and keeping them out. After the tournament, this person wanted to play me again to prove to himself (and others that watched) that he figured out how to beat me.

Although he didn't win the tournament, he believed that if he played me again, things would go very differently. Of course, he had no idea that I sandbagged after the tournament, too. :)

The SOLID principles in order of importance according to Uncle Bob

Uncle Bob had a podcast on Hanselminutes where he discusses the SOLID principles at length. I highly recommend you listen to the whole thing if you want to learn what the SOLID principles are. I'll wait..........

Ok, now that you know what SOLID's all about, I want to point out that off the top of his head, Uncle Bob listed the principles in order of importance:
  1. Single Responsibility Principle
  2. Dependency Inversion Principle
  3. Open Closed Principle
  4. Liskov Substitution Principle
  5. Interface Segregation Principle
Or, SDOLI.

I'd like to learn exactly why these principles are ordered this way, but, the podcast didn't really focus on this perspective.

Monday, March 2, 2009

You are here. You should be here...

In a fight, where is the best place to stand? That depends.

If you're attacking, the best place to be is barely in range. Here, your opponent will think he's safe when he's not. He'll get hit by moves he otherwise wouldn't because of a false sense of security. At this range, even if he does block, you are harder to retaliate against because you're often out of range.

If you're defending, the best place to be is barely out of range. Here, your opponent will think he can hit you when he can't. He'll be baited to attack when he shouldn't. Also, you limit his attacks to the ones he thinks can reach.

Of course, you're also limited to your long-reaching moves when you're in the ideal attacking position. That is why you should think of this as a principle rather than a rule: If your sole strategy is to stay in the ideal attacking range, you'll become too predictable.