*phew* I just finished a livestream that lasted for just over 8 hours! It's way more fun to work with people to talk to.
This devlog is for both today and yesterday. Yesterday's work was fairly evenly split between project planning and writing automated tests for the client. Today's work was a blur of refactoring with occasional emergency bug fixes.
Very Large Tasks
I started the day yesterday by adding in Jake's tasks for iteration 39 and 40. This consisted of making a few tasks and entering a lot of work logs.
The tasks were very large, consisting of an estimated week+ worth of work. This has been throwing off the iteration charts, but I plan on sitting down with Jake to get it sorted out.
The main issue is that an iteration is only one week long. So a task which is more than one week worth of work will just not fit. These larger tasks should ideally be broken up into bite sized pieces of perhaps no more than a days worth of work.
Mocking Trouble in Mockolate
I had a lot of trouble with mocking methods using Mockolate. I kept getting an Error #1065 when I tried running Cuke4AS3. The error seemed to be caused by any of the "calls..." methods. However, DConsole in the Cuke4AS3 DeveloperUI was not giving up any filenames, line numbers, or stack traces.
Fortunately I found a workaround, albeit a far from perfect one: Stubbing, rather than mocking, worked just fine. I had no idea why, but I was just glad something worked.
But unfortunately, I ran into the error again and this time simply changing the mock to a stub did not fix it. Rather than on a "calls..." method, it was now happening with the "times" method. No matter what I did, the error would not go away.
While looking for a way to get more debugging information, I accidentally found the cause: The DeveloperUI was automatically including a version of FlexUnit in addition to the one I provided. This must have been causing some sort of conflict, because once I removed the redundancy the error disappeared. I hope this helps anyone else who is having the same problem!
Who Owns It? UI or Logic?
One part of the refactoring work stands out in my mind. It is the part that I spent the most time on: Deciding whether moving characters between tiles is the responsibility of the user interface or the logic layer.
This isn't as simple as it might seem. Having the character start moving to a new tile could be seen as a move command. That feels very much like it belongs in the user interface layer.
On the other hand, the code would need to be aware that the character can move. That decision is a game rule, and if so it belongs in the logic layer.
I eventually decided to use a bit of a hybrid method. The UI polls the logic layer to see if the character can move. If he can, the UI issues a move command to the logic layer. The logic layer then handles the rest.
The Bug that Couldn't be Traced
While trying to move a forgotten user interface method into the GameUI class, I discovered that changing directions didn't work anymore. Upon further digging, I also spotted that your character would not stop animating after running into a wall. To make things even stranger, it looked perfectly fine for everyone else: Your character would be continually walking into a wall on your screen, but everyone else saw him standing still!
I first assumed it was an issue with the event listener call order. To test that theory, I placed trace statements in all of the listeners. Oddly, the output window remained empty.
So I looked for a method that I was sure would be called. The class didn't have a constructor, so I decided to use its initialization method instead. Placing a trace statement there, I ran the game again... And the output window was still empty.
The next few minutes consisted of random tests, checking flashlog.txt, checking other windows... Someone watching the stream even jumped in to try and help me figure out where the traces were going.
I eventually tried creating a basic constructor for GameUI. After placing a trace statement in it, I tested the game again.
There was a message in the output window!
This is when I realized what had gone wrong: The class was never being initialized. None of its event listeners were being registered!
After properly initializing the gameUI object, the game worked again. This was a major oversight that may have gone undetected if I had not decided to move that one method. Who knows how confusing it may have been to debug if it had been left alone.