Skip to content

PeeDeeWhite/CameraHeadTest

Repository files navigation

This is a solution I wrote for an interview for a contract in 2018.

The project included a .dll and a brief to write a simple WPF solution to demonstrate moving a test robotic camera head. The .dll contained some classes and interfaces for a simulated robotic camera head and a studio class to control it. I decompiled the code and developed a better version which you find here. And yes I did get the job.

This was originally a .NET 4 solution but I recently upgraded it to .NET 8 to add to GitHub as example of my work. Below is the original Readme I added to the project. As part of the migration to .NET 8 I used xUnit rather than MSTest as mentioned in the original readme.

Vitec Camera Head Test Utility

Interview Test Project

Overview

This document is provided as an explanation and guide to the design and implementation decisions I took when working on this project.

Solution Structure and Naming Conventions

Over the years I have worked on a number of projects with long life spans and I have come to appreciate the value of well structured and well named classes and members. I read Clean Code by Robert C. Martin (Uncle Bob) some years ago and it echoed many of my own conventions and introduced me to some new ones. As a result, I created a new solution rather than editing the Interview1 one I downloaded. The new solution demonstrates many of my conventions. For example, the use of fully qualified namespaces for project names and separate Model and Unit Test projects within the solution. I use Resharper to ensure code consistency in terms of class and member naming conventions. One of the consequences of this was that I had to re-implement the Robot class in the Simulator assembly to make it public so that I could reference it from my separate unit test project. This required decompiling the simulator assembly. Once I had done this it offered the opportunity to rename the IRobot interface. I felt the interface name was not specific or descriptive enough. I have called it ICameraHead. I feel this is good compromise between descriptiveness and verbosity. IRoboticCameraHead or IPanTiltCameraHead being alternatives I considered. Obviously in a real-world scenario we don’t always have this luxury. Once I renamed the interface a few other types benefited from a consistent approach and with Resharper’s refactoring tools this was easily achieved.

Camera Head Models

When I was initially looking at the requirements and the provided solution, I had not noticed the Simulator assembly, so I began writing my own concrete implementation of the IRobot (ICameraHead) interface. The first things that occurred to me that there was nothing in the interface for velocity of the camera head or the limits of it pan and tilt. I looked up the FHR-35 head shown in the document which described the requirements and got the specification which allowed me to continue building my implementation. I saw that there were other camera heads on the web site, specifically the heavy payload FHR-155. At this point I decided it would be good to have a base implementation and derive from it so I could have different models with different velocities and ranges of motion. I started looking at what was needed for the Studio class and realised that there was an implementation in the Simulator assembly and that there was a Robot class. Decompiling these classes was useful and allowed me to see some of the calculations used in the simulated movement and raising events. I discovered the use of an ElapsedEventHandler on a system Timer. However, I wanted to implement a Task based solution for my camera heads. This is complicated by the interface using a void instead of a Task for the SetPosition method. My implementation could use an async void method if I was careful about my use of the synchronization context and made sure I didn’t block the UI thread. As I had a different implementation of the SetPosition this was an ideal opportunity to write some unit tests to allow me to prototype my implementation. I added range checking for the pan and tilt which again was built with a TDD approach. I also allowed for different Pan and Tilt velocities although my examples used the same amounts for the Pan and Tilt. The Camera Head decompiled from the Simulator assembly would not work with my Camera head View model. I had to add a switch to my configuration which could wrap the call to SetPosition method in an asynchronous task.

WPF User Interface

To keep the solution simple, I did not use a framework such Prism or Caliburn.Micro. However, I did create a simple view model locator and used convention to wire the view models up with their views. In a larger project I would use a framework. As there are so few views and user controls, I have not created any folders for the views and viewmodels. I tend to use a folder per feature structure with views and viewmodels together, as opposed to a type per folder structure as common in MVC solutions. I find keeping the views and their viewmodels together easier to work with and it is one of the main reason Asp.Net Core has introduced Razor Pages. There is no code for dealing with unhandled exceptions which given more time I would have added.

Configuration

From working on .NET core solutions I have used the new configuration extensions. I have implemented these in the WPF project to load the configuration data for the Studio class as an alternative to old cumbersome XML config files.

Unit Tests

For simplicity I have just used the MS Test framework rather than nUnit or xUnit. For .NET Core projects xUnit is the preferred option and the one I have used most recently. The tests are written using the Fluent Assertions NuGet package which provides fluent and more readable style to the unit tests. The tests often include several progressive assertions which test with more and more granularity the conditions that need to be met to pass. The usual view is that tests should not have multiple assertions but this really should be that multiple conditions or cases are not tested within a single test. For example, in the tests I have written that check a collection has at least one valid entry in it, I check the collection is not null, then not empty, it contains the correct number of items and then finally the first item contains an expected value. If I had used xUnit I would have written the DistanceTo tests using data driven Theory tests.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages