Lesson 04.5: Improving the World – Factory and Guard Clauses

In this lesson, we will do more refactoring to the code we wrote over the last few lessons, where we were building the world classes.

 

 

Named Parameters

In the GameSession constructor, we instantiate a Player object, and set its properties.

Because the Player class has public properties, that each have a public “set”, we can make this code cleaner, by using “named parameters”.

When we use named parameters, we can remove the parentheses after the class name, when we instantiate the object. Then, we add opening and closing curly braces. Inside the curly braces, Visual Studio will show us the public properties that we can assign values to. We add the property name, an equal sign, and the value we want to assign to the property. If we want to add values for more than one property, we need to add a comma between each property.

 

Step 1: Edit GameSession.cs

In the constructor, replace this code:

 

With this code:

 

I like this technique because it is very clear what properties are being set. Plus, IntelliSense is available, as you set the property values.

 

Static Factory Class

While we are inside the GameSession constructor, we can make an improvement to the WorldFactory class.

Notice that we instantiate a WorldFactory object, get a World object from the CreateWorld function, and never use the WorldFactory object again.

We can make a change that will allow us to get a World object from the WorldFactory class, without instantiating a WorldFactory object. We do this by making the WorldFactory “static”.

You can use a static class, without instantiating it. Because we are only going to use the WorldFactory class to create a World object, it is a good class to make static. Using a static class, or function, to create objects is known as the Factory Design Pattern.

There are some rules to remember about static things.

  1. A static class can only have static methods/functions.
  2. An instanced class (like the Player class) can have static functions. These functions can be called, without creating an instance of the class.
  3. A static function can only use objects it creates inside the function, other static functions, or static class-level variables.

 

 

Step 1: Edit WorldFactory.cs

Change this line:

To this:

 

Notice that the CreateWorld function now has red squiggly lines underneath it. If you hover over CreateWorld, you’ll see an error message that says:

‘CreateWorld’: cannot declare instance members in a static class

Static class ‘Engine.Factories.WorldFactory’ cannot have a non-static method ‘World CreateWorld()’

 

This error is saying, “because the WorldFactory class is static (it will never be instantiated), it cannot have a function that requires an instantiated object”.

To fix this, we will also make the CreateWorld function static, by changing it to this:

 

Now, if we look at the constructor in GameSession, we see some errors. That’s because we are trying to instantiate a WorldFactory object – which we cannot do, now that it is a static class.

So, we will change these lines:

To this:

 

Now, the program doesn’t create an object it will only use one time.

 

NOTE: We can safely make WorldFactory a static class because we are not “maintaining state” in it – we are not holding any variable values inside the static class. We cannot make the Player class static because we need to “maintain state”. In a Player object, we store the player’s hit points, experience points, gold, etc. Those values will change, as the user plays the game.

You can store values in a static class, by creating static variables (like the private variables we use in the Player class). However, then you need to be more cautious about what changes those values. Because a static class does not need to be instantiated, it is available everywhere in the program. When any part of a program can change a value, it can be difficult to track down bugs.

 

Guard Clauses

Finally, we will look at the movement functions in GameSession.cs.

Currently, MoveNorth (and the other movement functions) will always try to move the player – even if the world does not have a location in the direction of the function. We prevent that from happening by making the movement buttons invisible in the UI. However, there is a saying in programming, “Never trust user input”. In some programs, a hacker could figure out how to send invalid calls to our code. Even though this is not a commercial program, we should be safer.

Inside each of the movement functions, we will do a check if there is a location in the direction. If so, we will set the CurrentLocation to the new location. If not, we will not do anything.

So, we will change the code for the movement functions to this:

 

Now, if the movement button visibility does not work, we have a second layer of protection in our code – which should prevent the user from doing something that would cause an error.

 

 

Final Version of the Source Code

WorldFactory.cs

 

GameSession.cs

 

 

 

 

Return to main page

6 thoughts on “Lesson 04.5: Improving the World – Factory and Guard Clauses

    1. I normally add two lessons per month. In April, I had a large project and also went on vacation. So, I didn’t have any new lessons. I should be back to the regular schedule, with a new lesson this weekend.

  1. why/when did you remove:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    from gamesessions?

    1. Those were probably removed by ReSharper, a Visual Studio plugin I use. If your class is not using any classes/functions from a namespace, ReSharper can remove it from your “using” directives when you run its “cleanup code” function.

  2. Scott,

    Thanks for these session as it has helped tremendously. I’m an amateur programmer and you really put some parts into perspective. When changing the world to static and refactoring the GameSession, I thought the call for new CurrentWorld become more clear. Prior I had issues to maping the information flow from Gamesession, Worlfactory and World. Majority of the time I understand the programming logic. My problems come when writing the program itself. I seam to stumble as there appears to be so many options to perform a said task. For a novice, what do you recommend to overcome these issues. I continue to watch videos and read material on C# and follow exercises and type them in visual studio to understand the flow. Do you have any other suggestions?

    I’m in the IT Field but mostly have done scripting which is a very different perspective when it comes to OOP.

    Thanks for these lesson as I continue through the class. You explain this in a clear and concise manner. Many Developer video talk on a much higher level that a beginner would not understand. Well off to the next lesson.

    1. You’re welcome, Allan,

      The best way to figure out with method to use is (unfortunately, for beginners) experience. However, it is possible to borrow some experience from other programmers. “Design patterns” are common ways to solve common problems. Like a chef learning how to bake, saute, etc., design patterns cover the general techniques. I have posts on some common C# design patterns. The book “Head First Design Patterns” is extremely good. It uses Java for the code, which is close enough to C# that you should be able understand the principles they’re trying to teach.

      I also like to write small “workbench” applications when I want to test a new technique. Take a problem you understand very well – maybe planning your garden, or keeping inventory of something you collect. You can write a very simple program to do that, then test out different techniques to modify it. Just make sure you use source control, so you can always undo the changes you make, and return to a working program (in case you have trouble implementing the new technique). You might want to follow the Plan-Do-Check-Act method (it’s also known as the OODA loop, and some other names) when experimenting. Treat your coding experiment like a real experiment. Decide what outcome you’re hoping to get by making the change (faster code, easier-to-read code, etc.), implement the new technique, check if it did what you expected, and adapt (if it didn’t do what you expected).

      I’d normally suggest going to local meetups, but those probably aren’t happening right now. Keep up with online training. There is a huge inventory of videos at MSDN Channel 9.

      Good luck, and let me know if you have any other questions.

Leave a Reply

Your email address will not be published. Required fields are marked *