I’m finally biting the bullet and open sourcing Surge – the source is now available on GitHub.
I’ve been thinking about open sourcing it for years, but I’ve always been hesitant – it’s the first project I’ve stuck with for more than a few months, and I’ve learnt an incredible amount since starting it – but there’s always been the thought in the back of my head that “it’s not finished yet”, or “it has bad code, I should fix these things before open sourcing it”. Mostly, I was worried that I’d just get negative reactions about my code being terrible.
Now though, enough is enough. Yes, there’s some ugly code in there. Yes, there are bugs, and it’s unfinished. That’s sort of the point, though – open sourcing a completely finished, “bug-free” application is less interesting than one that still needs work.
When it comes to feedback and comments, I’d love some, particularly on the F# project (Surge.Core). It’s the very first F# project I wrote that wasn’t a tutorial. I already know it has some problems that I will get around to fixing, but I am still learning F# and feedback can just help me learn!
As I’ve mentioned before, learning F# has been one of my goals for a while. During Christmas (2014), I decided to use the free time to start on this, and it’s gone very well. I went through various tutorials and books, and then went in the deep end and rewrote the entire back-end of Surge in F#.
The Universal App namespace (root name Windows) is not exposed to F# projects (even with Visual Studio 2015 and all of the preview bits), so the UI itself (the .xaml and .xaml.cs files) are still C# based, as are the Converters (as many of them use the Windows namespace). You can get around this by creating a C# PCL that exposes the functionality of the Windows namespace, include it as a DLL (a direct project reference gives an error), but frankly that’s a lot of work with limited benefit when it comes to the UI.
I’ve also kept the ViewModels in C# for now, because I want to research proper MVVM work in F# before I think about rewriting the ViewModels. It’s something I’d love to do, as that would mean much more of the app is in F#, but that’s a future project. Even then, some parts of the app MUST be in C# for now.
As this was my first proper attempt at writing something in F# (rather than following tutorials, etc.), I decided to make things easy for myself by changing the project in C# before writing an F# version. It was a good thing too, because the state of Surge was rather abysmal.
It was originally written using MVVM but there was so much bad code that snuck in over time that it became impossible to say where the borders were between the Views, ViewModels and Models. The first step, then, was to do a bunch of refactoring so that I had distinct Views, ViewModels and Models.
I started by extracting the Model/Business Logic layer to a Portable Class Library I named Surge.Core, while the UI & ViewModel stuff were left in the Universal Surge project. During the refactoring I rewrote Surge.Core to use the Immutable versions of System.Collection.Generics and made a few other changes so that I had a better idea about how to write Surge.Core in F# in terms of what I’d expose to the rest of Surge, even though the internal program flow could be quite different.
After that, I rewrote the entire library in F# over the period of about 2 weeks. After the rewrite it offered identical (or at least equal) functionality to the C# version, but is nicer to use and I expose fewer public methods and types.
In the spirit of F# blog posts everywhere, inspired by Kit Eason and Scott Wlaschin, I gathered some statistics about the library as an Immutable C# project and then as an F# project. I’d love to have numbers on the project before I made it immutable, but it was so intertwined with the ViewModel layer that it’s not feasible.
891 (48% of total)
555 (79% of total)
702 (almost 3x fewer)
Despite the immutability, it’s relatively close to the results Scott had. In C#, about 50% is actual code, and then the vast majority of what’s left is blank lines and brace lines. I have very few null checks, but that’s thanks to the immutable re-write, I suspect. Likewise, with F#, over 75% is actual code. The only real difference here is that I have quite a few blank lines, but that’s probably because I find spacing makes things easier to read.
I tested performance of all 3 implementations – C# mutable, C# immutable and F#. The test was very simple – I just timed each update with System.Diagnostics.Stopwatch and averaged out several runs.
As such, all three implementations had a harder initial update (as Surge has to create a complex file structure for a torrent the first time it is added), but each successive update is much faster.
~1500ms. From what I can see, it’s the use of Microsoft.Bcl.Immutable in the file structure algorithm.
~600ms. A massive improvement, which is likely because the file/folder structure algorithm is surprisingly complex and I’ve just managed to write a better implementation in F# because of the elegance of the language.
~150-200ms per update.
~250ms per update. Just like in the initial update, using Immutable Collections seems to be the culprit.
~200ms per update. Roughly the same as the initial C# mutable form.
So F# is substantially faster when doing the initial update, and about on par with the best when doing the other updates. Fantastic!
Next, I’m going to work on a “Shared” UAP F# library I can reference in various projects. Amongst other things, I’m going to convert my LittleWatson tool to F#, and make a few improvements (primarily handling async better and transmitting crash data silently rather than requiring the user to send an e-mail). It will be open source, as will the server-side part so that anyone who wants to can add free WinRT bug reporting to their app.
This has been a LONG time coming – it’s been 15 months since the initial release of Surge and I’ve not done a single update. The problem is that as it’s a hobby project, I’ve (a) ignored it when life has been in the way, and (b) I use it as a place to experiment because it’s my own.
However, it’s now ready for release. There’s been a massive rewrite to move to MVVM (although it’s a little hacky at the moment – I decided to release and then work on having cleaner MVVM, especially with Windows 10 on the horizon). I also removed the entire network/update stack and rewrote it in F#. I’m going to blog about this in much more detail later, but for now it’s enough to say that it was absolutely, definitely worth it. The code is easier to read, faster and several bugs were fixed in the process.
It took 11 months to have 10,000 downloads of Surge, and in the 4 months since I’ve had another 12,000. I can’t imagine how that will grow when I add support for Deluge and µTorrent. The number of downloads really helps motivate me to keep working on Surge, so thank you to everyone that has downloaded it.
Find out more about Surge here, and download it for free from the Windows Store (note that update has to propagate through the various store mirrors worldwide and this can take a few hours).
The release notes for Surge 2.0 are:
You can set torrent download locations.
Force Start button.
An additional filter so that you can view all torrents with errors.
Option to always show app bar.
Support for clients with no password or anonymous access.
Count displayed for each torrent category (“All”, “Active”, etc.)
Support for ordering the list by name or by queue position.
Show available disk space on server.
Show verify and magnet progress.
If Surge is opened by a magnet link or torrent file, it will now be added to the server once connected.
Files pane now always displays folder structures correctly.
URL handling fixed for adding torrents and setting up the server details.
Add torrent button and other buttons don’t stay stuck in a disabled state.
Various crashes prevented.
Misc. small bugs.
Performance improvements, particularly regarding the files pane (opening it is up to 45 times faster!).
Base code support for coming updates including live tiles, notifications and support for µTorrent and Deluge.
If you look at the date difference between this post and my last few, you’ll see that I haven’t really blogged in months. This is a real shame, as I’d put a lot of effort into starting the blog and getting a routine going, but I ran out ideas and wasn’t sure what direction I should take the blog.
Then, a few weeks ago, I found out through his blog post that John Sonmez (the chap that runs Simple Programmer) has an e-mail blog course available for free that helps programmers get a blog up and running. I signed up for it straight away as it seemed exactly what I needed – a kick up the rear so that I’d start blogging again as well as help on how to stick to it and make a successful blog.
The course has covered more than I expected – it covered not just how to set up WordPress or similar, but more useful things such as how to pick a specialisation for your blog, how to keep on top of subject matter, why you should develop a schedule for both releasing and writing posts, and even why you should run a blog and what the benefits are to you personally and professionally.
I’ve really enjoyed the course – it’s definitely rekindled my interest in blogging. As I already had a blog, I did a little extra work in the first week and did a total redesign of the blog with a professional theme, as well as redesigning the Surge website.
I’ve now gone through all of the exercises and information in the course – created lists, set a schedule and so on. This final week covers getting your blog “out there”, so to speak. I have the lucky advantage of covering a niche but loved topic (F#), and I’ve noticed that just tweeting a link to my blog posts with the #fsharp hashtag gets me a surprising number of visitors. Still, the lessons in the course that cover “marketing” your blog apply just as much to me despite that – I can’t rely on Twitter for everything.
Anyone reading this post who doesn’t already run a blog should definitely sign up for the e-mail course. I know that I’m going to take the lessons with me as I develop my blog over the years. Thanks, John!
As mentioned in the previous post in this series, by default App.xaml will be in the Shared folder, but you’ll have a unique MainPage.xaml for Windows and Windows Phone. You may have wondered that, as you can clearly share App.xaml between projects, if you can share other XAML. The answer is yes: you can share all XAML between your projects. WinRT on the phone contains all of the UI elements you have in WinRT in Windows 8, and we use the same controls in both types of applications.
If you’re going to make a fairly simple application with a simple UI, then you can actually go as far as deleting MainPage.xaml from both the Windows and Windows Phone projects and creating one in the Shared project instead. I’ve done this in Proverbinatus, as the in-app experience is simply seeing a quote in the middle of the page.
I wouldn’t recommend sharing XAML in more advanced apps, though. Particularly when you take into account that Windows 8 has snapping, while apps on Windows Phone are always full screen.
There is also no functionality similar to #IF WINDOWS_PHONE_APP to manipulate your XAML, so if you share your XAML, it will be identical.
If you do share files, the XAML designer in Visual Studio lets you swap between seeing what the XAML would look like on Windows or on Windows Phone. The default view is the current default project, but you can change it via the dropdown box highlighted in red in the following pictures.
So, we have Universal Apps, we can share code, using the WINDOWS_PHONE_APP constant if we need to.
This is all great, but at least for now, Windows 8.1 and Windows Phone 8.1 still have quite a few differences. Windows 8.1 apps can snap and have large square tiles, they can be upside down (while phone only has one portrait orientation), and phone apps can have requirements, so that you can ensure the device has what your app needs (e.g. front camera or GPS).
As such, there are still unique differences between the two types, and we need to configure them. Of course, Microsoft provided a way for us to do this. We’ll look closely now at some of the files that come in the Universal App projects.
So, we have our three projects, populated with various files. Let’s list what we have:
You can probably already see that the Windows and Windows Phone projects look very similar, and they are. I won’t describe the two projects separately, but just a general description and then mention any differences.
The Assets folder contains some default assets for your application. It contains a few logos of various sizes, and the Phone project has a few more as it requires a few more to be a valid project. I recommend you use the Assets folder for application assets (icons, splash screen images, etc.), but keep other application files (such as images you use in-app) separate, just because it’s easier to maintain. It’s entirely up to you, though.
The MainPage.xaml and MainPage.xaml.cs files are the first app page that is launched. The next part of this series covers XAML, including these files, in more detail, as well as App.xaml and App.xaml.cs in the Shared project.
The most interesting file is Package.appxmanifest. This file lets us configure each project independently of the other project and choose platform-specific options. The file itself is an XML file, but if you open it via Visual Studio you are presented with a friendly UI to configure it without having to fiddle with XML directly.
There are 6 tabs of options for Windows apps, and 7 tabs on Windows Phone (the additional one is for Requirements).
Here you configure the core details of the Application: the name, description and default language, the entry point (what file should first be executed when your app opens, which by default is yourapp.App, which corresponds to App.xaml), and a few capabilities about things like orientation and toast (notification) support.
This tab is fairly simple to deal with, as most things are fairly clear or just involve entering text about your app.
This is where you define the visual assets for the app, by which we mean the icons, splash screen and tile colour. There are varying sizes of tile, and for your app to be able to use that tile size, you must provide at least one of these. You may also notice that there are multiple scaled assets for each tile icon (three on Windows Phone 8.1, four on Windows 8.1). This is how different DPI screens are managed, and I strongly recommend that you provide images for each scale.
A few of these must be provided. These are the ones that already have an icon provided by Visual Studio. While I’m mentioning these default icons, a tip: replace these. Your app will not be approved to be on the store if you use the default icons!
As previously mentioned, this tab only appears for the manifest file in the Phone project.
Here you can choose which hardware requirements your app has, if any. There are only five valid requirements: Gyroscope (to detect motion), magnetometer (compass support), NFC (Near Field Communication) and the front and back cameras.
If a phone doesn’t have all of the hardware you request, they will not be able to locate it in the store or install it in any other way.
This tab lets you pick what capabilities your app will have. In this context, capabilities means what additional OS features you need access to that are not available by default. These capabilities will all show up on the store page for your app so that the user knows you require these. Choosing these options, particularly things like access to the user’s library or other personal detail without it being clear exactly why you need these is a quick way to have users suspect your app of malware-like behaviour and people will avoid it.
Only ask for a capability if you actually need it.
Declarations are how you declare that your app performs additional functionality that default apps do not. The difference between capabilities and declarations are that capabilities are requesting access to additional things (such as the internet, the user’s pictures or camera), while declarations are saying you perform additional tasks, such as being able to read a certain filetype, being able to handle a certain protocol, or supporting background tasks.
All declarations require, at minimum, the entry point into your application. That’s because every single declaration is informing the OS of a different way your application can be launched and accessed. Some of them require additional detail, such as Background Task support. I’ll cover this in more detail in the next part of this series, where I cover background tasks.
This tab lets you declare which external URIs are allowed to call windows.external.notify to communicate with your app directly.
You need to be aware that any URIs declared in here are able to message your app which can cause things to happen. This is most useful if your app is essentially a web wrapper with some additional functionality, but you should be careful to not declare a site you don’t have direct control over!
I’ve never used this feature, and honestly I don’t know how many apps actually do, but I’d imagine it’s quite low.
This final tab is mostly useless and you don’t need to interact with it. The Package name, Package display name, Publisher display name and Package family name are automatically replaced when your app is uploaded to the store.
The version number field is set by you, and should follow the pattern Major.Minor.Build.Revision. Microsoft used to recommend that Major should be at least 2 (so that the entire 1.x.x.x range is available for Windows 8.0 apps) but that isn’t necessary now. Lastly, the generate app bundle should just be left on If needed.
I said earlier that code can be shared between Universal Apps. This is true, but there are a few exceptions. For the most part, you can think of WinPRT as a subset of WinRT. There are several methods that WinRT has that will throw a NotImplementedException if you call them from WinPRT.
Mostly, these are thrown if you call methods that are not appropriate for using on a phone, such as trying to view the file system. However, there are some occasions where this can crop up when you’re doing something that might seem appropriate. The prime example of this is with Live Tiles.
Both Windows 8.1 and Windows 8 have live tiles, and in Universal Apps you create them in the same way. However, Windows 8.1 supports live tile sizes that Windows Phone 8.1 does not. There’s a full description of all of the live tiles available on MSDN at The tile template catalog (Windows Runtime apps).
Obviously, the solution to this is that you’ll want your code to skip generating those live tiles on the phone.
Luckily, we can do this fairly easily with compile-time constants. When your Universal App project is compiled for the Windows Phone app, a constant WINDOWS_PHONE_APP is created. We can just check for this in our code to skip over live tile generation, like this:
var tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150Text04);
var tileTextAttributes = tileXml.GetElementsByTagName("text");
tileTextAttributes.InnerText = text;
var squareTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text04);
var squareTileTextAttributes = squareTileXml.GetElementsByTagName("text");
var node = tileXml.ImportNode(squareTileXml.GetElementsByTagName("binding").Item(0), true);
var bigSquareTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare310x310TextList02);
var bigSquareTileTextAttributes = bigSquareTileXml.GetElementsByTagName("text");
node = tileXml.ImportNode(bigSquareTileXml.GetElementsByTagName("binding").Item(0), true);
var tileNotification = new TileNotification(tileXml);
For a while now, I’ve been using Bing Code Search in Visual Studio, and recently Microsoft did a rather substantial update where they combined the extension with the Visual Studio Sample Browser and created the Bing Developer Assistant.
It has three core components:
It extends IntelliSense, giving you suggestions on how to use the code you are working with.
It has the features of the sample browser, so you can find code samples and snippets easily via the toolbar.
Offline search, so the other plugins will work even if you’re offline if you have samples downloaded.
Universal Apps are Microsoft’s current solution to the problem of multiple devices. When you create a Universal App, you have one solution that will run on both Windows 8.1 and Windows Phone 8.1 devices.
This works because Windows Phone 8.1’s runtime (WinPRT) is, generally speaking, completely compatible with WinRT in Windows 8.1, and finally enough code can be shared between the two platforms to make this feasible.
How do they work?
I suggest that you create your own Universal App in Visual Studio so that you can see for yourself what I’m writing about.
To do this, select File -> New Project in Visual Studio and choose Templates -> Visual C# -> Store Apps -> Universal App. Please note that you need to be on Windows 8.1 to create Universal Apps.
The structure of a Universal App is very simple: essentially, you can think of it as three projects in one solution.
These solution will be named APP_NAME, and the projects will be APP_NAME.Windows, APP_NAME.WindowsPhone and APP_NAME.Shared.
APP_NAME.Windows and APP_NAME.WindowsPhone will be compiled normally, as you’d expect. APP_NAME.Shared, however, is not actually a real project, and is not compiled to anything. It’s just a bunch of code that is used by both of the actual app projects.
This shared project can’t have references, either: if you want to use a library in your Shared library, you’ll need to add the reference to both the Windows and WindowsPhone projects to be able to use it.
As a general rule, you’re going to want to have device-specific code (UI code, for the most part) in the Windows/Windows Phone parts, and the rest of your code, such as your ViewModel, should sit in the Shared project.
Other than that, it’s normal Windows 8 app development that applies to Universal Apps. Unfortunately, although understandably, most of the information online at current about Windows Phone development is about Windows Phone 8.0. Most of this information no longer applies, as we have newer APIs and a slightly different application lifecycle. As such, if you’re having a problem, try to find a Windows 8.1 solution rather than Windows Phone 8.0.