tag:blogger.com,1999:blog-107219952023-06-20T13:34:08.765+01:00The Cat's CodeCoding thoughts from the Creative CatAnonymoushttp://www.blogger.com/profile/14091105723232979517noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-10721995.post-38115551434457416022016-01-02T12:29:00.002+00:002016-01-03T00:00:45.273+00:00An Exploration of TDD Part 3 - Discovering that EF7 Doesn't Like ArraysWith my generic <span style="font-family: "Courier New", Courier, monospace;">Get()</span> method working as it should, it's now time to bake something that can retrieve a single location by its Id. My test for this looks as follows:
<br /><br />
<script src="https://gist.github.com/FraukeN/026d8c2908236a20b776.js"></script>
...and my initial implementation for the<span style="font-family: "Courier New", Courier, monospace;"> Get(int id)</span> method simply throws an exception, which makes the test go red.
<br /><br />
<script src="https://gist.github.com/FraukeN/9baed2857b0862f65a3c.js"></script>
After my first red, I implement the <span style="font-family: "Courier New", Courier, monospace;">Get(int id)</span> method:
<br /><br />
<script src="https://gist.github.com/FraukeN/4c2e09b3134215976bac.js"></script>
Running the test with the new implementation gives me - another red. The test fails on my attempt to retrieve the correct exit in direction 0. So what's going on here?<br />
<br />
Stepping through the test in the debugger reveals the following: locations <span style="font-family: "Courier New", Courier, monospace;">l1</span> through <span style="font-family: "Courier New", Courier, monospace;">l3</span> are all set up with correct Ids and exits. My <span style="font-family: "Courier New", Courier, monospace;">retrievedLocation</span>, however, has the correct Id, but all exits are set to the default of -1.<br />
<br />
Looking at the actual database file, I see that the schema only has a column for the Id - but nothing for the exits. This is not actually all that surprising, when you think about it. I, for one, can't think of a good way to store an array in a database - and I guess the programmers behind Entity Framework couldn't either, so I consider myself in good company here. As a result, the array that holds the information about exits in my <span style="font-family: "Courier New", Courier, monospace;">Location</span> class simply gets ignored.<br />
<br />
I can see two ways around the problem: I can create individual integer fields for each allowable direction. This strikes me as a horrendous solution; it violates several OOD principles. If I ever needed more than, say, four directions, I would have to modify my <span style="font-family: "Courier New", Courier, monospace;">Locations</span> class to do so, which violates the open/closed principle. Furthermore, the number of directions really shouldn't be defined in the Location class - it belongs in a class that deals with navigation, according to the single responsibility principle. <br />
<br />
With the current solution, using an array, I could have worked around it by injecting the number of possible directions into the constructor. With individual integer fields, e.g. <span style="font-family: "Courier New", Courier, monospace;">int NorthExit</span>, <span style="font-family: "Courier New", Courier, monospace;">int SouthExit</span> etc. that would be impossible, so I'm not going to go there.<br />
<br />
Instead I'm going to use a new class that deals specifically with this problem:
<br /><br />
<script src="https://gist.github.com/FraukeN/76a21a178cf5d2102978.js"></script>
That means some major changes in my Location class, of course. Instead of an array of integers, I now have a List of Exits.
And, in case you're wondering why I have made that a private property instead of a private field - that's because Entity Framework needs a property to do its magic.<br />
<br /><script src="https://gist.github.com/FraukeN/02f0bb250c17aaaf09ec.js"></script>
Running my tests after these changes gives me several reds, of course, where I was testing things like invalid indices. With a list, the following tests that deal with array initialisation or an index that's out of bounds are no longer required:<br />
<ul>
<li><span style="font-family: "Courier New", Courier, monospace;">Location_is_constructed_with_all_exits_set_to_no_exit()</span></li>
<li><span style="font-family: "Courier New", Courier, monospace;">Location_returns_no_exit_if_direction_is_negative()</span></li>
<li><span style="font-family: "Courier New", Courier, monospace;">Location_returns_no_exit_if_direction_is_greater_than_available_directions()</span></li>
<li><span style="font-family: "Courier New", Courier, monospace;">CreateOneWayExitToLocation_throws_exception_if_direction_is_negative()</span></li>
<li><span style="font-family: "Courier New", Courier, monospace;">CreateOneWayExitToLocation_throws_exception_if_direction_is_greater_than_available_directions()</span></li>
</ul>
I do need to add one test instead, however, to check that if an exit doesn't exist in a specific direction, my <span style="font-family: "Courier New", Courier, monospace;">ExitInDirection()</span> method still returns -1.<br /><br />
<script src="https://gist.github.com/FraukeN/f62663577f2de03da98c.js"></script>
One necessary test, however, remains stubbornly red: The one I created at the beginning of this article. But now it's red for a different reason. If I examine the database after creating my locations, I can see that I now have a table for my exits, and that this table is populated correctly when I save the changes to my context. The problem is that when I retrieve a location from my context, it doesn't automatically retrieve the exits as well (even though it automatically stores them when I store the location)<br />
<br />
Getting around this is a little bit tricky in EF7, so I'll leave that until the next post.
<a href="http://anyurl.com/" rel="tag" style="display: none;">CodeProject</a>Anonymoushttp://www.blogger.com/profile/14091105723232979517noreply@blogger.com0tag:blogger.com,1999:blog-10721995.post-41983713897229831572015-12-24T11:52:00.000+00:002015-12-25T11:30:00.086+00:00An Exploration of TDD Part 2 - A Data Repository for the Location ClassNow that I've got my data context class set up, I need a repository for at least basic CRUD operations for my <span style="font-family: "Courier New", Courier, monospace;">Location</span> class. In order to test this, I create a new test project. In the UnitTestApp.xaml.cs file I add the following code to the constructor:<br /><br />
<script src="https://gist.github.com/FraukeN/eeba71a3429dba308f34.js"></script>
This is to apply any pending migrations before running any of the tests. <br />
<br />
Next, the beginning of my <span style="font-family: "Courier New", Courier, monospace;">LocationRepository</span> class:<br /><br />
<script src="https://gist.github.com/FraukeN/83ebf82eb8c1b3a5be85.js"></script>This simply returns null to give me my first red test.<br />
<br />
In my first test, I'll try to read from an empty table, so I have to clear all entries from it first. After all, I can't be sure that this test won't run after one that adds something to my <span style="font-family: "Courier New", Courier, monospace;">Locations</span> table.<br /><br />
<script src="https://gist.github.com/FraukeN/2fc12e10f15d74b2b3ad.js"></script>
Running the test gives me a red result, as I expected, so now I add the functionality I want to my <span style="font-family: "Courier New", Courier, monospace;">Get()</span> method:<br /><br />
<script src="https://gist.github.com/FraukeN/e51f79d19e0686160164.js"></script>
I run my test again and... Gadzooks! It's still red! Looking at the test results, I see the following message: "System.ObjectDisposedException: Cannot access a disposed object."<br />
<br />
Well, that's because I forgot that my LINQ query actually uses lazy evaluation, and by the time I get around to trying to use my result (in my test), my database context has already disposed of. So I do a quick fix on my Get() method to force the evaluation of my query while it's still in scope:<br /><br />
<script src="https://gist.github.com/FraukeN/ab2e5fcc52341789eafe.js"></script>
...and running this give me the first green test for my repository class. So there it is - the test did its job to point out my temporary lapse of memory. Good test. Have a biscuit.<br />
<br />
Now let's see how we fare with a table that's not empty:
<br /><br />
<script src="https://gist.github.com/FraukeN/8fa55a3a52bbd80530cf.js"></script>
This test returns green straight away. I have no idea how I could make it red. I guess I should have created it at the same time as the first test, since it tests the same method. Ah, well, live and learn...<br />
<br />
<i>P.S. Remember: this is NOT a tutorial on how to write good code. This is an exploration of how useful TDD is in weeding out mistakes, bad code and possibly bad architecture. So I'm throwing everything at it, including the kitchen sink.</i><br />
<i><br /></i>
<i>P.P.S. You may be able to see where this is going. I'm currently looking at the code I will be using over the next few posts, and I'm not certain if the wetness trickling down my face is tears or if my eyes are bleeding. </i><br />
<i><br /></i>
<i>P.P.P.S But hey - "For Science!"</i>
<a href="http://anyurl.com/" rel="tag" style="display: none;">CodeProject</a>Anonymoushttp://www.blogger.com/profile/14091105723232979517noreply@blogger.com0tag:blogger.com,1999:blog-10721995.post-30150068998165016272015-12-09T12:00:00.001+00:002015-12-16T22:59:02.052+00:00An Slight Detour From TDD in Favour of Entity Framework 7Now that I've created a class for my locations, I need a way to store them. Unfortunately Microsoft, for reasons I have yet to fathom, decided that the best way to store data for MS Store applications would be as XML or JSON text files.<br />
<br />
Looking at my fledgling project I can already see that there's a good chance that I'll need objects that will contain other objects, all of which need to be referenced to each other - in short, a classic database scenario. And while other platforms have embraced the lovely lightweight database framework that is SQLite... Microsoft hasn't. Quite.<br />
<br />
Looking at Nuget I can see more SQLite .NET wrappers than I can shake a stick at, which makes it very hard to decide which one to go with that will be around for the long term. However, there's another possibility. Remember that I said 'Quite' at the end of the previous paragraph? That's because Microsoft is going to offer SQLite support as part of Entity Framework 7 - but that is currently only available as a pre-release. Still, it seems like the best bet for now, and since I'm curious about it anyway, I'll take that route.<br />
<br />
To get started, I'll be perusing the (sparse) EF7 documentation at <a href="http://ef.readthedocs.org/en/latest/index.html">ef.readthedocs.org/en/latest/index.html</a>, but I'll do a quick recap here, for your enjoyment. I'm working with an Universal Windows project, so I<br />
<ul>
<li>Add the following application specific runtime directive to my Default.rd.xml file (found under the project properties): <span class="p"><</span><span class="n">Type</span> <span class="n">Name</span><span class="p">=</span><span class="s">"System.Collections.ArrayList"</span> <span class="n">Dynamic</span><span class="p">=</span><span class="s">"Required All"</span> <span class="p">/>. The documentation says that this will become unnecessary at a later point, but for now, in it goes.</span></li>
<li><span class="p">Install the NuGet packages for EntityFramework.SQLite and EntityFramework.Commands. both are pre-release, so make sure you use the -pre option or tick the box that allows you to search pre-release packages.</span></li>
</ul>
With the preliminaries out of the way I use EF7 to create my database context class:<br />
<br />
<script src="https://gist.github.com/FraukeN/e34d4c5d5fe7f0c98d68.js"></script>
I build my solution and use migrations to create my database by running <span style="font-family: "consolas";">
Add-Migration LocationMigration</span> in the package manager console to create my initial database. This actually required a bit of guesswork because my Location class is in a class library rather than my main app project, but after adding a reference to the library to my main app, the command worked fine.<br />
<br />
Now, I can't see much to test in my class itself, but I do want to test that I can do at least basic CRUD operations with my new data context. I don't think those tests can be classified as unit tests, but hey, they're going to be useful, so I'm gonna add them and worry about the semantics another time.<br />
<br />
Coming up: Testing CRUD operations
<a href="http://anyurl.com/" rel="tag" style="display: none;">CodeProject</a>Anonymoushttp://www.blogger.com/profile/14091105723232979517noreply@blogger.com0tag:blogger.com,1999:blog-10721995.post-54539327915629012902015-11-28T20:11:00.000+00:002015-12-05T17:04:03.454+00:00An Exploration of TDD Part 1I've been squinting at TDD as a development concept for a while now. I'm coming from a background where all you did was testing after the fact (if you were lucky and had a patient boss), and I remember the pain of extending or changing code in such an environment. So TDD looked like a great concept to me, and now I've decided to put it to the test.<br />
<br />
My plan is as follows: I'm going to create a project with only the vaguest of notions as to where it may be going, and see just how useful TDD is going to be in helping me create maintainable code. As an added obstacle I have to say that I don't know much about TDD other than the principle of red-green-refactor.<br />
<br />
So this exercise should be interesting.<br />
<br />
Here's the concept of the software I'm going to create: A piece of software that creates a world that a player can walk through and do stuff. How's <i>that</i> <i></i>for a fuzzy brief?<br />
<br />
If I'm going to have a world that a player can navigate, it stands to reason that I need locations, and that my locations have to connect to other locations. And in order for a player to get to other locations, each location needs exits, which shouldn't point anywhere before they've been assigned. I'll also need to be able to get and set the location that an exit leads to, and each location should have a unique ID, which can be assigned to an exit in another location.<br />
<br />
Here are the tests I've come up with:<br />
<br />
<script src="https://gist.github.com/FraukeN/e110efbed75b7e79481e.js"></script>
I'm not entirely sure about the second test because, strictly speaking, it tests two things at the same time (the constructor and the ExitInDirection method), but I don't want my method of storing exits to be public, so until I figure out how to access private variables in a unit test, this'll have to do.<br />
<br />
I implement the constructor and ExitInDirection method to return hard-coded values other than the expected test results in order to get my first reds, then flesh them out as follows, which gives me green tests:<br />
<br />
<script src="https://gist.github.com/FraukeN/eca7a0eec8026479c979.js"></script>
I don't think I want to keep the number of possible exits to be hard-coded in the Location class, but that's for later. For now I can't see any other tests that I could apply to the constructor, but the ExitInDirection method is another thing. I need to test that against a direction that's outside of the bounds of my array of exits.<br />
<br />
<script src="https://gist.github.com/FraukeN/717d8ff00055b7f1666d.js"></script>
With the current code, both those tests are red as they throw an out of bounds exception, so now I refactor to account for invalid directions:<br />
<br />
<script src="https://gist.github.com/FraukeN/96b92425240518cc17c9.js"></script>
And with that amendment, all my tests are now green. Looking good so far.<br />
<br />
Another thing I need is a method to determine where each exit direction leads to. But so far I can't set the location for an exit, so that's my next goal.<br />
<br />
First I'll create a method to link a location to an exit, which initially does nothing at all:<br />
<br />
<script src="https://gist.github.com/FraukeN/bab7b254f7458d14640e.js"></script>
And some tests to check whether an exit links to the correct location after it's been created:<br />
<br />
<script src="https://gist.github.com/FraukeN/e4bcdf48a35aab212e8f.js"></script>
Running this against the blank method gives me my initial red, so now I'm good to flesh out my SetExitToLocation method:<br />
<br />
<script src="https://gist.github.com/FraukeN/97e026024fba262ab1ce.js"></script>
At this point I have to ask myself again what should happen if the direction is outside of the bounds of the array. Right now I get an index out of bounds exception, which isn't all that bad, but I figure that an argument out of range exception would make more sense. So I add two more tests for that:<br />
<br />
<script src="https://gist.github.com/FraukeN/8667d96731d5ac98a045.js"></script>
This gives me another red test until I amend my SetExitToLocation method to<br />
<br />
<script src="https://gist.github.com/FraukeN/9b89987d690ab0b9cc67.js"></script>
And that has my whole range of tests green again, and completes my first draft for my location class.<br />
<br />
<i>P.S. Since I'm new to TDD, any constructive comments as to what could be improved in my process are very welcome.</i>
<a href="http://anyurl.com" rel="tag" style="display:none">CodeProject</a>
Anonymoushttp://www.blogger.com/profile/14091105723232979517noreply@blogger.com0