When developing for Peter, please keep in mind the following patterns and practices:
Peter is developed using the MVVM paradigm. This is to help keep Data, Logic, and GUI code separate from each other. For a very nice explanation of MVVM, please visit the link below. Please keep in mind, we call our 'Models' 'Data', and 'View Models' are
just 'Models' or 'Logic'.
Now, in a perfect world the three (Data, Logic, and GUI) would always be completely separated, but we do realize that we do not live in a perfect world and this is not always possible. So in certain instances, like mouse events and so-on it is OK to have
logic code in the code-behind of a XAML file. We are aware that there are ways around this, but most of them come with a high level of complexity or processing overhead. To keep things simple, understandable and fast, if you absolutely need to add something
in the code-behind, go ahead and do so, but try and keep things a separate as possible.
Single Responsibility Principle
This is an object-oriented programming principle that states: every class should be responsible for one thing and that class should completely cover that responsibility. In Peter, we try to make most of the code as modular as possible, thus a class should
take care of a specific responsibility and not have arbitrary code in it.
As an example, we do not want to combine the code that handles status bar actions with code that creates the menus with the code that handles the logic of the main application. All this code is similar and is related, but it can be separated into different
classes. Thus we have the Main model, the Status model and the Menu model. All three are separate classes that handle the tasks they need to. Please see the link below for a more detailed definition.
Dialogs and the ServiceManager
When trying to keep GUI and Logic separate, one of the biggest problems are dialogs (i.e. MessageBox, prompts, etc.). In today's world, dialogs are becoming a thing of the past and other was to present users with information are becoming more prevalent.
There are still times when a dialog is needed and for this, Peter uses the
ServiceManager holds a list of 'Contracts' and implementations of the Contracts, which are called 'Services'. A contract is an interface that defines what will be accessible to the logic portion of the code. Thus the logic of the service
is separated from the GUI of the service via an interface. You can (and we do) add contracts and services to the
ServiceManager which have nothing to do with GUI as well. For a more detailed explanation of the
ServiceManager, please see the link in the paragraph above. For a quick example, here is how we would use the
ServiceManager for showing a message box:
In your App.cs file:
ServiceManager.Add<IMessageBoxService, MessageBoxService> ();
In the file you are using the message box:
var messageBox = ServiceManager.Get<IMessageBoxService> ();
if (messageBox != null)
messageBox.ShowError ("An error has occurred!", "Error");
Here we added the
MessageBoxService and the Message Box Contract (
IMessageBoxService) to the
ServiceManager. Then in order to use the service, we get the implementation of the contract from the
ServiceManager and use the interface provided. This way we can swap out the implementation when needed with something else, like a mocked implementation when we run Unit Tests.