Premature optimization is the root of all evil

May 30, 2016

Looking back at WPF/Silverlight/WinRT

Last week I had to write a small WPF application, and I was surprised how hard it is to get WPF right. By “right” I mean not just getting the code to work, but to write easily maintainable code I won’t feel ashamed of later. I haven’t being programming in WPF for about a year. A year is not long enough to lose touch, but long enough to get some perspective. While I was in the thick of it, I did not realize how ridiculous some things really are.

Of course, WPF is virtually dead, so its problems may not really matter, but WPF’s alleged successor “Modern UI” a.k.a. “Metro” a.k.a “WinRT” inherited most of WPF’s baggage. So, whenever I say “WPF” it really means “WPF, Silverlight, Metro and all other XAML-based technologies”. In fact, WPF successors made some problems worse, e.g. by excluding MarkupExtension.

WPF problem number one is that it is verbose. You have to write too much code to achieve simple things. Verbosity in WPF comes in multiple flavors:

  • XAML is verbose.
  • NotifyPropertyChanged is verbose and repetitive.
  • Value converters are verbose.
  • Dependency properties are verbose.
  • Attached properties are outright scary.

WPF problem number two is lack of consistent programming model. Putting business logic in views leads to mixing it with presentation, and your data binding looks awkward. Putting business logic in view models leads to ridiculous questions like “how do I handle double click”, “how do I open a new window from my view model”, or “how do I set focus to a control from my view model”. Any way you do it, it is either complex, creates unwanted dependencies, or both.

[read more…]

May 27, 2016

You ain’t gonna need it… You ain’t gonna need it…

Two parables about the YAGNI principle: both true stories.

Long time ago in a company far far away there was a piece of software. Every time we designed a new feature, we were told that “it must work when the computer is disconnected from the network”. Sometimes it did not matter, sometimes it complicated the design a lot. Punch line – no one ever actually checked that the software works when disconnected from the network. I tried it once, and it promptly hung on startup. Meaning: the rule about working without network existed only in theory, and its only real effect was to make things more complicated. No one ever cared about it in practice, but no one dared to question it either, so it poisoned our lives for years.

Different company, different piece of software, not so long ago. Pretty much every “update” operation in the software had a parameter for “as of” date. So, you could, say, cancel your subscription as of next Monday. This parameter existed only on the server side: no actual UI had it, and all real requests were to be executed immediately. Nevertheless, the parameter was passed around the entire body of the server code. No one asked questions like what would happen if I try to kill my own grandfather cancel my subscription as of before it was activated, or if I activate the subscription in the year 2038, but then get my account closed in 2017. There were no checks for that in the code. When we removed the parameter, not a single unit test failed (and we had quite a few). Meaning: someone thought it would be cool to have an “as of” date, but they never contemplated all the consequences, and this parameter was never used in practice. Its only real effect was to introduce annoying bugs when the client clock and the server clock went out of sync, giving users an opportunity to try to kill their own grandfather.

March 30, 2016

How to copy trusted root certificates to another machine

I have created a VM from an image with a very clamp down security setup. In particular, it had a very limited set of trusted root CAs. It would not even trust https://www.microsoft.com. So, I decided to copy the list of root CAs from my machine to that machine.

Exporting root CAs is easy: go to Control Panel, Administrative Tools, Manage Computer Certificates, select “Trusted Root Certificates” from the tree, go to Trusted Root Certification Authorities and then Certificates. Select all items Ctrl+A), right click, All Tasks, Export. I chose the .sst format and got myself a nice .sst file.

Importing that file into the VM proved to be more difficult. After some googling I found this article that contains a Powershell snippet that does the job:

[reflection.assembly]::LoadWithPartialName("System.Security")
$certs = new-object system.security.cryptography.x509certificates.x509certificate2collection
$certs.import("certificates.sst")
$store = new-object system.security.cryptography.X509Certificates.X509Store -argumentlist "AuthRoot", LocalMachine
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]"ReadWrite")
$store.AddRange($certs)

I copied this snippet into a file named import.ps1 and then executed it from PowerShell (“./import.ps1”). It worked great. I am not sure why Microsoft provides Export UI and leaves us to hunt for the import UI, but that’s a different question.

February 24, 2016

Access denied when creating a certificate enrollment request

As part of creating self-signed certificate, we use the following code:

var enroll = new CX509Enrollment();
enroll.InitializeFromRequest(cert);
enroll.CertificateFriendlyName = friendlyName;
string csr = enroll.CreateRequest(); // may fail with ACCESS DENIED

The latter is a call to COM method IX509Enrollment::CreateRequest(). If you are not running with elevated privileges, it will return with “access denied”, because it wants write access to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates. Note, that in latest versions of Windows most programs run without elevated privileges, even if current user has administrator rights. The program executing the above code must be specifically started via “run as administrator”.

