Tuesday, January 10, 2017

The Factory and Repository Pattern

So I bought a copy of "Learn Python the Hard Way" which I highly recommend to any would-be programmer learning Python.  The mid level project is to work on your own text adventure game.  It's supposed to be "Zork" like, with set rooms that you navigate through until you reach the end of the story.  The project is supposed to use all knowledge taught thus far, including "while" loops and "for" loops, as well as object inheritance and composition.

I took things a bit further.

I have been studying design patterns.  They're kind of like joseki in the game of Go, set patterns that are solutions to different situations.  After all, in software engineering, you come across the same problem multiple times, or at the very least, similar problems with similar solutions.  I've been reading "Head First Design Patterns," scouring the internet, and getting help from a software engineer friend of mine, and found two patterns that I found useful: The Repository and Factory pattern.

Here's my problem: the game is a text adventure.  You walk around rooms, talk to NPCs, fight monsters, pick up items, and fight.  During my first go through, my code was starting to get to be complicated.  I decided I wanted to save my items, npcs, rooms, etc. as JSON files.  That way, I can simply drop the rooms into a folder called "rooms" and just have the computer load the file, read the information, and create a new Room object or Weapon object or Silly String object.  Whatever I needed.  The game would be filled with different types of objects I would need on demand.

Here's where the patterns come in.

The Repository pattern is a way to request a certain kind of object from a "repository" of objects  you might need.  The factory is a way of constructing different objects you need on demand.  I linked it to a File loader object.  Essentially, the repository receives a request for a specific kind of object, then the file loader loads the JSON file, wherever it might be.  The factory creates the right kind of object (be it a room, a weapon, or a NPC) and returns the object to the repository.


What's great is that each part isn't "coupled" tightly with each other.  The repository just needs to know which factory to load and which file loader, past that it has no idea how a file is actually loaded, and definitely not HOW to make the object in question.  The file loader just takes an ID and a file path already given to it, and spits out a dictionary of information.  Does it have any idea the difference between Gandalf the Gray and a stick of butter?  Nope!  And it doesn't need to.  The factory basically just looks at the "type" part of the dictionary, and puts it through the sausage machine.  This makes it easy to use the factory for all kinds of things, including spells, monsters, and even actions.  

The main thing I learned is you need to de-couple one part of a program from another as best you can.  I don't want the repository to have deep tendrils into the factory, or else, if I have to change something about the factory, then the repository might also need to be re-coded.  The more complexity, the more chances there will be bugs.  

The next part of the game is to create a view for the player.  I was thinking a Game Screen class that spits out information at the player whenever the "Game State" changes.  So if the id changes, then it can have functions like "Print Room" etc.  That way, the action classes don't need to really care about what is being displayed to the player, they just need to conduct their own checks.  

I smell Observer pattern...but we'll get to that next time.

No comments:

Post a Comment