Improved Validation for Universal Windows Apps

I wrote a couple weeks back on my attempt to re-write the ValidatableBase class I wrote for Universal Windows Apps. The original idea was great, but in practice it turned out to be a headache. Writing a method per property (in some cases more than one!) really bloated the code and made it difficult to read. So I set out to tackle this in a different way.

To demonstrate the improvements, I want to first revisit how the previous version worked. The following is a simple User model that would perform validation on a user name and password with the old ValidatableBase.

public class User : ValidatableBase
{
    private string email = string.Empty;

    private string password = string.Empty;

    public User()
    {
        this.RegisterProperty("Email", "Password");
    }

    public string Email
    {
        get 
        {
            return this.email;
        }
        set 
        { 
            this.email = value;
            this.OnPropertyChanged("Email");
        }
    }

    public string Password
    {
        get 
        { 
            return this.password; 
        }
        set 
        { 
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

    public override void Validate()
    {
        this.ValidateProperty(this.ValidateEmailIsNotEmpty, "Invalid Email Address.", "Email");
        this.ValidateProperty(this.ValidateEmailIsFormatted, "Email Address is not in the correct format.", "Email");
        this.ValidateProperty(this.ValidatePasswordIsNotEmpty, "Password can not be empty.", "Password");
        this.ValidateProperty(this.ValidatePasswordIsToShort, "Password must be greater than 8 characters.", "Password");
        this.ValidateProperty(this.ValidateIfPasswordContainsSpaces, "Password must not contain spaces.", "Password");

        base.Validate();
    }

    private IValidationMessage ValidateEmailIsNotEmpty(string failureMessage)
    {
        if (string.IsNullOrEmpty(this.Email))
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }

    private IValidationMessage ValidateEmailIsFormatted(string failureMessage)
    {
        string[] addressParts = this.Email.Split('@');

        if (addressParts.Length < 2)
        {
            var msg = new ValidationErrorMessage(failureMessage);
            return msg;
        }

        string[] domainPiece = addressParts.LastOrDefault().Split('.');
        if (domainPiece.Length < 2)
        {
            var msg = new ValidationErrorMessage(failureMessage);
            return msg;
        }

        return null;
    }

    private IValidationMessage ValidatePasswordIsNotEmpty(string failureMessage)
    {
        if (string.IsNullOrEmpty(this.Password))
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }

    private IValidationMessage ValidatePasswordIsToShort(string failureMessage)
    {
        if (this.Password.Length < 8)
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }

    private IValidationMessage ValidateIfPasswordContainsSpaces(string failureMessage)
    {
        if (this.Password.Contains(' '))
        {
            return new ValidationErrorMessage(failureMessage);
        }

        return null;
    }
}

As you can see, I had to write a single method for each different type of validation I wanted to perform. In this case, as shown in the Validate() method, I have 5 different methods to validate 2 properties. Imaging a more complex model? This quickly turned in to a messy model.

The solution

I heavily modified the ValidatableBase class and its interface initially, but ultimately ended up being able to keep it mostly unchanged and just add on to it. The validation via method delegates certainly has a place, and I didn't want to loose that. The goal this time-around however was to make delegates the last choice instead of the first choice.

The class now supports attribute based validation, very much like Microsoft's DataAnnotation. Since Data Annotations are not supported in Universal Apps, I set out to build my own version, which actually ended up being a bit different with some nifty features.

Let's take the User class, and re-write it to use the new validation scheme.

public class User : ValidatableBase
{

    private string email = string.Empty;

    private string password = string.Empty;

    [ValidateValueIsNotNull(FailureMessage = "E-Mail can not be left blank.", ValidationMessageType = typeof(ErrorMessage))]
    [ValidateWithCustomHandler(DelegateName = "ValidateEmailFormat")]
    public string Email
    {
        get
        {
            return this.email;
        }

        set
        {
            this.email = value;
            this.OnPropertyChanged("Email");
        }
    }

    [ValidateStringIsGreaterThan(GreaterThanValue = 6, FailureMessage = "Password must be greater than 6 characters.", ValidationMessageType = typeof(ErrorMessage))]
    [ValidateStringIsLessThan(LessThanValue = 20, FailureMessage = "Password must be less than 20 characters.", ValidationMessageType = typeof(ErrorMessage))]
    public string Password
    {
        get
        {
            return this.password;
        }

        set
        {
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

    [ValidationCustomHandlerDelegate(DelegateName = "ValidateEmailFormat")]
    private bool ValidateEmailIsFormatted(IMessage failureMessage)
    {
        string[] addressParts = this.Email.Split('@');

        if (addressParts.Length < 2)
        {
            return false;
        }

        string[] domainPiece = addressParts.LastOrDefault().Split('.');
        if (domainPiece.Length < 2)
        {
            return false;
        }

        return true;
    }
}

Now we are down to just a single method that performs validation. The Email property has two validation attributes, a ValidateValueIsNotNull and a ValidateWithCustomHandler attribute. The value is not null attribute is self explanatory, it just ensures the value isn't null and progresses. The ValidateWithCustomHandler allows you to specify a delegate name that you want th validator to use when performing validation. You'll notice that there no longer needs to be a method within the model called Validate() as this is part of the base class and handles invoking all of the validation attributes, and their custom handlers if they exist.

We use validation on the Password property as well, by ensuring it meets the minimum and maximum length requirements we define.

A really cool feature of this, is the ability to perform validation based on other property values. For instance, let's assume that validation for the Password can only fire when the Email property has a value set. If that is the case, then we just modify the Password attributes to specify that the Email property must be valid in order for our validation to fire.

    [ValidateStringIsGreaterThan(GreaterThanValue = 6, ValidateIfMemberValueIsValid = "Email",  FailureMessage = "Password must be greater than 6 characters.", ValidationMessageType = typeof(ErrorMessage))]
    [ValidateStringIsLessThan(LessThanValue = 20, ValidateIfMemberValueIsValid = "Email", FailureMessage = "Password must be less than 20 characters.", ValidationMessageType = typeof(ErrorMessage))]
    public string Password
    {
        get
        {
            return this.password;
        }

        set
        {
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

As you can see here, by setting the ValidateIfMemberValueIsValid, the validation will only get fired if the Email property is not empty or null. What if we wanted to have validation fire only if the Email property was empty? We can do that be prepending an exclamation mark in from of the string representation of the Email property.

ValidateIfMemberValueIsValid = "!Email"

This works with boolean values by checking if it is true or false, floats, doubles, ints, longs, shorts and decimals by checking if they are zero or not along with empty strings and null objects.

Finally, the method delegate feature still exists, and can be used by external objects to enforce additional validation on the model. Let's use a view model as an example. Assume the view model has a PasswordConfirmation property, that must equal the users Password before user creation validation is considered acceptable. We can do the following in our view model, within a CreateUser method or an ICommand.Execute method.

    public void Execute(object parameter)
    {
        // Perform validation on the user's built in validation.
        this.AppUser.ValidateAll();

        // Piggy-back on top of the user default validation with an additional level of validation in our view model.
        // We ensure the password and password confirmation matches.
        this.AppUser.ValidateProperty(
            () => PasswordConfirmation.Equals(this.AppUser.Password),
            new ErrorMessage("Passwords do not match!"),
                "Password");

        // Check if there are any errors.
        if (this.AppUser.HasValidationMessages<ErrorMessage data-preserve-html-node="true">())
        {
            return;
        }

        // Do stuff.
        return;
    }

Here, we fire the user validation off, then we piggy-back on it by creating our own validation via an anonymous method, and assigning it to the "Password" property of the user. If validation fails, it will be added to the Users validation message collection. We then check if the user has any validation error messages. If they do, we abort the user creation.

The API still has a bit of tightening up to do before I can upload it, but it should be ready before the end of the week on GitHub. It's taken a bit of time due to ensuring that what I end up here can run properly. I managed to wire it up in to the latest build of the Mud Designer engine tonight which will really help with development.

Building an app targeting desktops & mobile

The Mud Designer is currently being developed to support a wide range of operating systems.

  1. Desktops
    1. Windows 7
    2. Windows 8
    3. Windows 8.1
    4. OS X
  2. Mobile
    1. WinRT 8
    2. WinRT 8.1
    3. Windows Phone 8
    4. Windows Phone 8.1
    5. iOS
    6. Android

To facility this, the engine at the lowest level will be wrote using Portable Class Libraries (PCL) so that I can target all of the operating systems with the same low-level codebase. The engine itself will be developed fairly abstractly, implementing a series of patterns that will help facilitate this requirement, with the bulk of the components hidden behind interfaces.

At the moment the engine is broken up in to 4 layers. From the highest layer to the lowest layer, the following provides an idea of what the overall acrchitectural layout looks like.

  1. App
  2. Engine
  3. Data Access
  4. Services

Each layer is broken down further, to facilitate the level of abstraction needed to provide cross-platform support.

App

The App layer looks like this

  1. Universal App
    1. Windows Phone
    2. WindowsRT
    3. Shared
    4. Presentation
  2. Windows
    1. Desktop
    2. Modules
    3. Infrastructure

As you can see, the mobile apps will be wrote within the Universal App layer while the Windows Desktop apps will be wrote under the Windows layer. Each will be able to target a version of the engine (and it's repositories and services) that is designed specifically for that platform.

I really want to avoid using #if WinRT #elif Win7 #endif kind of macros through-out the engine, as that makes maintaining it difficult and doesn't provide the level of support I want to provide for 3rd party developers. Since the engine will fully support engine and editor plugins, it needs to be modular and flexible enough to allow other developers to target a specific device or platform if they want, without having to rely on macro's.

For instance, the core project contains an IGame interface that exposes the following contract.

/// < summary>
/// Gets or Sets the current World for the game. Contains all of the Realms, Zones and Rooms.
/// < /summary>
ICollection< IWorld> Worlds { get; set; }

Since Universal Apps don't support ObservableCollections in the same manor that WPF Desktop apps do, I can implement the IGame in a Desktop library like this.

/// < summary>
/// Gets or Sets the current World for the game. Contains all of the Realms, Zones and Rooms.
/// < /summary>
public ObservableCollection< IWorld> Worlds { get; set; }

This still satisfies the interface's contract, yet provides support for WPF XAML's binding engine. Ideally, I will be able to build an abstract implementation of IGame in the Core engine, and then have the individual platforms inherit and override/implement the specific components that apply to them.

While the solution is still being organized and structured, this is the initial look of how the over-all application suite will be set up.

Using NDepend to analyze Mud Designer Alpha

Why analyze?

Since the latest build of the Mud Designer re-write isn't ready to ship yet, I thought I'd go back and run a code analyizer against the original Mud Designer Alpha, so that I can compare the quality of the old engine to the new (once it is ready). The goal of the re-write was to improve the code base and make it more abstract and not as tightly coupled.

I was provided a copy of the NDepend toolchain and used it to run the first report against the Alpha version of the Mud Designer and thought I'd share the results of it.

The stats

After the analysis was completed, it provided me with some basic stats.

  1. The project contained 3,852 lines of code, of which 47% was commented. Pretty good coverage, almost to much. Half of my code base shouldn't be covered in comments if the code was wrote clearly. The project
  2. The project contained 152 Types across 5 assemblies with 1,091 methods.
  3. I did not have any rules with errors, but ended up with 61 rule violations in total. I'm not sure if that is a significant number for the number of lines/methods/types the project has or if it is minor.

The violations

I had two violations for Types being to large and one for a method that was to complex. These two violations were anticipated before hand, since all three of them take place in the WinForms code-behind. Code-behind on a WinForms project tend to be ugly and cumbersome, so this was expected. It's also a large part of why I chose to build the next version in WPF with the MVVM pattern.

The report also told me that I had a total of 8 methods that needed to be refactored. With 4 of them being engine methods and 4 of them being WinForms project methods. Once again, the amount of code in violation within the engine was minor next to the WinForm project. The WinForm project just over double the number of IL instructions (117 vs 242) than the rest of the engine.

Something that I had not expected was that I had 9 Types with to many methods. With all but one of those Types living within the Engine assemblies. The bulk of the bloated Types lived under the GameObjects namespace, which was responsible for all of the player, item, world and npc code. Reviewing the code and the analysis showed that the objects could really use a good refactor. Something that I was already planning on the next version of the application. The BaseMob Type contained 81 methods by itself. It made me cringe and not want to even go back and look at the source.

I'm not going to go over every rule violation that took place in this report with this post, but there are a few interesting things to point out.

The report showed that I had a problem with cohesive methods, potential issues due to invoking virtual members within my constructors and that I was not properly disposing of Types that implemented the IDisposable interface. I'm really anxious to get the dust to settle on the new version of the Mud Engine source so that I can run the tool against it. I am planning on a series of posts as I build out the new engine and run the analysis tool against it. The goal of the series would be to demonstrate rule violations and how to address and fix them.

There's really no question that using NDepend will help make my code base much better. It is fairly complex at first when you go to use it, but their documentation seems pretty good. Using their documentation with the analysis and a bit of googling, you can quickly pick up what patterns can be applied through-out your app. It's really nice.

Stay tuned for additional posts coming soon.

ValidatableBase: Back to the drawing board

A couple of weeks ago I posted about my new ValidatableBase object I put on GitHub. It worked pretty good for Windows Universal Apps and I'm enjoying it's simplicity.

I ran in to some drawbacks when using it with WPF however. In WPF, most projects use either IDataErrorInfo or INotifyDataErrorInfo. Neither of these two interfaces worked for the business requirements I have. Neither interface make it really easy to break up your validation errors in to categories. What if want to perform validation and have it come back with a warning instead of an error? You can't do that with IDataErrorInfo and while you can do it using INotifyDataErrorInfo, it requires a decent chunk of plumbing to expose and doesn't make sense semantically. To get all errors, warnings and information messages, you access the GetErrors method or HasErrors property. It makes things confusing when building a framework and you want others to access warnings and informative messages from the model. "Just grab the warnings from the GetErrors method". Huh?

So I thought I'd just move over and ValidatableBase in WPF. The problem that I ran in to with it is that it was not easy to quickly re-evaluate a properties failed validation. I can of course re-run the entire validation process, but I wanted to have more control. Since the Func< > required by the ValidateProperty is typically an anonymous method or a private method within the model, it makes invoking the ValidateProperty method on the model really unsafe. The view model was reproduce the validation rules for the property, which it shouldn't ever do. If I exposed all of the individual validation methods within the model, then I kind of feel like I'd be breaking the Open/Closed principle.

To resolve this, I set out to re-build the ValidatableBase with a better version (still a work-in-progress). The revision will provide support for two methods. ValidateAll() and ValidateProperty(string property). These two methods wil then hit a cache of Validation Rules that each object has associated to it's properties and run the validation from those objects. As an example, I can create a StringIsNotNull validation rule object and add it via a property. When a model is instanced, it wil find all of the validation rules required and cache them. When either of the aforementioned validation methods are invoked, the applicable validation rules will get their Validate() method called and your property will be validated. If you want to re-evaluate a property, you can with ValidateProperty("Email");. This lets you abstract the actual validation rules out in to independent objects that can be re-used across your models.

The work is mostly done, but I'm having to spend some time determining the best way to provide parameters to the validation rules. Once this is ironed out, I should be able to publish a new version to GitHub.

Breaking Ground with Visual Studio Online

For my current project, I've chosen to host it on Visual Studio Online and make use of their source control, continuous integration via automated builds and Agile support.

Source Control

Visual Studio Online's source control (along with everything else) is handled through TFS. You are given the choice of using the TFS repository or a Git repository, that is managed by the TFS server. While I prefer Git, I chose the TFS repository since that is what I use at work. Since I use it on a daily basis, I am more comfortable and familiar with it. I want to spend my time learning better ways to code and building a quality product rather than spending time learning the ins and outs of Git via TFS Server.

The Visual Studio IDE has excellent source control support, so I was up and running really quick. I brought my self up to speed with the revised ALM Rangers Guide for branching strategies and got my branching system put together. Initially I'm starting with just a single branch, Main. Once the application gets to a stable point, I'll branch to a Dev branch and continue development there. I'll will ultimately end up with a Development and Release branch isolation strategy. Being a solo developer, I think this works well. It lets me stage chunks of code in Main, that will ultimately end up in Release, while continuing to develop new content in Dev until I am ready to ship Main.

Automated Builds

One of the things I'm really anxious to start doing, is automating my builds everytime I check in. Since Visual Studio online only provides you with 60 minutes of build time per month, I will probably only run continuous integration builds when I merge from my Dev branch in to Main and Release. When I am checking in code to Dev, I'm don't really need to have a build generated.

The nice part with this is that I can easily access a build of my application from anywhere. I just need to log in to Visual Studio Online, download the drop and run it. Since I don't like storing my source code on cloud services like OneDrive or Dropbox, this lets me access my source and drops from anywhere.

Agile

We use a variation of Agile at my work and I don't have any complaints with how Agile works. I used it somewhat with AllocateThis! when my buddy and I where working on some stuff together and found it helped provide a clear path for development. Typically, I just start writing code, then end up going back and re-writing code so that the new features I want work well with the old code. This time around, I'm going to plan properly.

I have crafted a series of user stories already and have a decent back log that is being built. An initial prototype of the app has already been wrote, so I've already got a decent idea of what is involved with creating a Universal Windows app. I will spend the next week or so finalizing the initial backlog, then start taking my prototype and building an actual product with it.

I'll post updates of my progress (without giving away to much detail!) as I develop the app. I kind of want to document a little bit the entire process, from start to finish, of creating a Universal Windows App Store app. Coming from WPF, it's been a bit of an adjustment. I had thought that they would be relatively the same (which they are); the differences however between the two frameworks are pretty significant and slowed my prototype development down. I imagine as I progress, my overall velocity should increase. At least until I start doing UI animation in Blend!