Maximizing Code Reuse Across Windows 8 and Windows Phone Apps

A common ask among customers and developers is around guidance on how to structure/architect their code to maximize reuse across Windows 8 and Windows Phone apps. This post will explain what is/isn’t reusable across apps, cover some patterns that will help increase code reuse across Microsoft platforms, and puts the theory into practice with a sample that shows common code being used for both a Windows 8 and Windows Phone 7.5 app — available here.

Note: This post focuses on Windows 8 and Windows Phone 7.5 app development. However, the patterns and practices described can be applied to other platforms (i.e. Windows Phone 8 when it’s generally available).

To maximize code reuse across Windows 8 and Windows Phone the best practice is to use the MVVM (Model/View/ViewModel) pattern to architect your code combined with PCL (Portable Class Libraries).

MVVM (Mode/View/ViewModel)

MVVM focuses on separating the user interface (the View) from the data or business logic (the Model). The ViewModel provides a specialization of the Model that the View can use, and also provides a place for complex operations that are View related and maintaining state like selection. The MVVM pattern relies heavily on data-binding. I won’t go into any more detail about MVVM since it’s been covered ad nauseam. If you’d like additional information on the pattern I’d suggest this video by John Papa/Dan Wahlin as a starting point.

PCL (Portable Class Libraries)

PCL by definition are constrained and  can only reference APIs that are available across multiple platforms (i.e. Windows 8, Windows Phone 7.5). Consequently, libraries can be shared across projects without modification.

image

 

By combining MVVM with PCL it is possible to architect code so large portions like the ViewModel and Model can be reused across supported platforms. It is also possible to reuse parts of the View because a significant amount of XAML (i.e. StackPanel, Grid, Button, etc.) is available to both platforms but the general guidance is to focus on taking advantage of the form factor instead of forcing the issue.

Practice, however, is never as clear cut as theory. For example, when creating a ViewModel that is responsible for retrieving data the first wrench appears. Writing code to retrieve data that is common across both platforms is non-trivial because WinRT introduces HttpClient that is asynchronous using async/await  to simplify networking

HttpClient client = new HttpClient();
HttpResponseMessage response = new HttpResponseMessage();
client.MaxResponseContentBufferSize = int.MaxValue;
response = await client.GetAsync(requestURL);
string responseString = await response.Content.ReadAsStringAsync();

and Windows Phone relies on HttpWebRequest that requires a callback.

HttpWebRequest req = HttpWebRequest.CreateHttp("http://odata.netflix.com/...");
req.BeginGetResponse(new AsyncCallback(GetResponseStringAsync), req);

To leverage either of these networking stacks in the ViewModel would be impossible because they are not in the PCL common subset.

The solution is to first abstract the concept of getting data by providing an interface that accepts a callback

public interface IGetTitlesService
{
    void GetTitles(Action<List<Title>> callback);
}

and then to implement the interface in a platform dependant way.

public class Query: IGetTitlesService
{
    //...
}

The ViewModel needs to be created with the correct concrete implementation but the interface lives in the PCL keeping the ViewModel platform independent.

public TitleViewModel(IGetTitlesService getTitlesService)
{
    getTitleServie.GetTitles(LoadTitles);
}

private void LoadTitles(List<Title> titles)
{
    //..
}

Another wrench appears when using MVVM on Windows Phone because the responsibility lies with the developer to marshal calls back to the UI thread. Windows 8 automatically takes care of this. Again this difference threatens to tie the ViewModel to a specific platform but a similar pattern can be used to abstract the Dispatcher.

public interface IDispatch
{
    void Dispatch(Action action);
}

The sample I’ve provided shows how to work around both wrenches and uses a common ViewModel and Model for both the Windows 8 and Windows Phone apps.

Other Reuse Tips

From my experience there are two other ways to maximize code reuse that can be used in conjunction with MVVM and PCL.

  1. Linked Files – allows a file to be shared between two projects but only one copy is maintained
  2. Preprocessor Directives – compiles code based on conditions that are set up in the build environment (contributes to code smell and not recommend but I’ve included an example in the sample for reference)

I hope these tips help – if you have additional tips or suggestions please feel free to leave a comment.

Windows 8 samples require Windows RP & Visual Studio 2012
Windows Phone 7.5 sample requires Visual Studio 2010 with Windows Phone SDK 7.1, Windows Phone SDK 7.1.1 (to run on Windows 8),  Portable Library Tools 2 RC

Both comments and pings are currently closed.

6 Responses to “Maximizing Code Reuse Across Windows 8 and Windows Phone Apps”

  1. [...] Maximizing Code Reuse Across Windows 8 and Windows Phone Apps by Alnur Ismail (August 2012) [...]

  2. Portable Class libraries are the bomb.
    If only the latest rev worked on the July LakeView ADK :)

  3. [...] was that you would have to package, change the DLL, re-package. Not anymore…”Maximizing Code Reuse Across Windows 8 and Windows Phone Apps (Alnur Ismail)“A common ask among customers and developers is around guidance on how to [...]

  4. Necroman says:

    I’ve been solving this issue too. Currently it’s not really possible to create shared code between WP7 and Win8, because Portable Class Libraries doesn’t support async/await syntax. In Win8 are async/await calls irreplaceable, in WP7 it’s possible to use async/await with Async CTP and it is believed async/await will be supported in VS2012 too with Async targeting pack (it’s supported by default when targeting WP8 as far as I know).

    So the best solution I’ve found right now is sharing files between WP7 and Win8 and defining few surrrogate classes to overcome differences between WP7 and Win8, like defining HttpClient as a wrapper for WebClient, defining own Settigns class for persisting data using IsolatedStorageSettings in WP7 and ApplicationData.Current.LocalSettings in Win8.

    Once VS2012 RTM, WP8 SDK and updated Async targeting pack is available, I believe sharing code between WP7/8 and Win8 will be much simpler than today.

  5. Ross M says:

    Nice article, and helped confirm some things for me… Have been doing the same with the PCL and WP7/Win8.

    Have you looked at Navigation also? Another challenge between the two platforms given the API differences.