January 17, 2016

A year of using Git: the good, the bad, and the ugly

I have been working with Git for about a year now, and I think I am ready for some summary. Before Git, I used SVN, and before it Perforce, TFS, and some other products, but I will use SVN as a prototypical “non-Git” system.

Git buys you flexibility and performance for the price of greatly increased complexity of workflow.

SVN will work for you better if

  1. All your developers work under single management, AND
  2. All developers can get relatively fast access to a central server.

Conversely, you should prefer Git if

  • There are multiple independent groups of developers that can contribute to the project, AND/OR
  • It is difficult to provide all developers with fast access to a central server

Here is my take on the good, the bad, and the ugly sides of Git.

GOOD: great performance, full local source control that works even when disconnected from the server, ability to move work quickly between servers without losing history.

BAD: complexity of workflow, more entities to keep track of, lots of new confusing terms, “one repo is one project” policy, limited/outdated information about the remote, misleading messages. Commit labels are not integers, which complicates build/version number generation.

UGLY: you can lose work by deleting branches or tags.

[read more…]

January 7, 2016

Thank G-d for StackOverflow

I have just run into a problem: a test passes fine on the CI sever, but breaks on my machine. Reason: it gets a wrong config file. Root cause: when you run tests from multiple assemblies via Resharper test runner, it plays games with AppDomains for the sake of optimization. Let’s say you are testing assemblies A.DLL and B.DLL. If you run tests from B.DLL separately, they will be executed in an AppDomain that points to B.DLL.config. However, if you run tests from both A and B in one session, they all will be executed in a single AppDomain, most likely pointing to A.DLL.config, and thus tests from B.DLL may fail.

It turns out there is an option to turn off this optimization, but obviously it is not really easy to find among 10,000 Visual Studio options. Thankfully, someone raised a similar question on StackOverflow:

http://stackoverflow.com/questions/27298101/why-am-i-getting-different-behaviour-when-clicking-resharper-run-all-tests-but

They even submitted a feature request to JetBrains:
https://youtrack.jetbrains.com/issue/RSRP-428958

In the comments to that request, JetBrains support says this is already fixed, but it’s not clear in which Resharper version. I sent a query to JetBrains support to find out, waiting for their response.

January 2, 2016

PHP SimpleXml is Broken: Part 2

In a nuthsell, SimpleXMl has two things broken:

1. Elements that represent “emtpy” tags evaluate to false. This is weird design.
2. Other elements sometimes evaluate to false due to bugs.

I covered problem #1 in the previous post. This post is about #2.

Unfortunately, due to bugs in the SimpleXML parser, a non-empty element may evaluate to false. No version I tested is completely bug-free, and the difference between correct and incorrect behavior may be as subtle as adding a space outside the element in question.

The code I use for testing is along these lines:

$xml = $xml = simplexml_load_string($text);
$node = $xml->xpath($xpath)[0];
if ($node) echo "Evaluates to true!"; else echo "Evaluates to false!";

Here are the test results:

$text $xpath Result Boolean value
<root><b>text</b></root> /root/b <b>text</b> PHP 5.4.4 – true
PHP 5.4.45 – true
PHP 5.6.15 – true
<root><a/><b>text</b></root> /root/b <b>text</b> PHP 5.4.4 – false
PHP 5.4.45 – true
PHP 5.6.15 – true
<root><a/><b>text</b> </root>
note extra space before “</root>”
/root/b <b>text</b> PHP 5.4.4 – false
PHP 5.4.45 – false

PHP 5.6.15 – true
<x:root xmlns:x=”urn:q”><a /></x:root>
same as the first one, only with a namespace
/x:root <?xml version=”1.0″?>
<x:root xmlns:x=”urn:q”><a/></x:root>
PHP 5.4.4 – true
PHP 5.4.45 – true
PHP 5.6.15 – true
<x:root xmlns:x=”urn:q”><x:a /></x:root>
same as previous, but using <x:a /> instead of lt;a />
/x:root <?xml version=”1.0″?>
<x:root xmlns:x=”urn:q”><x:a/></x:root>
PHP 5.4.4 – false
PHP 5.4.45 – false
PHP 5.6.15 – false
<x:root xmlns:x=”urn:q”><x:b>text</x:b></x:root> /x:root <?xml version=”1.0″?>
<x:root xmlns:x=”urn:q”><x:b>text</x:b></x:root>
PHP 5.4.4 – false
PHP 5.4.45 – false
PHP 5.6.15 – false

I believe evaluating non-null objects to false was not a good idea in the first place, but worse yet, PHP cannot really do it right, so the result of if ($node) check is never reliable.

PHP SimpleXML is broken: Part 1

