Tuesday, April 22, 2014

Object Oriented Programming - Beginner Resources

Over the past few years, I've run across some great content on the web for learning object oriented programming.  The below is a list of web resources...



Using the Convention Based Prism 5.0 View-Model Locater

All the information you need to use the View-Model Locator is in the Prism 5.0 documents, but if you've been there and had some trouble this may help. The key here is that this is all about convention over configuration. You can configure what view goes with what view model per the docs like this:
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
        {
            ...
            return viewModelType;
        });
However, if you just name things according to the specified convention, things will auto wire with a few of the normal expected issues. First off let's get to what the convention is. When I set up a new project, I typically make two folders - one named ViewModels and one named Views. I've seen other folks use the singular ViewModel and View, but if you want this to work, you'd better make those plural. The folders are Namespace providers so .ViewModels.MyScenicViewModel, and .Views.MyScenicView. That was my downfall... The expected convention is that the view not have any suffix of View, but the View-Model must have a ViewModel suffix. So to adjust what we had before, it would look like this: .ViewModels.MyScenicViewModel and Views.MyScenic. This threw me for a bit of a loop but yes, it is clearly stated in the Prism documents. The next gotcha is the normal View-Model must have a default constructor. If it doesn't, you need to tell the Prism VM locater how to resolve its dependencies. In your app initialization add the following:
    ViewModelLocationProvider.SetDefaultViewModelFactory(t => _container.Resolve(t));
The view must implement the empty IView interface found in the Microsoft.Practices.Prism.Mvvm namespace.
  public partial class Wizard : Window, IView
    {
        public Wizard()
        {
            InitializeComponent();
        }
    }
And finally set the auto wire up flag to true in your views xaml.
<Window x:Class="MyProject.Views.Wizard"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mvvm="clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop"
        Title="Wizard" Height="600" Width="800"
        mvvm:ViewModelLocator.AutoWireViewModel="True">
That's about all there is to it For more info, read the Prism 5.0 Developers Guide.

Prism 5.0 for WPF

I was listening to .Net Rock's! show 971 with Brian Noyes, and I was thrilled to hear that Microsoft just dropped a new release of Prism - Prism 5.0 for WPF. I've been using Prism on an application mainly for modularity, but I was encouraged to hear that several small tweaks had been made to the Prism library.  Here are a few of the highlights...
  • Broken into smaller more targeted assemblies
  • Updated NotificationObject to BindableBase
  • Includes a conventions based View-Model Locator
  • Objects can be used to pass data around in Region navigation
Personally, I think this is all great!  I was a little shocked to read some of the comments on CodePlex.  People in general, and developers especially, have a tendency to develop very strong opinions based on biases from their personal experiences.  Let's not lose site of the reason we have the MVVM pattern. Its about the ability to decouple the software so we can test it.  If you use an injected view service to open child windows or a behavior, and you accomplish the goal of keeping your View-Model testable... does it really matter?  
There was one comment aimed at the View-Model Locater calling it an anti pattern...  People are entitled to their opinions, so here is mine.  Using the View-Model locater that now comes with Prism saves me a few lines of code.  Relating the View to the View-Model is ceremony code. If it doesn't drive business forward, it wastes my time.  Some clever people at Microsoft helped me out with this...  My View-Model is still testable and the project has a few less lines of my code. What's wrong with that?

The guidance documents have been updated, and the source is on CodePlex

Wednesday, April 9, 2014

Testing Internal Classes in .Net - Pragmatically

Lately, I've been working on a very large .Net API that our company is developing. Ultimately, the number of classes exposed to the user is very few.  To facilitate testing everything was originally developed as a public class.  Now that the development has slowed substantially, I've gone back through the code and used the Internal (C#) or Friend (VB) access modifier to hide away the code that doesn't concern the public API.

This immediately caused our automatic test runner tool NCrunch, to show failing tests.  The reason is obvious, once you change the access modifier to Internal, your test project which is a separate assembly can't see those classes.  A quick search of the internet turned up a few interesting solutions.  Some people suggested moving all the tests for the internal classes into the main assembly, marking the tests as internal as well.  I'm not a fan of that idea, as I like the separation offered by a test project. 

Other folks feel that if the class is internal, you should forget about testing it, and just test what is exposed.  Perhaps if this was a small uncomplicated API this would be okay.  However, our API is related to some fairly complex engineering tasks, and as such the internal members really need testing.  

The pragmatic solution is this...  In the project AssemblyInfo file add an attribute to expose the internal classes to your testing assembly.  

Example given here is with VB attributes...

'Exposing the assemblies to Test Framework, and to Moq's Proxy Generating Assembly
<Assembly: InternalsVisibleTo("KNE.TubingForces.BLL.Test")> 
<Assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")>
Notice that I also expose to DynamicProxyGenAssembly2, this is so Moq's proxy engine can still create mocks for internal classes as well.