To begin our little project, we need to create our initial project structure. Once that’s in place, we can create the first class from our application model - VocabularyWord
.
Project Creation
It’s frequently the case that a project directory accumulates addition stuff above and beyond the actual source code itself. For this reason, it’s my custom to carefully curate the folder structure of any project, so that things start off tidy and stay that way as the project evolves.
For this project, I’m starting with two subfolders underneath the main project folder:
The src
folder is for all the projects that make up deliverable components of our application. In this case, we’re starting with just a single project WordTutor.Core
.
The tests
folder is for all our test projects, keeping the tests nicely segregated. You can see here the WordTutor.Core.Tests
project, which will contain all the unit tests for the Wordtutor.Core
project.
BTW, the .vs
folder is a working folder for Visual Studio Code, and the .git
folder contains our git repository. Both can be ignored.
One thing I’m really appreciating with .NET Core is the new project structure - all of the repetition and boilerplate from the old .csproj
files has gone. Check it out - here’s the entire file for WordTutor.Core.csproj
:
Here, we’re targetting .NET Standard 2.0 for maximum compatibility. Good practice is to target .NET Standard where possible - and the lower the standard you use, the wider the potential for reuse. Though, this is because lower versions are more restrictive, so it’s a balancing act.
The project file for WordTutor.Core.Tests.csproj
is a litte more complex, due to project and package references, but it is still far easier to read than the older style:
This time, the project targets an actual runtime, necessary for execution of the unit tests.
Neither project explicitly references any .cs
source files - inclusion is now automatic, with a couple of benefits: there is a reduced chance for conflicts when adding additional source files, and this also encourages a tidy codebase where extraneous source files (debris left over from earlier efforts) is cleaned up as it’s made.
Modelling a single word
To encapsulate each individual spelling word, we have the immutable class VocabularlyWord
. Here’s an abridged view of the important details:
We begin with the essential properties for the word - how to spell it correctly, how to say it correctly (because sometimes a speech engine doesn’t say things the way we expect), and a sample phrase to give the word in context.
For simplicity, we initialize a word with just a spelling and then we have some transformation methods that each return a new instance with the required change. This is a little bit wasteful, creating heap debris, but we’re looking at an interactive application here, not a server, so the simplicty of design likely worth the performance cost.
The key that makes these transformation methods work is a private constructor that allows creating of a near-clone of an existing word:
Each parameter has a null default, and if not provided, the matching property from original
is used instead. This is possibly because null isn’t a permitted value for any of the properties.
There’s nothing particularly novel about the implementations of Equals()
and GetHashCode()
, but they’re included for completeness:
The testing of VocabularyWord
is pretty straightforward, so I’ll leave it to you to check out the code for yourself.
Next time
In the next post, we’ll look at collecting many words together into a VocabularySet
and explore how to transform an immutable collection.
Comments
blog comments powered by Disqus