The following code does not work as expected:

$xml = simplexml_load_string("<root><a/><b>text</b></root>");
$node = $xml->xpath("/root/a")[0]; 
if ($node) process($node); // process($node) may not be called for some valid nodes

Unlike most other objects, SimpleXmlElement may evaluate as false even when it is not null. Specifically, SimpleXmlElements representing empty tags (like “<a />) will evaluate as false, so process($node) won’t be called for them.

Yes, they made a special case for it in the language definition. E.g. DOMElement representing an empty tag won’t evaluate to false, at least not according to the documentation.

So, in my previous post “Node is null” should read “Node evaluates to false”, but it is still a bug, since it was not an empty tag.

When you write if (something) that something will be converted to Boolean per the below conversion rules. Most of them make sense, but some of them totally don’t. If you want to check for null, you’d better do it explicitly: if (something !== null).

PHP Boolean Conversion Rules

Per the PHP documentation on Boolean (comments are mine):

When converting to boolean, the following values are considered FALSE:

the boolean FALSE itself Totally makes sense
the integer 0 (zero) Like in C/C++, so it is expected, even if may not make perfect sense
the float 0.0 (zero) Like in C/C++, so it is expected, even though it makes even less sense
the empty string Not like in C/C++, but sort of makes sense
and the string “0” Why?! Because it represents integer 0? How about string “0.0” then? Or string “false”?
an array with zero elements Sort of makes sense
an object with zero member variables (PHP 4 only) Does not make sense, but they deprecated it
the special type NULL (including unset variables) Totally makes sense
SimpleXML objects created from empty tags Why?! Who came up with this wonderful idea?

Rest in peace, dear rule of least astonishment. You should never have ventured in that cruel PHP land.

PHP bug + version dependency hell

I have discovered a bug in PHP 5.4.4: a simple XPATH does not work.

$xml = simplexml_load_string("<root><a/><b>text</b></root>");
$node = $xml->xpath("/root/b")[0]; // $node is null $node evaluates to FALSE

This is so ridiculous, I could not believe my eyes. Nevertheless, it’s a bug. It does not occur with the latest version of PHP (5.6.15), although I could not find a specific fix that would be responsible for this in the PHP bugs database.

The trouble is, PHP 5.6.15 no longer supports Apache 2.2, which means I have to upgrade to Apache 2.4. This is probably a good idea anyway, but I hate this kind of domino effect.

Alternatively, I could ditch SimpleXML and switch to DOMDocument. Or write the whole thing I was writing (which is a test project anyway) in something more civilized like ASP.NET. Anyhow, fun stuff!

Update: PHP 5.4.45 does not have the bug. PHP guys seem to be doing a good job backporting bug fixes to older versions. Revolution averted :)

Update2 : Correction: in PHP 5.4.4 the node was not actually NULL, it was (incorrectly) evaluating to FALSE as if it were an empty tag. This, however, is still a bug. The fix in PHP 5.4.45 is also only partial. See my next post.

December 31, 2015

WCF Restful service: returning data in different formats depending on request parameter

Suppose I want to return a list of users in JSON or CSV format depending on a query parameter.

MyService.svc/users?format=json returns JSON
MyService.svc/users?format=csv returns CSV

The question is: how do I implement it with WCF (leaving aside the discussion on whether it’s a good idea)?

The answer: the multi-format method must have return type Stream. The programmer is fully responsible for formatting the response body in all cases, including setting Content-Type.

    [ServiceContract]
    public interface ITestService
    {

        [OperationContract]
        [WebInvoke(Method = "GET", UriTemplate = "users?format={format}")]
        Stream GetUsers(string format);
    }

Solution attempts that did not work

1. You cannot have two methods that differ only on query parameters.

    [ServiceContract]
    public interface ITestService // Does not work as expected
    {

        [WebInvoke(Method = "GET", UriTemplate = "users?format=json", ResponseFormat = WebMessageFormat.Json)]
        List GetUsers();

        [WebInvoke(Method = "GET", UriTemplate = "users?format=csv")]
        Stream GetUsers();
    }

This throws an exception at runtime saying one cannot have two methods whose URI templates differ only by query parameters.

2. You cannot have a method that returns object. I expected WCF to turn off response formatting when dynamic response type is Stream. This turned out to be not the case. WCF turns off response formatting only when the method’s static return type is Stream. See my question on StackOverflow.

Things to pay attention to

1. If you create a MemoryStream and write into it, make sure to reset the pointer to the beginning. If you don’t, the response body will be empty.

2. Don’t forget to set Content-Type and (optionally) Content-Disposition.

3. JSON must be serialized by hand.

4. Don’t forget to properly handle case of bad request parameters.

Code: https://github.com/ikriv/wcf-rest-multiformat