So the code is pretty straight forward, I have a PermissionChecker whose job is to use the IModuleDisabler to turn off certain modules depending upon the user permissions. Pretty straightforward implementation.
Now that the solution is fleshed out, it’s time to write some tests around this. When it comes to testing classes that have dependencies on non-trivial classes, I use NSubstitute, a mocking tool, to create mock versions of those dependencies. In this case, NSubstitute allows me to test how the IModuleDisabler is being used by the PermissionsChecker.
For example, let’s say that I wanted to test how the PermissionChecker interacts with the IModuleDisabler when the user has a partial access, I’d write a test that looks like the following:
In the above test, our assertion step is to check if the mockDisabler received a single call to the DisableReportModule. If it didn’t receive a call, then the test fails. We can write similar tests for the different modules that should be disabled for the partial rights permission and follow a similar pattern for the full rights permission.
However, things get a bit more interesting when we’re testing what happens if the user is an admin. If we follow the same pattern, we’d end up with a test that looks like this:
The issue arises when we add a new module to be disabled which forces the IModuleDisabler to implement a new method. In that case, you need to remember to update this test to also check that the new method wasn’t being called. If you forget, this test would still pass, but it’d pass for the wrong reason.
To help illustrate, let’s say that another method, DisableImportModule, has been added to the IModuleDisabler interface. In addition, we also need to make sure that this is called when users have partial access, but should not be called for users who are admins or users who have full access.
To fulfill those requirements, we modify the PermissionChecker as so:
At this point, we’d write another test for when the a user has partial access, the import module should be disabled. However, it’s very unlikely that we’d remember to update the test for the admin. Remember, for the admin, we’re checking that it received no calls to any disable methods and the way we’re doing that is by checking each method individually.
[Test]publicvoidAnd_the_user_has_admin_permissions_then_the_disabler_is_not_used(){// ArrangevarpermissionChecker=newPermissionChecker();varmockDisabler=Substitute.For();varuser=newUser{IsAdmin=true};// ActpermissionChecker.CheckPermissions(mockDisabler,user);// AssertmockDisabler.DidNotReceive().DisableSystemAdminModule();mockDisabler.DidNotReceive().DisableReportModule();mockDisabler.DidNotReceive().DisableUserManagementModule();// Need to add check for DidNotReceive().DisableImportModule();}
There’s got to be a better way. After some digging around, I found that any NSubstitute mock, has a ReceivedCalls method that returns all calls that the mock received. With this new knowledge, we can refactor the previous test with the following:
This solution is much better because if we add more modules, this test is still checking to make sure that admin users do not have any modules disabled.
When using a NSubstitute mock and you need to make sure that it received no calls to any methods or properties, you can using NSubstitute’s ReceivedCalls in conjunction with CollectionAssert.IsEmpty to ensure that the substitute was not called.
In this post, I’m going to solve a logic puzzle using C# and F#. First, I’ll define the problem being solved and what our restrictions are. Next, I’ll show how I’d break down the problem and write an easy-to-read, extendable solution using idiomatic C#. Afterwards, I’ll solve the same problem and write an easy-to-read, extendable solution writing in idiomatic F#. Finally, we’ll compare the two solutions and see why the F# solution is the better solution.
For this problem, I’m going to write a constraint solver (thanks to Geoff Mazeroff for the inspiration).
If you’re not familiar with the concept, a constraint is simply some rule that must be followed (such as all numbers must start with a 4). So a constraint solver is something that takes all the constraints and a source of inputs and returns all values that fit all the constraints.
With that being said, our source will be a list of positive integers and our constraints are the following:
4 digits long (so 1000 – 9999)
Must be even (so 1000, 1002, 1004, etc…)
The first digit must match the last digit (2002, 2012, 2022, etc…)
To further restrict solutions, all code will be production ready. This includes handling error conditions (like input being null), being maintainable (easily adding more constraints) and easy to read.
To quickly summarize, we need to find a robust, maintainable, and readable solution to help us find all 4 digit number that are even and that the first and last digit are equal.
For the C# solution, I’m going to need a class for every constraint, a class to execute all constraints against a source (positive integers) and a runner that ties all the pieces together.
Starting with the smaller blocks and building up, I’m going to start with the constraint classes. Each constraint is going to take a single number and will return true if the number follows the constraint, false otherwise.
With that being said, I’d first implement the constraint that all numbers must be 4 digits long
At this point, I have the constraints written, but I need them to follow a general contract so that the Constraint Solver (about to be defined) can take a list of these constraints. I’ll introduce an interface, IConstraint and update my classes to implement that interface.
So now I have the constraints defined and they’re now implementing a uniform interface, I can now create the constraint solver. This class is responsible for taking the list of numbers and the list of constraints and then returning a list of numbers that follow all constraints.
This solution is easily extendable because if we need to add another constraint, we just add another class that implements the IConstraint interface and change the Main method to add an instance of the new constraint to the list of constraints.
Now that we have the C# solution, let’s take a look at how I would solve the problem using F#.
Similar to the C# solution, I’m going to create a function for every constraint, a function to execute all constraints against a source (positive integers) and a runner that ties all the pieces together.
Also similar to the C# solution, I’m going to start with creating the constraints and then work on the constraint solver function.
First, I’d implement that the number must be four digits long constraint.
At this stage in the C# solution, I had to create an interface, IConstraint, so that the constraint solver could take a list of constraints. What’s cool with F# is that I don’t have to define the interface. The F# type inference is saying that each of these functions are taking the same input (some generic `a) and returning a bool, so I can add all of them to the list. This is pretty convenient since I don’t have to worry about this piece of plumbing.
Now that the different constraints are defined, I’d go ahead and write the last function that takes a list of constraints and a list of numbers and returns the numbers that the constraints fit. (Confused by this function? Take a look at Implementing your own version of # List.Filter)
Now that we have both solutions written up, let’s compare and see which solution is better.
First, the same design was used for both solutions. I decided to use this design for both because it’s flexible enough that we could add new constraints if needed (such as, the 2nd digit must be odd). As an example, for the C# solution, I’d create a new class that implemented IConstraint and then update the runner to use the new class. For the F# solution, I’d create a new function and update the runner. So, I’d think it’s safe to say that both solutions score about the same from a maintainability and extendability point of view.
From an implementation perspective, both solutions are production ready since the code handles possible error conditions (C# with null checks in the ConstraintSolver class, F# with none because it doesn’t support null). In addition to being robust, both solutions are readable by using ample whitespace and having all variables, classes, and interfaces clearly described.
With that being said, this is where the similarities end. When we look at how much code was written to solve the problem, we have a stark difference. For the C# solution, I ended up with 48 lines of code (omitting blank lines), however, for the F# solution, it only took 19. Now you could argue that I could have written the C# solution in fewer lines of code by removing curly braces around one line statements or ignoring null inputs. However, this would lead the code to be less robust.
Another difference between the F# solution and C# is that I was able to focus on the solution without having to wire up an interface. You’ll often hear developers talk about the how little plumbing you need for F# to “just work” and this small example demonstrates that point.
Another difference (albeit subtle) is that the F# solution is that I can use the findValidNumbers function with any generic list of values and any generic list of functions that take the generic type and return true/false.
In other words, if I had another constraint problem using strings, I’d still implement the different constraints, but I could use the same findValidNumbers function. At that point, however, I’d probably rename it to findValidValues to signify the generic solution.
What’s awesome about this is that I didn’t have to do any more work to have a generic solution, F# did that for me. To be fair, the C# solution can easily be made generic, but that would have to be a conscious design decision and I think that’s a downside.
In this post, we took a look at solving a number constraint problem by using idiomatic C# and F#. Even though both solutions are easy to read and easy to extend, the F# version was less than 1/2 the size of the C# solution. In addition, I didn’t have to do any plumbing for the F# version, but had to do some for the C# solution, and to top it off, the F# solution is generically solved, whereas the C# solution is not.
As I’ve been thinking more about F#, I began to wonder how certain methods in the F# stack work, so I decided to implement F#’s List.filter method.
For those of you who aren’t familiar, List.Filter takes a function that returns true or false and a list of values. The result of the call is all values that fulfill the fuction.
For example, if we wanted to keep just the even numbers in our list, then the following would accomplish that goal.
Now that we have the signature, let’s add some logic to match on the list of values. When working with lists, there are two possibilities, an empty list and a non-empty list. Let’s first explore the empty list option.
In the case of an empty list of values, then it doesn’t matter what the func parameter does, there are no possible results, so we should return an empty list for the result.
Now that we’ve handled the empty list, let’s explore the non-empty list scenario. In this branch, the list must have a head and a tail, so we can deconstruct the list to follow that pattern.
letfilter(func:int->bool)(values:intList)=matchvalueswith|[]->[]|head::tail->// what goes here?
Now that we’ve deconstructed the list, we can now use the func parameter with the head element. If the value satisfies the func parameter, then we want to add the head element to the list of results and continue processing the rest of the list. To do that, we can use recursion to call back into filter with the same func parameter and the rest of the list:
At this point, we need to handle the case where the head element does not satisfy the func parameter. In this case, we should not add the element to the list of results and we should let filter continue the work
By handling the base case first (an empty list), filter can focus on the current element in the list (head) and then recurse to process the rest of the list. This solution works, but we can make this better by removing the type annotations. Interestingly enough, we don’t care if we’re working with integers, strings, or whatever. Just as long as the function takes some type and returns bool and the list of values matches the same type as the func parameter, it works. So then we end up with the following:
In general, when working with lists, I tend to start by matching the list with either an empty list or non-empty. From there, I’ve got my base case, so I can focus on the implementation for the first element. After performing the work for the first element, I can then recurse to the next element.
There is nothing new in the world except the history you do not know.
– Harry S. Truman
The more experience I gain problem solving, the more this holds true. For this post, I’m going to first discuss the problem that I was trying to solve. Next, I’ll show what my first solution was, followed by the shortcomings of this solution. Thirdly, we’ll iterate over a better solution to the problem. This in turn, will provide the motivation for what the Chain of Responsibility is and how to implement. Finally, I’ll wrap up with what the benefits were of using this design. .
As part of the process of installing our software, there are scripts that will update the database from it’s current version to the latest version. As it stands, it needs to be able to upgrade a database from any version to the current version.
The first thing that comes to me is that I need to apply database scripts in a sequential way. For example, if the database’s current version is 1.0 and the latest version is 3.0, it would need to apply the script to upgrade the database from 1.0 to 2.0 and then apply the script to upgrade the database from 2.0 to 3.0.
For the first implementation, there were only two versions, 1.0 and 2.0. Since I didn’t want to build in a lot of functionality if it wasn’t needed yet, I created a helper method that returns the correct updater for a given version. In the below code, if the version does not exist, I assume the database does not exist and return the class that will create the database. Otherwise if the version is 1.0, I return a class that is responsible for the upgrading a database from 1.0 to 2.0. If the version is 2.0, I return a class that doesn’t do anything (i.e. there’s no upgrades to be done).
publicIDatabaseUpdaterGetDatabaseUpdater(stringversion){if(string.IsNullOrWhiteSpace(version))returnnewDatabaseCreator();if(version=="1.0")returnnewDatabase100To200Updater();if(version=="2.0")returnnewCurrentVersionUpdater();thrownewArgumentException("The version "+version+" is not supported for database upgrades.");}
This solution worked well when there only three possible actions (create a new database, apply the single script, or do nothing). However, we are now going to be shipping version 3.0 and there will need to be a new class that is responsible for upgrading the 2.0 to 3.0. In order to add this functionality, I’d have to do the following:
Create the Database200To300Updater class that contained the logic for updating the database from 2.0 to 3.0.
Modify the Database100To200Updater class to also use the Database200To300Updater in order to perform the next part of the upgrade.
Add additional logic to the above method so that if the database is 2.0 to return the Database200To300Updater class.
After making the modifications, the method now looks like:
publicIDatabaseUpdaterGetDatabaseUpdater(stringversion){if(string.IsNullOrWhiteSpace(version))returnnewDatabaseCreator();if(version=="1.0")returnnewDatabase100To200Updater(newDatabase200To300Updater());if(version=="2.0")returnnewDatabase200To300Updater();if(version=="3.0")returnnewCurrentVersionUpdater();thrownewArgumentException("The version "+version+" is not supported for database upgrades.");}
So far, so good, we now have the logic to be able to apply scripts in order, however, now that we’ve added version 3.0, I start to wonder what I would do if we added more versions? After some thought, it would look identical to the previous steps (see below for what would happen if we added version 4.0).
publicIDatabaseUpdaterGetDatabaseUpdater(stringversion){if(string.IsNullOrWhiteSpace(version))returnnewDatabaseCreator();if(version=="1.0")returnnewDatabase100To200Updater(newDatabase200To300Updater(newDatabase300To400Updater()));if(version=="2.0")returnnewDatabase200To300Updater(newDatabase300To400Updater());if(version=="3.0")returnnewDatabase300To400Updater();if(version=="4.0")returnnewCurrentVersionUpdater();thrownewArgumentException("The version "+version+" is not supported for database upgrades.");}
If we create some variables to hold onto these classes, and reorder the if statements, we can write this helper method as:
publicIDatabaseUpdaterGetDatabaseUpdater(stringversion){if(string.IsNullOrWhiteSpace(version))returnnewDatabaseCreator();if(version=="4.0")returnnewCurrentVersionUpdater();vardatabase300Updater=newDatabase300To400Updater();vardatabase200Updater=newDatabase200To300Updater(database300To400Updater);vardatabase100Updater=newDatabase100To200Updater(database200To300Updater);if(version=="1.0")returndatabase100Updater;if(version=="2.0")returnnewdatabase200Updater;if(version=="3.0")returnnewdatabase300Updater;thrownewArgumentException("The version "+version+" is not supported for database upgrades.");}
What I find interesting in this design is that I’ve now chained these updater classes together so that if the version 1.0 is returned, it will also use the 2.0 updater, which in turn calls the 3.0 updater. It was at this point, that I remembered a design pattern that followed this structure.
In this design pattern, you essentially have Handlers (in my case updaters) that check to see if they can handle the request. If so, they do and that stops the chain. However, if they can’t handle the request, they pass it to their Successor (which was also a Handler) to handle the request. The design pattern I was thinking about is the Chain of Responsibility pattern.
In order to implement this pattern, you need to have an IHandler interface that exposes a Handle method and either a method or property to set the Successor. The method is the action to take (in our case Update) and the Successor represents the next Handler in the chain if the request could not be handled. The second component is referred to as ConcreteHandlers and they are just the implementors of the interface. One way to implement this is like the following:
publicinterfaceIHandler{IHandlerSuccessor{get;set;}voidUpdate(intversion);}publicclassConcreteHandlerA:IHandler{publicIHandlerSuccessor{get;set;}publicvoidUpdate(intversion){if(CanTheRequestBeHandled){// handle the request}else{Successor.Update(version);}}}
The main difference between the pattern and what I need is that instead of doing if (canHandle)/else call Successor, what I’m really looking for is to run the upgrade script if the version we’re upgrading to is higher than our current version and then always call the successor. Given this change, here’s what that new implementation looks like:
publicclassConcreteHandlerA:IHandler{publicSuccessor{get;set;}publicvoidUpdate(intversion){if(CanTheRequestBeHandled){// handle the request}Successor.Update(version);}}
Now that I know the pattern to use and how it works, I need to update the IDatabaseUpdater interface to follow the IHandler interface. Next, I will need to modify the concrete handlers to use the new interface correctly.
Second, we will need to update our concrete handlers to implement the interface correctly and to update their UpdateMethod to follow the design. In my case, the concrete handlers perform similar logic, so one of the classes is used for an example.
publicclassDatabase100To200Updater:IDatabaseUpdater{privateDatabase200To300Updater_successor;publicDatabase100To200Updater(Database200To300Updatersuccessor){if(successor==null)thrownewArgumentNullException("successor");_successor=successor;}publicvoidUpdate(){Console.WriteLine("Updating the database to version 2.0");_successor.Update();}}
publicclassDatabase100To200Updater:IDatabaseUpdateHandler{publicvoidUpdate(intversion){if(version>=2)Console.WriteLine("Updating the database to version 2.0");if(Successor!=null)Successor.Update(version);}publicIDatabaseUpdateHandlerSuccessor{get;set;}}
What I really like about the chain of responsibility pattern is that I was able to connect my upgrade classes together in a consistent fashion. Another reason why I like this pattern is that it forces me to have the logic to determine whether I should run the update or not inside the individual classes instead of the helper method. This produces more readable code which then lends itself to easier maintainability.