CX Reconsidered [1]: A Thin Layer of CX?
This is the first blog post in a series of n. The posts in this series will discuss opinions about C++/CX (from here on referred to as CX for reasons to be explained later), discuss pros and cons, and propose a meaningful way of working with C++ and Xaml in the context of Windows 8.The table of contents into that series will develop right below this sentence.
Part 1: A Thin Layer of CX? (this post).
Part 2: MVVM to the Rescue.
Part 3: Components on a thread
Introduction
Before Windows 8, I used to develop software in C# .Net for ASP.Net, WPF, and Silverlight, in C++ and some DirectX. What I needed was a better integration of C++, DirectX, and Xaml user interfaces. And low-and-behold, with Windows 8, Microsoft introduces CX. According to MS spokespeople CX is to be used as a thin layer around C++ programs, 99% of the code should be regular ISO C++. The value of the CX layer lies in the ability to cross the ABI (Application Binary Interface). The ABI is what makes it possible for programs written in language A to be used by programs written in language B. By the ABI, CX can also be provided with, among other things, a Xaml UI. Of course I jumped on it, this was exactly what I was looking for!
Now I’ve been writing software in CX (among others) since May 2012. It’s now June 2013, hence it is time to evaluate the experience; for myself, but hopefully this evaluation is of value to other developers too.
Conclusion
Let’s start with the conclusion, and then provide some analysis.
The conclusion is that I truly and intensely dislike CX. In the MS Forums (Fora?) someone wrote that programming the bare WinRT is tedious and rather painful. To me, the same holds for CX as well – although it is meant to relieve just that experience. My aversion for CX brought me to the point that I could not see where CX does come in handy, but thankfully I was able to put myself straight at that point.
What I dislike about CX can be summarized in 3 statements:
1. CX is supposed to be used as a thin layer, but escaping from CX is very hard. Once you start developing your program in it, you are likely forced to keep using it.
2. CX is not C++. That is, practices and idioms that you use with ISO C++11 are, as a rule, not valid for CX. This is why it is being called CX here, its native, but not C++.
3. CX is not C#. The same as above holds for C#, moreover, the developer experience with VS2012 is strongly inferior, as is the support for Xaml interfaces. Community contributions (such as MVVM light for .Net) are minimal.
That is, CX doesn’t meet your expectations as either a C++ developer or a C# developer. nor does it support ‘a thin layer of CX’ – it doesn’t let you go.
So, if you are a .Net developer that would like to author C++, doing CX is not the way to go.
Then there is this nagging question: If CX is meant to be used as only a thin layer around C++ code, then why has MS created the HILO example: a full-blown CX program? To show that CX should not be restricted to a thin layer?
Analysis
Why the aversion? Let’s go over the points in the Conclusion above.
A Thin layer of CX
The intention of a thin layer of CX is OK. It saves you the trouble of having to write code using the WRL (say COM). However, by the way MS has set application templates up that are based on CX, it is hard to restrain CX to a thin layer. A CX application has two powerful assets that bring it everywhere:
1. It defines the outer periphery of the application, that is all contact of the application with the world outside the application is via CX.
2. It runs on the main application thread; the UI thread, so it constitutes the main flow of control of the application.
This is a powerful combination in an application which architecture is to respond to environmental input and some system events. Anything coming from the environment: user input, file contents, network data, and data from files and databases, comes into the system in CX data structures, and on a CX thread.
Restrictions that apply to CX data structures tend to proliferate into user defined data types, and threading restrictions tend to proliferate into user spawned threads. Thus, the CX layer tends to expand. It will not be a thin layer, You will not work in C++, but in CX.
CX is not C++
If you are a C++ developer, you want to code in ISO C++11, not in CX, and certainly not in CX types instead of e.g. STL types. The developer experience of CX is strongly inferior to the C++ experience.
CX is not C#
C# .Net developers are used to a comfortable developer experience. Things tend to ‘just work’ (as they should). With CX, things don’t ‘just work’. Give a C# .Net developer the choice to switch to CX, and he/she will walk away smiling, if not grinning, after a short trial.
So, what happens is that CX hijacks your program, and you will have a hard time to escape. Once caught within CX you will be frustrated because you will be deprived of both the developer experience of both C++ and of C# .Net.
Not all is lost, however. With some architectural maneuvers, we will definitely put CX back in its cage! (But that will be in another installment in this series 🙂 ).
Next up: How CX was received in the forums (fora).
>>CX is supposed to be used as a thin layer, but escaping from CX is very hard. Once you start developing your program in it, you are likely forced to keep using it.
I sympathize with this, but do not think it’s a short-coming of CX itself. I did quite a bit of CLI/C++ in the past and had these exact same issues. I would develop a mixed mode assembly and by the time I was done it was a mish-mash of .NET and C++. When the time came extract the C++ code to it’s own native library, it was essentially a rewrite.
Since those times, I took a new strategy in CLI/C++ and since applied in CX. I DO NOT start writing in CX. Instead I always write a static (ISO C++) library first, then I use CX to wrap that. This ensures I have the most portable C++ code and minimize CX “leakage”.
When developing UI components, lots of CX is unavoidable. It can still be thought of a “thin wrapper”, but when building UI, you are consuming WinRT and exposing your WinRT classes at the same time. So here, the “thin wrapper” is twice as thick. Even for some custom controls, you may have very little ISO C++, which is ok because these controls aren’t usable outside WinRT anyways.
>>. It runs on the main application thread; the UI thread, so it constitutes the main flow of control of the application
Not sure if I follow. UI events will happen on the UI thread. Async operations such as network or filesystem can callback (via ppl) on the calling thread or an arbitrary thread pool thread if set. This isn’t too different than WPF or Silverlights DispatcherObject and its UI thread requirement.
-Jer
Hi Jer,
How very nice of you to write a comment!
Have you noticed how the timing of your comment and part 2 of the series (MVVM to the rescue) coincided? All aspects of the first guillemet of your comment are in this new article in some way. (So, I guess we very much agree).
Of course, the leakage is part of a chain of dependencies, created by the development tactics / strategy handed over to developers by Microsoft via Visual Studio and CX. Different tactics are the answer.
As for your doubts concerning the section on threading, it seems to me you are looking at it from your viewpoint of someone who has already adopted an effective development strategy, while it has been written from the viewpoint of someone who has just coded numerous task().then() chains. Another theme that keeps one from writing ISO C++.
The general point in part 2 of the series is to do as much functionality / code as possible not in the UI layer and the wrapper layer but in the stat. lib. The plan is to write some more installments in order to explore the solution of part 2 and see in which ways it can be made to work well (and to see what doesn’t work, of course 🙂 ).
Regards,
Marc.
[…] CX Reconsidered [1]: A Thin Layer of CX? […]
[…] CX Reconsidered [1]: A Thin Layer of CX? […]