As software creators we don't get to decide what version of our tools / libraries that people use. If we try to force them, our users will go somewhere else.
This post talks of tools, applications and libraries. Things that end up in the users hands. This does not apply to SaaS or websites. These do not end up in the hands of the users in the same sense.
For those of you who immediately think of Chrome or Firefox, which are applications that end up in the users hands, those apply to this post as well. They have nearly perfected a silent upgrade experience, but if they ever mess up that experience, users can choose to use something else. And I believe there is a way to opt out as well (not easily achieved but possible).
I write software. Much of it is open source. I have multiple versions of my products out there. Even with newer versions available that fix bugs and bring about new features, I still find people using older versions. Even though I have a better newer version that fixes some of the bugs they are dealing with, they are still using an older version. Think about that for a second. There must be a good reason right? Let’s state this in an official sense.
As a software creator you release software. You put a release out there and people use that release. You delineate different releases by a concept of versioning. People use a particular version of your release. You release newer versions of your software that has fixes and enhancements. You hope users upgrade to the latest release when it is available.
I’ve stated five facts and finished with a hope. If you can accept those as facts, we can move on. If we can’t, then you might want to stop reading now because we are never going to agree. If you are a developer like me, you really want people to always use the latest version of your software, so you might be able to accept the last statement as a fact for you. I really want people to always use the latest release of my software as I have went through the trouble of testing it and making it better.
Now let me change some terms for you. Software release management is really a fancy way of saying package management. A software release could be better termed a package. So to restate, as a software creator, you release packages. You put a package out there and people use that package. You delineate different packages by a concept of versioning. People use a particular version of your package. You release newer versions of your package that has fixes and enhancements. You hope users upgrade to the latest package when it is available.
I say “hope they upgrade” because you really can’t control that aspect. You can try. You can delete the older versions. You can refuse to have older versions available. You can tell users that they should and need to upgrade. But you put it out there once and it is now out there forever. People will find a way to get to the particular version they need. Or they will go elsewhere. Users speak with their feet.
I find attempting to force a user to do something is both an exercise in futility and a great way to guarantee that you have less users overall.
So people must want to use a particular version of a product. Let’s examine this a little more. Why on earth would someone use an older version of a product when a newer, better, less buggier version is available?
Users use older versions of our packages and they have great fundamental reasons for doing so:
In fixing a product and making it better and less buggier, you may actually be breaking someone’s ability to use a newer version. And you have no guarantee to the user that this version doesn’t have flaws of it’s own. Right? Otherwise there would only be one version that ever had fixes in it. We wouldn’t need to release newer versions with fixes, only enhancements. But we don’t. We fix things we thought worked and we fix things we tested but missed some crazy edge case. This is why we go down this path of release management. This is software development.
So people get a certain version and they use it. Users upgrade to the latest version of software when they are ready, not when the software creator is ready. People depend on certain versions or on a range of versions. In reality I can't force someone to use the latest version. If I try, they will find the version they need through the powers of the internet or find another way. Accepting that, I can give them a way to see it and help them fall into the pit of success.
Shifting to the perspective of the user, I might use your library in my own software. Being able to build my product, even if it means it is using an older version of your package that has bugs, is worlds more important to me and my users. We'll get to your latest version when we can test that it doesn't break our product. But don't try to force me to upgrade to your latest version or I will find another way. I'm not saying that with your package but in all packages the newer version may be buggier than the current buggy version we are using. We don't know and you can’t guarantee that it doesn’t, even with extensive testing. Testing doesn’t prove the absence of bugs, only the absence of errors that you know. I digress.
It’s an evil that we know versus and evil that we don’t. Or put another way, it's a buggy version we know versus a buggy version we don't.
If it’s a tool, we need to ensure that our usage of your product still meets our expectations. We need to test it even though you did and make sure it still works for our needs and scenarios. Where it doesn’t we need to decide if that means we can shift our expectations and upgrade. But we are not going to blindly upgrade and just use the latest version because the software creator believes that is best.
Can you cover the millions of dollars that we might lose by taking on a newer version of your product? If you can give me that guarantee, as a user I will gladly pass that risk on to you.
Whether you agree or not, as software creators we don't get to decide what version of our tools / libraries that people use. We just don’t have that luxury. If we try to our users will go somewhere else. So we make it easy for them to upgrade so they will want to. We make the upgrade experience painless so they will want to. We need to be good stewards.
Have you ever had an error crop up when debugging an application which has made you simply want to pull each hair out of your head one by one with a pair of tweezers because that would be less painful than debugging the error? Today I had just this happen to me.
Today when I hit F5 to launch our Silverlight application I received the following exception :
The body of this error message is
Line: 56 Error: Unhandled Error in Silverlight Application Code: 2108 Category: InitializeError Message: Failed to download the splash screen
Of course since I have the debugger I was going to attach to it, but sadly that was NO HELP. When reading error you notice it says that it failed to download the splash screen. This is really odd because when looking in the source it is there… In an effort to ‘remove the problem’ I removed the line of code from our ASPX page which setup the splash screen as a resource, the line below.
<param name='splashscreensource' value='SplashScreen.xaml' />
Thinking that this would solve my issue, at least for now, I hit F5 again. Things were different this time, but sadly not for the better. Now in place of getting the error message I simply got the default ‘blue dots’ from silverlight indicating that the xap was trying to load. This was really odd. I did what any developer would do, I hit F5 3-4 more times thinking that the problem would just magically go away, hey it does happen, but as you can guess it did not go away.
Because I had been making a bit of changes in the code and it was possible that I could have accidently really FUBARED my code base I shelved my code, blew away my ENTIRE branch and did a fresh pull. Yea, that did not either.
So my on branch was dead, but my co-worker who is in the same branch was able to launch and run the app just fine. In another effort to see if it was my branch code or my machine I decided to pull down the trunk (the parent of this particular branch) to see if I had the issue there… Yea no, that code worked just fine.
Because I knew it was not my machine it had to be code. I decided to start diffing the files I thought were causing the issues such as our default.aspx page, our login page along with a few other files. As you may have guessed NONE of these files were different.
Because I had been beating my head against this for greater than an hour I decided that I should move on to something else and come back to this later (I guess I was still holding out for the code fairy to magically fix my stuff while I was away).
Well later came and I had to go back to my branch to fix a production issue and this issue was still there. This time however things were a bit different, no the code fairy did not do her magic, my co-worker said ‘hey I got that a few minutes ago’. I was both elated and pissed at the same time. I was elated because maybe NOW I could solve my issue. I was pissed because this was the same co-worker I had talked to about this issue a few hours back and NOW they knew how to solve the issue.
So what was the issue? My co-worker was playing around with some security settings in our web.config file and had accidently committed is changes. It was these changes that was causing my issue. What did he change? He did 2 things
1) He setup a deny ALL authorization rule
2) He setup other rules to only allow a few pages to be open as such
The 2nd change was not a huge issue, it was the 1st one that was killing me. Because he had turned off anon access to the site my xap could not load and because my xap could not load the splash screen could not be presented to the user and for what ever reason Silverlight decided that in place of providing a meaningful message it would simply say it could not find my splash screen resource.
Since I knew the issue I was able to change my rule from deny to allow (in #1) and re-run the application…. finally I could fix bugs I created
The moral of the story here is that if you get an error saying you cannot access a resource in your xap file double check that IIS has access to the xap because if it does not you may get this issue.
The other moral of the story is that it should be 100% legal to cane a co-worker who commits a change that breaks you and does not even realize it. Ok caning may be harsh, at least they should buy you a beer.
Till next time,
I’m extremely pleased to announce the release of Caliburn.Micro v1.3. This is a great release with many bug fixes and several API improvements. We also support several new platforms. Here’s the highlights:
Thanks to the great community who provided awesome feedback during this release cycle. Thanks also to those who spent time to provide fixes and pull requests for bugs as well as for API improvements. I’d like to add a special thanks to Chin Bae for excellent work on making our ViewLocator and ViewModelLocator both more extensible and more accessible for common customizations.
We’re still just getting started. Enjoy the new bits and see what you can build!
Quick question – from the top of your head, without running the code, what is the result of:
var foo = -00.053200000m;
var result = foo.ToString("##.##");
Or a different one:
var foo = "foo";
var bar = "bar";
var foobar = "foo" + "bar";
var concaternated = new StringBuilder(foo).Append(bar).ToString();
var result1 = AreEqual(foobar, concaternated);
var result2 = Equals(foobar, concaternated);
public static bool AreEqual(object one, object two)
{
return one == two;
}
How about this one from NHibernate?
var parent = session.Get<Parent>(1);
DoSomething(parent.Child.Id);
var result = NHibernateUtil.IsInitialized(parent.Child);
Well, if you can answer all of the above without running the code, we’re hiring. I don’t, and I suspect most people don’t either. That’s fine. Question is – what are you going to do about it? What do you do when some 3rd party library, or part of standard library exhibits unexpected behaviour? How do you go about learning if what you think should happen, is really what does happen?
I’ve seen people open up Visual Studio, create ConsoleApplication38, write some code using the API in question including plenty of Console.WriteLine along the way (curse whoever decided Client Profile should be the default for Console applications, switch to full .NET profile) compile, run and discard the code. And then repeat the process with ConsoleApplication39 next time.
The solution I’m using feels a bit more lightweight, and has worked for me well over the years. It is very simple – I leverage my existing test framework and test runner. I create an empty test fixture called Scratchpad.
This class gets committed to the VCS repository. That way every member of the team gets their own scratchpad to play with and validate their theories, ideas and assumptions. However, as the name implies, this all is a one-off throwaway code. After all, you don’t really need to test the BCL. One would hope Microsoft already did a good job at that.
If you’re using git, you can easily tell it not to track changes to the file, by running the following command (after you commit the file):
git update-index --assume-unchanged Scratchpad.cs
With this simple set up you will have quick place to validate your assumptions (and answer questions about API behaviour) with little friction.
So there you have it, a new, useful technique in your toolbelt.
I am a believer in the value of testing. However not all tests are equal, and actually not all tests provide value at all. Raise your hand if you’ve ever seen (unit) tests that tested every corner case of trivial piece of code that’s used once in a blue moon in an obscure part of the system. Raise your other hand if that test code was not written by human but generated.
As with any type of code, test code is a liability. It takes time to write it, and then it takes even more time to read it and maintain it. Considering time is money, rather then blindly unit testing everything we need to constantly ask ourselves how do we get the best value for the money – what’s the best way to spend time writing code, to write the least amount of it, to best cover the widest range of possible failures in the most maintainable fashion.
Notice we’re optimising quite a few variables here. We don’t want to blindly write plenty of code, we don’t want to write sloppy code, and we want the test code to properly fulfil its role as our safety net, alarming us early when things are about to go belly up.
What many people seem to find challenging to test is conventions in their code. When all you have is a hammer (unit testing) it’s hard to hit a nail, that not only isn’t really a nail, but isn’t really explicitly there to being with. To make matters worse the compiler is not going to help you really either. How would it know that LoginController not implementing IController is a problem? How would it know that the new dependency you introduced onto the controller is not registered in your IoC container? How would it know that the public method on your NHibernate entity needs to be virtual?
In some cases the tool you’re using will provide some level of validation itself. NHibernate knows the methods ought to be virtual and will give you quite good exception message when you set it up. You can verify that quite easily in a simple test. Not everything is so black and white however. One of diagnostics provided by Castle Windsor is called “Potentially misconfigured components”. Notice the vagueness of the first word. They might be misconfigured, but not necessarily are – it all depends on how you’re using them and the tool itself cannot know that. How do you test that efficiently?
One possible solution to that, which we’ve been quite successfully using on my current project is approval testing. The concept is very simple. You write a test that runs producing an output. Then the output is reviewed by someone, and assuming it’s correct, it’s marked as approved and committed to the VCS repository. On subsequent runs the output is generated again, and compared against approved version. If they are different the test fails, at which point someone needs to review the change and either mark the new version as approved (when the change is legitimate) or fix the code, if the change is a bug.
If the explanation above seems dry and abstract let’s go through an example. Windsor 3 introduced way to programmatically access its diagnostics. We can therefore write a test looking through the potentially misconfigured components, so that we get notified if something on the list changes. I’ll be using ApprovalTests library for that.
[Test]
public void Approved_potentially_misconfigured_components()
var container = new WindsorContainer();
container.Install(FromAssembly.Containing<HomeController>());
var handlers = GetPotentiallyMisconfiguredComponents(container);
var message = new StringBuilder();
var inspector = new DependencyInspector(message);
foreach (IExposeDependencyInfo handler in handlers)
handler.ObtainDependencyDetails(inspector);
Approvals.Approve(message.ToString());
private static IHandler[] GetPotentiallyMisconfiguredComponents(WindsorContainer container)
var host = container.Kernel.GetSubSystem(SubSystemConstants.DiagnosticsKey) as IDiagnosticsHost;
var diagnostic = host.GetDiagnostic<IPotentiallyMisconfiguredComponentsDiagnostic>();
var handlers = diagnostic.Inspect();
return handlers;
What’s important here is we’re setting up the container, getting the misconfigured components out of it, produce readable output from the list and passing it down to the approval framework to do the rest of the job.
Now if you’ve set up the framework to pup-up a diff tool when the approval fails you will be greeted with something like this:
You have all the power of your diff tool to inspect the change. In this case we have one new misconfigured component (HomeController) which has a new parameter, appropriately named missingParameter that the container doesn’t know how to provide to it. Now you either slap yourself in the forehead and fix the issue, if that really is an issue, or approve that dependency, by copying the diff chunk from the left pane to the right, approved pane. By doing the latter you’re notifying the testing framework and your teammates that you do know what’s going on and you know it’s not an issue the way things are going to work. Coupled with a sensible commit message explaining why you chose to approve this difference you get a pretty good trail of exception to the rule and reasons behind them.
That’s quite an elegant approach to a quite hard problem. We’re using it for quite a few things, and it’s been giving us really good value for little effort it took to write those tests, and maintain them as we keep developing the app, and the approved files change.
So there you have it, a new, useful tool in your toolbelt.
When building applications it is very common to have a set of screens which are basically list/edit screens. And when having these list/edit screens it is also common to allow users to delete a row. In this post I am going to show how you can add a neat little UI wrinkle to your deleting action which will be visually appealing but will also allow users to undo their changes with ease.
If you take a look at the screen shot below you will notice that I have a data grid with 2 line items. You should also notice that at the far right of each row is a ‘Red X’ which can be used to delete that selected row. Commonly when you have this type of delete action the row will be removed from the UI in real time. Having the row removed in real time is ok but it does give the user an easy way to undo their actions prior to committing their changes. What I would like to do is change this.
In the screen shot below you can see how we have accomplished the ability to mark a row as being deleted yet still give the user the ability to undo a given deletion. What we have done is 2 things.
Since we know what we want to accomplish how do we actually do it.
private bool _deleted; public bool Deleted { get { return _deleted; } set { _deleted = value; OnPropertyChanged(() => Deleted); } }
BoolenToVisibilityConverter Code
public class BooleanToVisibilityConverter : IValueConverter { public Visibility TrueValue { get; set; } public Visibility FalseValue { get; set; } public BooleanToVisibilityConverter() { TrueValue = Visibility.Visible; FalseValue = Visibility.Collapsed; } public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null) { return Visibility.Collapsed; } return ((bool) value) ? TrueValue : FalseValue; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
As you can see you can implement a slick UI which shows the user an item has been deleted with very little effort.
What Happened To Me
I’d say that 2011 was a pretty good year for me as a .NET open source developer. After all, Caliburn.Micro had it’s first official release in April 2011 just in time for the Mix Open Source fest. At the festival, the framework had a great showing. I had tons of people literally coming up to me and dumping *all* their voting tokens into my bucket. In fact there were so many people constantly standing around my booth that my bucket didn’t even get collected for counting in the official vote. Thankfully someone standing around realized this and helped to remedy the situation. Needless to say, it was a successful event. Over the next several months I did two additional non-trivial releases and then began work on the v1.3 release. I also added support for Silverlight 5, WP7 Mango and preliminary support for WinRT/Metro. Furthermore, I began refactoring the entire framework so that it could be modularized into “feature” packages allowing a variety of different uses of the framework via Nuget. I even tested CM’s EventAggregator and IoC container to make sure they would run without issue on iOS and Android devices via Unity3d. In addition to the actual framework development, I wrote documentation, blogged, fixed dozens of bugs and added new features. I also participate daily in the Caliburn.Micro forums which currently have about 1k discussions. Caliburn.Micro is now used as the core enabling framework for thousands of applications across WPF, Silverlight and various versions of WP7. Depending on the day, Caliburn/Caliburn.Micro is the second or third most trafficked Xaml-related open source project in existence.
I’m not trying to toot my own horn here. I’m just trying to set up a context. Considering the enormous amount of work in both creating the project and supporting the community…you can imagine my surprise when I received the “form letter” stating that my MVP was not being renewed because I hadn’t accomplished enough in the last 12 months….and what I did do did not “stand out” in the community. Here’s the actual quote:
“The MVP Award is presented to individuals for their past year’s contributions to online and offline communities, which stand out from others in the communities that focus on Microsoft technologies. Your contributions were diligently evaluated over the past year against the contributions of others in the Silverlight community. As a result of this evaluation, you were not awarded as a MicrosoftMVP for the January 2012 award cycle.”
Now, I’m not really “attached” to being an MVP. I don’t attach a lot of self-worth or emotional satisfaction to it. It’s a nice thing to have though. So, I was really caught off guard by this and wondered how the MVP program could come to the conclusion that I hadn’t significantly contributed in the last year.
What I Did
Being surprised as I was, and not being too fond of “generic” letters , I made one simple tweet:
“Apparently Caliburn/Caliburn.Micro and my support of it is not a ‘good enough’ contribution for Microsoft. I lost my MVP this year.”
The Community Response
Immediately following this tweet, a storm of people responded with great affection for my work and general encouragement. I want to say thank you to everyone who responded so kindly. Paired with the encouragement was a general sense of befuddlement around how the MVP program could make such a conclusion. Apparently, I wasn’t the only surprised individual.
I thought to myself “mistakes happen.” But as I was surveying the twitter-verse, I also learned that Jeremy Miller (StructureMap, FubuMVC, Storyteller) and Daniel Cazzulino (Moq) also lost their MVPs; two other prominent open source developers. Now I had had some problem during the re-evaluation process indicating my new MVP Lead clearly didn’t understand the nature of open source. When I was up for renewal, he asked me to fill out a rather ridiculous spreadsheet. If you could see it, you would notice something missing? There’s no category for Open Source!!! There’s not even a way to report it. I had this problem in previous years when I was asked to update my online MVP profile (a hideously painful UX by the way). The program uses that to evaluate you as well. Guess what? There’s no way to report Open Source work!!! Do you see a trend here?
--Start Rant
The thing that really disturbed me was that my MVP Lead didn’t know who I was or understand the nature of my contributions. What is it that an MVP Lead does anyways? I can’t tell. I get a useless mass email every week or so telling me things about Microsoft I don’t care about. Half of the time it isn’t even readable due to bad formatting, etc. My Lead never contacted me personally during the year. When I came up for renewal, I had to *defend* why I should have my award renewed using a bad Excel spreadsheet and a really bad online form which don’t even allow me to capture my real contributions. Shouldn’t it be an MVP Lead’s job to know his MVPs and what it is they are doing? Seriously. I sat down and calculated how much time it would take me to fill out the Excel form and the online form, plus writing a custom report for everything that wasn’t able to be captured via those broken mechanisms. I took that number of hours and multiplied it by my hourly consulting rate and determined that the money I would make working exceeded the material value of the MVP award. Haven’t I given enough free work to Microsoft? This isn’t a personal attack on *my* MVP Lead. I don’t know the guy. But, I wonder whether the role of MVP Lead is improperly defined or under-defined, because I know that I’m not the only person who has had this exact problem repeatedly.
--End Rant
Microsoft Employees to the Rescue
Also following my tweet, a number of Microsoft employees stepped in to investigate. I have to thank them here personally. Much thanks to you (in no particular order) Tim Heuer, Pete Brown, Joe Healey, Glenn Block and Scott Hanselman. At one point I heard that this issue had even been escalated internally to Scott Guthrie. It’s truly an honor that so many well known and respected individuals *inside* Microsoft stepped up to personally investigate my situation. Thank you again. This is a tremendously good thing and points out something of great importance. Over the years I’ve very rarely had negative experiences with individual Microsoft employees. But, I’ve almost always had bad experiences interacting with groups, programs, etc. It seams that somehow the opinions of the individuals are lost in the system. That’s a real shame.
If the opinion of many trusted Microsoft employees and the opinion of so many community members is not reflected in the MVP Award, then there certainly is a problem with the program…or I don’t understand what the program is.
An MVP Again…for a few hours
Thanks to the work of the gentlemen listed above, I was informed last night that I was being re-awarded an MVP for the 2012 year. I understand this sort of thing never happens. But, I’d already had several days to reflect on the MVP program and had several conversations with various people leading to several realizations listed above and several more detailed below. I was very unsettled.
Why I Turned Down the MVP
This morning I responded to the award email with a respectful decline. Below are some of the reasons I chose to no longer be a part of the program and why I doubt I will participate again, unless serious reform happens.
Becoming an MVP
One of the problems with the MVP program is that the whole thing is basically a mystery. Here’s where I first knock heads with the program. I value transparency and openness, even if it’s difficult or sometimes painful. The MVP program does not value openness. That’s why it’s basically a mystery how you get nominated for an MVP or what you have to do to get one. Let me do a little exposé here. In my case, I’m fairly sure that my local Developer Evangelist saw the work I was doing in the local community and submitted me. That’s a good thing and it’s probably fairly common. But what happens from there? It’s my understanding that it’s completely out of DPE’s hands at that point. Who knows? From what I can tell, if the MVP program is interested in you, you then have to submit proof of your accomplishments to them. I remember doing this. It’s not like a normal award where the organization does the work to investigate your contributions and then decides whether or not to give you an award. No. If you are being considered for nomination, you literally have to *sell* yourself to the MVP program…and selling is exactly what you are doing. Want to know why? Have you noticed that the MVP disciplines are strictly organized around internal product groups, regardless of how hindering to the particular MVP discipline it appears to be? An example of this is that Client AppDev, Silverlight, WP7 and Blend are all separate MVP groups even though they should be unified. Because they are different products, they are different MVPs (actually, they should all be the same product, but that’s a subject for another blog post). Do you know why this is? I’ll tell you: because each product group literally gets an MVP “budget” which they use to “purchase” MVPs for the year. Personally, I’m offended by this notion. But it would take drastic re-organization of the MVP program to fix it.
General Life as an MVP
Now you can just imagine how this division along product lines and MVP purchasing might affect things. Because Microsoft’s product teams are notorious for not only being non-communicative with one another but are often pitted against one another by the upper level management…the various product teams can develop a vastly different set of values and beliefs with respect to interaction both internally and with the outside world. Depending on what MVP discipline you are a part of…and the nature of your contributions…you may have a great experience or you may be in store for hell. If the product group you are associated with is open, such as ASP.NET, you can expect lots of interaction, incorporation of your feedback into the product and probably a deep respect of open source work. If your product team is something like WP7, you can expect much less communication, very little change to the product based on your feedback and probably…they don’t even know what open source is.
My Life as an MVP
As for myself, it’s clear that my major contribution is through an open source framework. What a fool I was…there’s a certain insanity in building an open source framework on top of a proprietary UI stack. Back when I was awarded the MVP, I was given the Client AppDev designation, which basically means WPF (but for some reason, contrary to what I’ve said above, also included WinForms..interesting how they had WPF and WinForms in the same group but not WPF and Silverlight…but I digress…or do I?). Back then Xaml tech wasn’t so secretive. When Silverlight came along, they moved me into that group. That group was different. Silverlight was kept tightly sealed. When I was a Client AppDev, I actually felt like Rob Relyea and John Gossman were my kin. When I became a Silverlight MVP, I felt like I was an outsider being graced with a little tiny window to peer in on things. I say all that because when I started on Caliburn, while I was working on a proprietary platform, it felt more open. But when Silverlight came along, things changed. WP7 was even worse than Silverlight…and WinRT/Metro…well…they didn’t talk to anyone. Now that Xaml has moved out of the Developer Division and into the Windows division, it’s only going to get worse.
Secret Societies
I’ve already mentioned how the organization of the MVP groups along product lines can be a hindrance to everyone. WPF, Silverlight, WP7, Metro and Blend…which are all used by the same group of people, are actually different MVP groups. As a Silverlight MVP…I had no access to anything happening with WP7. I had no knowledge of WinRT/Metro. I had no knowledge of Blend or any mechanism to directly interact with that product team. Now, Caliburn.Micro spans all of these technologies, but I could really only talk to Silverlight product team members…and a few of my old WPF comrades. But would it surprise you if I told you the organizational absurdity went even farther. Did you know there are “insiders” groups. “Insiders” for a particular product group have more privileged knowledge than MVPs and more opportunities for direct interaction. Some MVPs are also insiders, but not all. Some insiders are not MVPs. But wait, there’s more. There’s also the TAP program….which seams to have more privileged connections and knowledge. To this day, I don’t know how one gets in a TAP program. I was in the WP7 Tap for about two days. Some guys already in the program were talking in the TAP forums about getting Caliburn.Micro working on WP7. They yelled loud enough and the powers that be invited me, since it seamed that significant apps were likely to be built with my framework. Unfortunately, things went public very shortly after that and the TAP was closed. LOL. But it doesn’t end there. It seams, based on observation, that there are even more secretive groups…who pretty much know everything the product team knows. These guys don’t have a name and I don’t know how you get into that. Though, I’m pretty sure it has to do with being “chummy” to the right people. Childishness. The bottom line is that there are too many levels of secrecy and too many and the wrong types of divisions to enable an effective feedback loop. I don’t know if this is true of all MVP groups, but it was with Silverlight and it has got worse with each successive Xaml platform. Now that Xaml is in Windows, I don’t expect anyone to be able to provide decent feedback.
Fruitlessness
Since things are so improperly organized, there are really only a few occasions where one can really provide good feedback on the product. Unfortunately, after three years as an MVP, I have to say that not a single bit of feedback I provided resulted in any sort of change to the product. With the Silverlight team..and almost always with the Blend team (when I could actually run one of them down), I would get some response like “yes, we’ll have to have a conversation about that.” And I’d be thinking…”isn’t that why I’m here at the MVP summit talking to you now?” But they never seamed to want to engage in a real discussion on *anything* that affected me, my project or my clients. I had this happen every year at the summit. I had even more outrageous things happen in email and at BUILD. On the insiders email list (when I finally got on it), I tried to start a conversation about Convention over Configuration and improvements to tooling that would help support those scenarios and generally make tool extensibility better. Somehow I managed to get into a private email thread of the Blend team where they could engage me on that. You know what they said when I tried to continue the conversation? They said “we don’t want to discuss that right now.” Ok…thanks. That made me really mad. Why am I an MVP again? But the real treat was at BUILD. I managed to track down two of the Blend PMs. I first talked to the PM in charge of the JavaScript Blend work. I told him about what I was building in JavaScript. He was really interested and wanted to follow up with me on what I was building and how it would work inside Blend. Then I took several steps to the right to talk to a Blend PM working on the Xaml side of things. I tried, once again, to discuss CoC. I know for a fact these guys either don’t understand it or don’t think it’s important in software at all. Well, they listened for a moment, then I asked about improving the tooling so I could have a plugin mechanism by which to improve that scenario for my customers. They were very not-helpful. I tried to bring up issues of developer productivity and better strategies for building applications. In a nutshell, the PM basically said to me “we don’t care about developers…they aren’t part of our use cases.” I was pretty enraged by that. See how the product team’s culture affects the effectiveness of the MVP program? My main point though is that nothing I ever said or did affected any product team’s work. Nothing. It was a waste of time and energy…and an emotional drain.
MVP Quality
Now I want to tread lightly here with how I say this….not all MVPs are created equal. I’m going to be vague here. I met an MVP once for Technology X. It turned out that she had never built anything with Technology X and wasn’t overly knowledgeable about it. She liked Technology X a lot though. Each day she would scan her RSS feeds and post about 8 - 10 links on Technology X. That’s why she had her MVP. It looks good on a review doesn’t it? I blogged 365 posts on Technology X this year!! Now, I’ve met some MVPs in various areas that were brilliant and obviously contributing a lot. But, I’ve met a fair share of MVPs who not only were not experts on the technology, but didn’t make half the contribution that other developers I knew did, who were never awarded MVPs. Not all MVPs are equal. If you are an employer, or looking for a speaker, expert, consultant…whatever; you cannot assume that just because that person has an MVP that they know what they are talking about. It’s sad, but this describes a noticeable number of MVPs.
One more word on MVP quality with respect to division along product team lines. You should never hire a highly product-specific MVP to help advise you on technology choices. I hope you realize the built-in problem with that. I know very few Technology X MVPs who would tell you not to use Technology X, even if there was a better, cheaper, faster way to build your solution. Be wary.
Open Source
I just want to say a little more about this. As I mentioned, there’s nothing about the MVP program that explicitly allows for recognition of open source work. It’s hard to get nominated for it and it’s even harder to renew with it. MVP leads who play a major roll in the renewal process may not be technical at all and even may not understand Open Source. Since I’ve mentioned how MVPs are linked to product groups, you might guess that the effectiveness of your MVP as an OSS developer is entirely dependent on that particular product group’s understanding of and interest in OSS. In a group related to ASP.NET or JavaScript, developers on the team are likely to have run open source projects themselves. In a group like Silverlight or WP7, they are likely to have never done such a thing…and not even have a clear idea of what is involved. I really came face to face with this when my non-renewed MVP…got renewed. Why? Well, it felt like a sort of “benefit of the doubt” renewal. Here’s the advice I was given from the renewal email, elided:
EDIT: I removed this quotation because a good friend of mine was honest enough to remind me that quoting a personal email is neither professional nor polite. I repent of that.
What!? I released one of the most popular Xaml-related OSS project this year. I did multiple version releases, nuget packages, podcasts, documentation, forum support…the list goes on. What more do you want from me? And what should I do next year…because Caliburn.Micro is so popular, that in order for me to do something bigger for next year…I’d have to dump it entirely….completely abandoned it and build something totally different…something even more popular for Silverlight!? How could I do that to my community? That’s not even nice. No, in 2012, I’m going to continue to fix bugs, add features, add platform support and do awesome things with Caliburn.Micro. I love my own community and I’m going to continue to work hard and support them.
Now this kind of comment clearly expresses a deep lack of understanding for both the value of a project like Caliburn.Micro and the amount of time and resources it takes to maintain both the project and the community. If your OSS project is successful, it’s not just something you do one year and then move on to something else the next. In fact, building the first version of Caliburn.Micro was the easy part! It’s everything that’s happened afterwards and what is happening now that is hard work and will continue to be.
Unfortunately, Microsoft just doesn’t have a way of recognizing OSS developers who improve their platform. The MVP program doesn’t do this and the product teams may not either. In fact, Balmer has explicitly said he isn’t creating any policy around OSS…he’s totally dodging it entirely. This leaves the decision up to the individual teams…which sometimes goes well, but often times does not. That’s irresponsible leadership.
Career Affects
No one ever hired me as a consultant because I had an MVP. They hired me because of my open source work and my recognized expertise in UI architecture. The company I’m working for…I don’t even think they know what an MVP is. They hired me because they know *me* and know I can help them with their particular problem. I would say the personal career benefits of having an MVP are a wash except…
With Microsoft’s less than above the bar treatment and communication about Silverlight over the last year or so, you might imagine this could effect MVPs associated with the program. I’ve heard a lot of horrible stories in the last year. I didn’t have anything terribly bad happen to my business, but I was quite embarrassed recently. I was attending a .NET user group meeting, of which I am the president. Somehow I or someone else mentioned that I was a Silverlight MVP. I don’t remember the detail about how it came up, but I do remember what happened next. Someone laughed at me. Literally, I was made fun of because my MVP had the word Silverlight attached to it. Now, I’m just not willing to endure mockery for the sake of Silverlight, especially since I understood exactly why he was laughing at me. It has got to where being a “Silverlight” MVP is bad for my career.
My Happiness
Looking over the last three years, I’ve definitely been a less happy, more frustrated developer. I’m sure it’s linked to the sort of fake “value” being a Silverlight MVP gave me. Basically, they give you a couple of cheep gifts, then they pretend to listen to your feedback, while not actually doing anything. Year after year of that and you get really unhappy. It’s demoralizing. You start to realize that you really are a commodity. You are purchased by a product group and kept around as long as they perceive they need you…your feedback is allowed, but not effective. Again, it’s probably not the case for all MVPs, it depends on the groups. I just don’t need that in my life.
Conclusion
I’m saying goodbye to the MVP program even after I was re-offered the award for 2012. If you’ve read this far, you can probably see why I made that decision. I’m really positive about the future of Caliburn.Micro and hopeful regarding my JavaScript framework. I think 2012 is going to be a wonderful year. If someone seriously reforms the MVP program or if Microsoft decides to properly recognize and reward open source efforts, then, maybe I’ll let them give me an award. But for now, I don’t need to suffer any more. I’m free and I’m going to do great things.
Now that Windsor 3 is released I can concentrate on some of my other ideas and projects. While working on one of them, called Cartographer, I encountered an interesting API design problem.
I have a class (a builder to be precise) that has a task of setting up a central object (an IMapper implementation) in Cartographer (If you’ve ever used Autofac, it is somewhat analogous to ContainerBuilder). What is interesting about it, is I have three goals for that class:
How would you design the API for this class?
Oh, and happy new year.
If you have created any silverlight applications which need to communicate to a WCF Endpoint you know that you must communicate with WCF via Async actions. As you may know there are multiple ways to get your Silverlight application to communicate with a WCF service. One way is to simply create a Service Reference, aka proxy. The other is to use the ChannelFactory and a shared interface. There are many good references on the net on why one is better than the other but personally I prefer to use the ChannelFactory approach as it allows for cleaner separation of concerns and it allows me to share the same interfaces/models on both side of the wire. Of course this really only works in a closed development scenario, one where you control both sides of the wire.
The issue with using the Channelfactory pattern is that by default it will create synchronous endpoints for use and this is not allowed in Silverlight. However this problem is easily solved for you and we will take a look at how to solve this.
When you typically setup a WCF OperationContract you typically do something like the following:
[OperationContract]List<Make> GetMakes();
However as you may have guessed this will create a synchronous method/endpoint when you use the ChanelFactory. In order to use this in WCF you need to make a slight change to your setup. You will need to instruct the Contract that you are following the AsyncPattern . The code below will show you how using the AsyncPattern changes your setup.
[OperationContract(AsyncPattern = true)] IAsyncResult BeginGetMakes(AsyncCallback callback, object state); IList<Make> EndGetMakes(IAsyncResult result);
As you can see from above, using the AsyncPattern = true pattern does mean we need to create 2 methods not just 1. We should take a closer look at these to better understand what is going one.
In the first method we are creating the ‘begin’ call which will return us back a IAsyncResult which will later be provided to the End method. In the second method we are making a call and passing in the IAsyncResult instance provided to us via the begin call. It is this second method which will return us back our actual data.
Now that we know how to create our OperationContract we should take a look at how to create our implementation of these contracts. The code below will illustrate how to do this
public IAsyncResult BeginGetMakes( AsyncCallback callback, object state ) { var db = new AutomobilesEntities(); var makes = db.Makes.Select( m => new Make {Name = m.Name} ).ToList(); return new CompletedAsyncResult>(makes); } public IList EndGetMakes( IAsyncResult result ) { var completedAsyncResult = result as CompletedAsyncResult>; return completedAsyncResult != null ? completedAsyncResult.Data : new List(); }
Taking a closer look above you should notice that the Begin method will actually do the ‘heavy’ lifting in terms of performing any real logic. This method also returns back a AsyncResult class (see below for that class) which will be passed into the ending call The End call. The End call will accept the provided AsyncResult instance and pull out the data payload inside of it. It will then pass this payload back as the actual results you were expecting.
Now that we know how to create an Async endpoint how to we spin up an endpoint via the ChannelFactory and make our WCF call work. Take a look at the code below for that example.
var binding = new BasicHttpBinding(BasicHttpSecurityMode.None) { MaxBufferSize = 2147483647, MaxReceivedMessageSize = 2147483647 }; var endpointAddress = new EndpointAddress(fullEndpointAddress); var channelFactory = new ChannelFactory(binding, endpointAddress); var channel = channelFactory.CreateChannel(); AsyncCallback callback = result => { var endGetMakes = channel.EndGetMakes(result); Debug.WriteLine( "I Have Makes" ); }; channel.BeginGetMakes(callback, channel);
The magic in the code above which makes this all work is to create the pointer to the AsyncCallback instance and to provide this in your Begin call.
This is the class I used for encapsulating our IAsyncResult
public class CompletedAsyncResult : IAsyncResult { T data; public CompletedAsyncResult(T data) { this.data = data; } public T Data { get { return data; } } #region IAsyncResult Members public object AsyncState { get { return (object)data; } } public WaitHandle AsyncWaitHandle { get { throw new Exception("The method or operation is not implemented."); } } public bool CompletedSynchronously { get { return true; } } public bool IsCompleted { get { return true; } } #endregion }
Using the Async Pattern in WCF is a bit more work but it will allow you to do 2 things. 1) Use the Channelfactory in WCF and 2) Create async service calls to allow your application to continue working while you wait for your call to come back.
After successful beta and RC releases final version of Castle Windsor (as well as Castle Core, and a whole set of facilities) has now been released. There are no major changes between final version and RC. The difference is some minor bug fixes, improved exception messages and some small improvements all over the place.
The packages are available now, on Nuget (with symbols), and via standard .zip download.
Last but not least - thank you to everyone who downloaded beta and release candidate and provided feedback. You guys rock.
Recently when I was working with Entity Framework inside one of our RIA Services end points I ran into the errors below while trying to save my changes. Of course at first this error caused me to stop and scratch my head
To give a bit of background on what I was doing. Inside one of our RIA calls (Off Topic, not a big fan of RIA but this is not the time or the place) we were doing a bit of background processing. In this background processing we needed to query the database for some data (as seen below), update the data and then save the data. However, when I called ObjectContext.SubmitChanges() I would get the error above. what was really odd was that I was saving on the EXACT same ObjectContext instance as the instance the data was queried from so I was a bit stumped.
Here is the original code which was causing the problems
var socialLinks = ObjectContext.SocialMediaLinks.Where( x => x.ClientID == clientId )
As you can see from the line above the code appears to be pretty harmless. I am simply reaching into my ObjectContext and grabbing all the items which match for a given client. Later on in the code I am doing a ForEach loop over the list and changing various values based on rules. However, it is this code which is causing me errors when I try to save.
After a bit of searching and staring it finally occurred to me what the issue was. Because I had never actually ‘completed’ my query the original transaction was still opened and when I called save it was trying to create and use another transaction.
To get around this issue (there may be better ways and if so please let me know) I changed my code to be the code you see below.
var socialLinks = ObjectContext.SocialMediaLinks.Where( x => x.ClientID == clientId ).ToList()
By adding the .ToList() to my query I am forcing the fetch to take place at one time, thus closing the underlying transaction to the database. Now when I saved the data (I literally did not change another line of code) everything worked just fine.
If you find your self in this situation make sure you have actually finished executing your EF queries before you save your changes. BTW this is done inherently when going across the wire which is why I have never seen this before.
Today one of our production ‘slowness’ issues finally came to a head and it was deemed a TOP priority which meant I actually had a legitimate reason to spend time working on it. The first think I did to attempt to find the issue was to fire up DotTrace from Jetbrains (killer app and very easy to use) and about 2 minutes later I had found the source of my bottle neck
Take a look at the 2 images below for an illustration of how simple it can be to find and SOLVE very large performance bottlenecks.
This is the original code. As you can see there are 12 calls (this is inside a loop) to a class called CMEHelperSupportsInstance which in total take up 141 SECONDS. Just for a bit of background this code is actually making a CORBA call across the wire to a Java server which we integrate with, which means I expect it to be a bit slow, but OMG 141 seconds slow….. GOD HELP ME
After making a very simple code change (more on that in a minute) here is the updated logic with perf numbers
As you can see from the above we are now only calling CMEHelperSupportsInstance 1 time for a savings of about 134 total seconds. What I found was that we were creating an instance of this class for EVERY iteration of a loop, which as I explained above was VERY expensive. I moved the creation of this to outside the loop and passed the instance around. This was a very simple fix but had it not been for the perf tool showing me exactly how expensive.
It is always important to make sure your application is performing as expected but without the right tools and without knowing where to look it is often very hard to find and diagnose where you have performance issues. If you have an idea of where you have issues and you have a too like DotTrace (or any other .net profiler for that matter) finding and solving issues can be very simple and very rewarding it.
You probably are aware by now that as of ReSharper 5 we added first-class support for ASP.NET MVC. This included among many things, the ability to provide Intellisense, Create from usage and Navigation to built-in methods such as Controller.View or Html.ActionLink:
Ctrl+Left Mouse Click or F12 will navigate to the corresponding View
or to the Action and/or Controller
Ability to have Intellisense when providing Actions/Controllers
as well as the possibility of creating from usage
However, what happens when you want to use a custom function, for instance, a better ActionLink or your own View method? Did you know that you can still get all these goodies? All you need to do is use some Annotations.
ReSharper uses annotations via the form of .NET attributes to figure out what an ASP.NET MVC View, Action or Controller is. As such, all we need to do for our custom method and extensions to leverage this, is tell ReSharper what parameter corresponds to what.
To use ReSharper annotations, we have mainly two options (with a third one hopefully coming soon):
1. We can include the library JetBrains.Annotations.dll in our project and reference it.
2. We can copy the annotations and include it as source in our project
[3. We can use nuget install-package JetBrains.Annotations] Coming soon!
The first option is pretty simple. The DLL is located in the ReSharper installation bin folder. For the second option, we open up ReSharper | Options and select Code Annotations entry
select the Copy default implementation to clipboard button and paste into an empty file.
Once we’ve completed this step, all we need to do is annotate our parameters with the correct attributes. We’re interested in 3 different attributes in particular:
Here is the header corresponding to a base controller with a custom method named ExtendedView
and here’s the header for a custom ActionLink
(the body of both methods are omitted and are not necessary to demonstrate the functionality)
As soon as we do this, ReSharper picks up these methods and offers us the same functionality that is provided for the methods that ship out of the box:
Notice how we still get Navigation (the underlining), Intellisense and Create from usage in our TheOnlyActionLink custom method. Its much the same for the ExtendedView method
That’s all there is to it.
TeamCity 7.0 EAP (Early Access Program) was recently opened and one of the new features is the built-in support for NuGet. I recently blogged about setting up TeamCity to pack and publish NuGet packages via a plug-in and this plug-in is now included by default in TeamCity 7. However, the real new interesting feature is that TeamCity is now a native NuGet repository too!
Many of those that have been using NuGet, have most likely been using it to consume packages from nuget.org where there are currently over 3800 unique packages, most of which are open source.
What happens however if for some reason or another you do not want to submit packages to nuget.org? For instance, think that you want to use NuGet to modularize and distribute code inside your own organization, or create libraries for private consumption. In this case, publishing to nuget.org does not make sense. This leaves you with basically two options:
Both of these options come with their own share of overhead. With the local share you now require sharing of folders and permissions. Setting up your own NuGet repository also requires managing permissions and whatnot separately. At the end of the day, its another service to manage.
Fortunately, you now have a third option: TeamCity. The same server that builds your projects, runs your tests, packs and publishes your packages can now also serve them. The best part of it is that it is so simple, that I had to take up the rest of this blog with the previous nonsense just to give it some meat.
I am not going to cover how to pack and publish packages in this post. All that is covered in detail in the previous post I wrote, so please read that first if you’re not familiar with the process. Enabling TeamCity as NuGet and making packages available consists of two steps:
Go to Administration | Server Configuration | NuGet tab
Click on the Enable button to enable it. The same screen with then display two different feeds: a public and a private one:
If by chance the Public Url is not available, you will probably see a message telling you that you need to enable the Guest account in TeamCity, which can be done from the General tab.
Since TeamCity itself is going to be a NuGet server, the step to publish a package is no longer required. However, packing the package is. In this step (NuGet Pack Build Type), we can just configure the output for the package to point to some specific folder, for instance packages
We need instruct TeamCity to ouput the results of this folder as artifacts. This is done in the General Settings step of the Build Configuration
and with that, we’re done. Next up is to configure Visual Studio to consume from this feed.
Although this step is optional, it is recommended to add your repositories to Visual Studio to avoid having to type long URL’s in each time you want to read from a specific package repository. To do this, click on Options | Library Package Manager | Package Manager Settings
We need to add a new NuGet Repository. I’ve called it Local TeamCity and the URL corresponds to the public URL provided to me by TeamCity in Step 1:
Notice that I have another entry which is Local TeamCity Auth which corresponds to the authenticated version.
Once we have this, we can now easily consume packages from our repository by merely specifying it in the Package Manager Console, either via the Combobox or explicitly in each call:
That’s all there is to it. By merely publishing our packages as artifacts, TeamCity now provides a full-fledged nuget server which opens up great possibilities when it comes to working and managing dependencies between projects. TeamCity is currently in EAP and much of what I’ve described here is in open to improvements. That is why your feedback is very important. Download 7 and start playing with it today. Let us know what you think.
Today I was building a UI in Silverlight which needed a Data Grid and a Data Pager. When I setup my pager I had it bound to the various properties that I cared about (Source, PageIndex, PageSize, etc) via my ViewModel. However when I ran the page for the first time I received the error below
At first I was a bit stumped because why in the world would I want to set my Page Index to –1 (as an FYI my Source property is NULL when first bound because of the way we lazy fetch our data. In order to get around this I did what the error told me and set my Page Index to default to –1. This worked… kinda. See it worked the first time I loaded the screen when there was NO data loaded in memory. Every subsequent loading of the page threw another exception telling me that my default Page Index had to be >= 0.
As I sat there scratching my head it dawned on me that the issue was due to the way that the XAML engine reads/parses the elements (left to right, top to bottom). I reset my default Page Index to 0 and moved my Source property to the left of my PageIndex property and this worked. Take a look below at my XAML to see the difference.
Original XAML
Correct XAML
The moral of the story is that you need to pay attention to the order (left to right/top to bottom) of your XAML properties in some places.
About The CodeBetter.Com Blog NetworkCodeBetter.Com FAQOur Mission Advertisers should contact Brendan
Subscribe Google Reader or Homepagedel.icio.us CodeBetter.com Latest ItemsAdd to My Yahoo!Subscribe with BloglinesSubscribe in NewsGator OnlineSubscribe with myFeedsterAdd to My AOLFurl CodeBetter.com Latest ItemsSubscribe in Rojo
Member ProjectsDimeCasts.Net - Derik Whittaker
Friends of Devlicio.usRed-Gate Tools For SQL and .NETNDependSlickEdit SmartInspect .NET Logging NGEDIT: ViEmu and Codekana LiteAccounting.Com DevExpressFixxNHibernate ProfilerUnfuddle Balsamiq MockupsScrumyJetBrains - ReSharper <-- NEW Friend!
Site Copyright © 2007 CodeBetter.Com Content Copyright Individual Bloggers