Refactoring sometimes creates issues
Not as expected
I didn’t get much accomplished this weekend on my adventure game. While I did manage to get a ContainerThing class created, the next step kind of failed miserably.
ContainerThing was added as a descendent of the Thing:w
class so that we can have chests and sacks; things that have to be opened and closed before user access. That all went pretty well. I did have to adapt to using instanceof in order to access the isOpenable field and the open() and close() methods. But it worked out.
However, before moving further, I wanted to follow the author’s direction and the time has come for a pretty major refactor. Right now, all of our game methods reside in the Game class. Two of these are really important for the user, wordList( String input ) and parseCommand( String[] wordlist ). wordList tokenizes the user’s input into a String array. parseCommand uses this String array to determine two Strings; verb and noun, depending on whether they are in our list of acceptable words. verb and noun are then passed to processCommand( verb, noun ) to determine what action to take. Is it take sword or north and what method receives those words?
Though the author dives right in with the refactor, I approach these tasks differently. Writing a method in one class and then deciding it ( or a group of related methods ) deserves its own class, is common in programming. When I encounter these issues, my first step is not to dive into the refactor. My first step is to relocate the methods into a new class “as is” and adjust the calls and returns until things still work.
My problem here, and eventually my issue that failed, is how processCommand gets called. I moved wordList and parseCommand to a new class called Parser. We are going to make great differences in parsing verbs and nouns to also include articles ( the, a, an ) and prepositions ( into ). The new methods will be static methods and will be called with Parser.wordList and Parser.parseCommand. The first, Parser.wordList sets up pretty well as it just returns a String array. Again, that String array is the input for Parser.parseCommand. Both methods are called from the Game class.
Things began to fail when I noticed that Parser.parseCommand returns a message String which eventually goes back to the user’s terminal as a status message. Game.processComand is called internally from the parser and isn’t a return. Additionally, our Game class isn’t static. It is instantiated in the Main class when everything begins. I can’t just willy-nilly call a non-static method from a static method.
With chatGPT’s help, we decided on a mediator, a record class to carry the verb and noun into the game object method of processCommand. Yet, after an hour or more fighting it, I decided to give up until later. Though I got it to work and compile, it wouldn’t run right. Things weren’t going where we sent them. Better to put it aside and regroup for later.
Fortunately, I use git. I had not committed anything of what I was doing. So, I did git reset --hard HEAD, I think. You might want to look it up. It lopped off what I had done and reset my dev branch back to it’s last good commit ( the one where I added ContainerThing ). I could now delete any extraneous files and move forward. I also branched to a refactor branch so I could work on this problem without touching the dev branch.
Not everything we do in programming works right the first time. Many times, it does not. We set up our workflow and toolchains to help with this very problem. I will eventually solve the problem, even if it is just following the author on the new branch. My tooling will adjust and I’ll not go over the cliff.
I realize this is a one-way conversation. I intend to try soon to get Hugo to add a comment section. I’m pretty tight on comments, though. They will all be reviewed before published. No spammers or other types. Anyways, carry on, happy coding!