August 2009 - Posts
And yes, I’m a novice in VSX development, take these tips with a grain of salt *.
1. Don’t debug your own VS settings. Instead – use a different VS settings hive. When you create a project of type VSPackage – the “debug” command is automatically set to use a different hive, but if you create an addin project – not so.
The command parameters should be: “/RootSuffix YourHiveName /ranu”.
About creating a different settings hive read here.
2. Don’t use the “/ResetAddin” switch all the time. Use it only when you want to actually reset the addin. Otherwise – you won’t catch any “leftovers” that your addin leaves behind.
3. When you encounter a problem – give up. There are no solutions. Anywhere.
---
* Could be a good subtitle for the blog. Take EVERYTHING with a grain of salt**. Except salt.
** Oooh! It could be an even better subtitle for a cryptography blog!
Are you familiar / have you ever used the above pattern?
I find myself using this a lot.
Since I use (debugger break on) first chance exceptions all the time (and so should you) some operations could be troubling:
There are those which simply cannot be checked if they’ll succeed beforehand, and it’s in their DNA to throw exceptions as part of their regular operation. Those actions could be very disturbing when debugging, if you constantly break to debugger on regular operations.
Now, you COULD ignore a specific exception type from breaking in the exceptions dialog…
… but then you could miss out on the other places which throw this kind of exception in a truly exceptional manor.
So the only other option is to mark the specific point in code to be ignored, which can be done by marking a method with DebuggerNonUserCodeAttribute. Since the smallest scope is a method – we want to minimize the method content to have only the risky invocation and the catch block to make the exception go away.
Basically – we get something like this:
[DebuggerNonUserCode]
private bool TryRiskyOperationAndIgnoreSomeException()
{
try
{
RiskyOperation();
return true;
}
catch (SomeException)
{
return false;
}
}
or a slightly more complicated exception handling, like:
[DebuggerNonUserCode]
private RiskyOperationResult TryRiskyOperationAndIgnoreComExceptionForSomeErrorCode()
{
try
{
return RiskyOperation();
}
catch (COMException e)
{
if(e.ErrorCode == 0x0000ABCD) // Some errorcode
{
return null;
}
throw;
}
}
As always with exception handling – AVOID catching ALL exceptions, and limit your catch clause to the specific exception you plan on catching.
I allow myself to get excited when some tests fail. Not the bad kind of excited – the good kind which makes you think “thank god I have this test”. And those tests are usually not feature-oriented unittests.
Maybe I got used to the fact that I have feature unittests which fail when a feature breaks. I’m spoiled that way.
I’m not even talking about integration tests which make sure the system actually works.
I often get exited when a “preemptive" test finds a bug I didn’t yet write a specific test for.
HUH?
Yup.
Let’s get to a concrete example – say you have some message object in your system, on some other type which needs to be serialized. That object may be a simple envelope for a couple of strings, but it could be a root for a complex object graph. I had such message (or otherwise potentially serializable) objects in my recent projects. Marking the object as a serializable isn’t enough – all the object graph also needs to be serializeable. You find out the objects you’ve neglected to mark as such only if you happen to try to serialize an object graph with those objects in run time (integration tests, hopefully).
I have another solution – a “SerializationTest”. This tests gets a message object (graph root) and checks if it is serializable, if all its members are serializeable, if all types which derive from it are serializeable and if its base type is serializable. Repeat recursively.
Now I have an early warning if I create a new object which could, in some way, be included in the message object.
And I’m a forgetful man. I need that test. :)
Bug preempted.
Code below:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using MbUnit.Framework;
namespace TestGen2._Tests.Archetypes
{
[TestFixture]
[Author("Ariel Raunstien", "emailRemoved")]
public class SerializationTests
{
[RowTest]
[Row(typeof(MessageRootType))]
public void All_objects_reavchable_from_root_type_are_serializeable(Type rootTypeToCheck)
{
//Exclude testing these types
var testedTypes = new HashSet<string>{
typeof (object).FullName,
typeof (ValueType).FullName,
typeof (Array).FullName
};
TestAllRelatedTypesAreSerializableRecursively(rootTypeToCheck, testedTypes, 0);
}
private void TestAllRelatedTypesAreSerializableRecursively(Type type, HashSet<string> testedTypes, int level)
{
if (type == null ||
type.IsGenericParameter ||
testedTypes.Contains(type.FullName) ||
type.IsPrimitive ||
type.IsEnum)
{
return;
}
string typeName = type.FullName;
for (int i = 0; i < level; i++)
{
Debug.Write("| ");
}
Debug.WriteLine("Tested type " +typeName);
testedTypes.Add(typeName);
if (type.IsArray)
{
TestAllRelatedTypesAreSerializableRecursively(type.GetElementType(),testedTypes, level + 1);
return;
}
bool shouldTestType = !type.IsInterface;
if (shouldTestType)
{
Assert.IsTrue(type.IsSerializable,string.Format("The type {0} is not serializable", typeName));
}
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var info in fields)
{
TestAllRelatedTypesAreSerializableRecursively(info.FieldType, testedTypes, level + 1);
}
var props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var info in props)
{
TestAllRelatedTypesAreSerializableRecursively(info.PropertyType, testedTypes, level + 1);
}
TestAllRelatedTypesAreSerializableRecursively(type.BaseType, testedTypes, level + 1);
var derivedTypes = type.Assembly.GetTypes().Where(type.IsAssignableFrom);
foreach (Type derivedType in derivedTypes)
{
TestAllRelatedTypesAreSerializableRecursively(derivedType, testedTypes, level + 1);
}
}
}
}
Yesterday the highlight of my day came early. You know how it is – you have fun solving an interesting bug and then it’s all downhill from there.
My colleague had come to me with a problem. First thing’s first – I asked him if he changed anything remotely related (no), then I checked locally (no repro), then I told him to commit everything (we’re two developers on the project, so we can allow ourselves to check in half-baked (but compileable) code in case of emergency), then I did the same, and then we both checked again (no repro on my machine, still happens on his), we then proceeded to delete the entire working folder to make sure everything is “pure SCM” (no, I will not trust my SCM) (no help on the bug, btw).
Then we decided to call it a day, but started thinking about environment variables, installation tests which were performed, GAC cache issues, and all sorts of fun ideas.
The following day I got to actually debug on his machine. The bug manifested itself as a StackOverflowException (SOFE) in StructureMap’s object instantiation code. Figuring out which components cause a circular dependency with StaructeMap isn’t trivial, but it’s easy once you know the trick. And a dependency cycle is the best bet with SOFE.
Side note - How to decypher the dependency cycle: What you want to do is review the call stack for lines beginning with something like “Builders73d4fd0ff16041cb96d035c9d9d03163.dll”. This is the (attempted) instantiation of a type whose namespace and name are immediately after the dll name, so for class named Company.Product.Project.Folder.TypeName the line would say something like “Builders73d4fd0ff16041cb96d035c9d9d03163.dll!CompanyProductProjectFolderTypeNameInstanceBuilder6d0fbe7cb39a40baa03f8e78e372477d.BuildInstance() + 0x53 bytes” (your GUIDage may vary). if you spot all those lines – you’ll catch the types leading to a cycle.
So that’s how you find the SOFE cause with StructureMap initialization. Why did I go there?
Ah, yes, the bug.
It turns out that while this happened on his machine – on my machine the original instantiation wasn't even attempted.
The bug was caused because of some IEnumerable.First() call which returned one value on my machine and another on his. What could populate a collection in a manor that is indeterminate between machines? Well, I did have a collections of plugins do some work (add an item to a collection), but those plugins were retrieved by StructureMap (from only one assembly, yes), and the code is identical on both our machines – again, what could reorder them?
Long story long – the both of us worked on two versions of VS08 (one with SP1 and the other without), and although the code is the same – the compiled assemblies were not. StructureMap’s “Assembly.GetAllTypes()” simply returned arrays ordered differently! The plugins were created in a different order, ran in a different order, and resulted in different outputs.
Well, that’s all I’ve got to say about that. And yes, I enjoyed the hunt.
Quick postmortem:
- We keep working on two versions of VS. Now I tend to think it’s actually beneficial to find bugs earlier.
- We did not make any change to the initialization code, but changed that “IEnumerable<T>.First()” call into something more well defined. We basically don’t make any assumptions about the order of collections, unless the ordering is explicit.
I’m referring to the tests you wrote just to repro some exception. Most other tests (especially if you take a TDDish route) are meaningless without an expectation.
A regression test for an exception is a great safety net to have, and a good indication that your problem is gone, once it’s actually gone.
If you’re like me - you wrote your test without an assertion. It wasn’t really necessary at that point, since the test failed. A failing test is the first step on RedGreenRefactor, right?
It is, but that’s not the last step you need to take with that test.
After getting the test to pass you need to get back to it and add an assertion. Why? Because now this is not just a regression test – it’s a first class citizen in your unittest suite. This test represents a feature. Moreover – it represents an untested feature. We know this for a fact because it we would have had a test for this feature – we would have seen the aforementioned exception (the root for authoring this test).
Now, if this test tests a feature – there are some conditions for that feature’s correct behavior. Assert on them. Now you have a real test, which checks functionality, and not a specific implementation.
---
* Replace “feature” with “user story” or “requirement” wherever you fell.
* And when I say “Add an assertion” I mean just that – don’t go back and change the rest of the test because if you will – you would no longer have a test which “failed at least once”.
A couple of days ago we’ve added a lovely new concept in our test suite – a KnownIssues root folder for tests.
In our tests project we previously had a root folder for “Unit” and “Integration”, and under those folders the folder hierarchy from the tested project is duplicated. All very standard.
You can probably understand what the meaning of the new “KnownIssues” folder is: all newly discovered bugs are converted into failing unittests, and then marked with “Ignore” if they are not otherwise fixed. (actually – they are included in a test fixture marked “Ignore”, so that it would be easier to “recheck” if the bugs have “magically disappeared”).
For bugs we know exist buy cannot repro with a small enough test (or just don’t have the time") – we add a test (properly named to explain the bug) with an “Assert.Fail(“Unreproduced yet”);”.
Code-based issue tracker. I’ll let you know if it actually works out on the long run. :)
I’m thinking about possibly extending this methodology to connect the failing tests to a live “issueId” in a live issue tracker, and let the automatic build close bugs for me if it sees a previously failing test now passing.
---
Oren had a post about how his team thought about an edge case to some feature implementation, and his response was “let the user fill in a bug report”.
I would say “write a failing test in the KnownIssues and forget about it”.
Israeli developers (MSFT oriented) will be enjoying a convention of a new breed pretty soon. Ken Egozi has organized the IDCC – a convention with an open agenda – you vote for the sessions you want to hear. It’s not an Alt.Net OpenSpaces conference; there are still lecturers and a structure, but that structure is defined by the audience. Wonderful.
So you can now stop complaining that all the conferences are too marketing and hype oriented, and help this new concept.
You can also vote for my session, but only if you think it’s a good one.
…
Nah, I’m just kidding, vote for me anyway. Go, go, go.
My GOD!
It seems like the only thing I CAN do on my machine right now is write a blog post.
Several non-random thoughts:
- VPC sucks. Sorry. I’ll be downloading VMWare server as soon as the installation on the VPC finishes. And I hope to god that the VPC2VMWare won’t take the second part of my day away.
- VS08SP1 installation takes longer than VS08 installation. WTF?!
Microsoft, darling, sweetness, honey, I’m addressing to your heart, MAKE THINGIE WORKIE FAST! - I have a fun Dell Latitude E4300, with a freaking SSD drive (not alone, I know). I should be seeing the world moving in slow motion. Have I made a mistake? (I cannot find a link to an article I’ve read a couple of months age, comparing several SSDs in real scenarios. It basically said that there are extreme performance differences between models. If you’re looking to buy a new machine – check out those issues)
No, no I did not. But I wrote some code that kinda felt like I did.
Problem: I have an Assembly and I want to load all of its Types and all types in all referenced assemblies (recursively). BTW – did you know that the BCL has a cyclic reference? Well it does, and it sucks (System.Xml<->System.Configuration for one. There are others involving mscorlib). Stackoverflows galore. :)
Now, if you want to get an assembly’s referenced assemblies you need to invoke the aptly named Assembly.GetReferencedAssemblies(). That method, however returns an array of the AssemblyName classes. That class does not provide some core properties, like is it in the GAC or its location. I’m not sure if it should, but is causes a situation where I need to write the following loading code:
public Assembly GetAssembly(AssemblyData assemblyData)
{
if (assemblyData.IsInGac)
{
//GACed assemblies will definatly be loacated like this
return Assembly.Load(assemblyData.Name);
}
else
{
//unGACed assemblies MIGHT be located using private paths,
//but I will concede loading them into the "Load" context, and settle for the "LoadFrom"
return Assembly.LoadFrom(assemblyData.Location);
}
}
public IEnumerable<AssemblyData> GetReferencedAssemblies(AssemblyData assemblyData)
{
Assembly assembly = GetAssembly(assemblyData);
foreach (AssemblyName nameOfReferencedAssembly in assembly.GetReferencedAssemblies())
{
if(assemblyData.IsInGac)
{
//if the original assembly was GACed - so are its referenced assemblies; no need to load the
//real assembly and just create assemblyData object
yield return new AssemblyData(null, true, nameOfReferencedAssembly.FullName);
}
else
{
//otherwise - we need to load the assembly to get its location
Assembly referencedAssembly = LoadAssembly(assemblyData, nameOfReferencedAssembly);
yield return new AssemblyData(referencedAssembly.Location, referencedAssembly.GlobalAssemblyCache, referencedAssembly.FullName);
}
}
}
private Assembly LoadAssembly(AssemblyData assemblyData, AssemblyName nameOfReferencedAssembly)
{
//try to laod and hide the exception
Assembly referencedAssembly = TryNormalLoadAssembly(nameOfReferencedAssembly);
if (referencedAssembly != null)
{
return referencedAssembly;
}
//if loading the assembly normally failed - deduce the most likely search path by getting the path
//of the referencing assembly
string supposedAssemblyDirectory = new FileInfo(assemblyData.Location).DirectoryName ?? "";
string supposedAssemblyLocation = Path.Combine(supposedAssemblyDirectory, nameOfReferencedAssembly.Name);
//try both "exe" and "dll" files
if (File.Exists(supposedAssemblyLocation+".dll"))
{
return Assembly.LoadFrom(supposedAssemblyLocation + ".dll");
}
if (File.Exists(supposedAssemblyLocation + ".exe"))
{
return Assembly.LoadFrom(supposedAssemblyLocation + ".exe");
}
throw new ApplicationException("Assembly was not loded; referenced assembly " +
"probably located in a valid probing/private path for the applciation ");
}
[DebuggerNonUserCode]
private Assembly TryNormalLoadAssembly(AssemblyName nameOfReferencedAssembly)
{
try
{
return Assembly.Load(nameOfReferencedAssembly);
}
catch
{
return null;
}
}
(The “AssemblyData” object is my abstraction for the assembly.)
I feel like a binder. I don’t like it.
And yes, the issue of private paths is still open. I’ve selected not to tackle it (since I’m not required to).
I haven’t installed MSDN on my machine the last three or four years, so I cannot testify to the repercussions, but I do have an F1 key on my keyboard, and it does sit dangerously close to the actually useful Esc key.
The solution? Remap all the help keys. Help Begone!
It’s a great feeling to accidently press F1 and not curse immediately after. sometimes I flirt with danger, and press F1 intentionally. It’s a game of Russian Roulette, only instead of bullets – I hope that the keyboard mappings were not magically reset.
(Pre-post update: it seems like just about every commenter on Roy’s Post said the same thing. Well… Good for the Tuna.)
I’ve grown to like IoC containers. It’s no surprise. The concept does indeed kick ass. (I won’t explain what they are or what they do. No need to reiterate the discussions of 3 years ago, or that article from Martin Fowler I’ve linked two lines ago.)
I also like concept of autowiring or autoconfiguration based on convention. I LOVE the fact that you can let StructureMap do all my dirty work like this:
public void BootstrapStructureMap()
{
ObjectFactory.Initialize(
x => x.Scan(
y =>
{
y.TheCallingAssembly();
y.WithDefaultConventions();
}));
}
Yes, that’s ALL the configuration I have centralized. (marking singleton behavior is something I prefer to do on the type itself, and not in a central configuration)
The best part about this whole thing is that unlike most “right” things we do in software – this actually saves you time on the long term, short term, AND the immediate term. You write less code to create a more sustainable application. Who can say no to that?
And let’s be clear about it – I know very little about how to use SM, but the little I know – works great. I use construction dependencies injection almost exclusively, and no other fancy injection (like property injection. Real fancy, ah?) methods, and let the container slide everything around.
This could cause some problems, in case you have created some circular dependency between your components (ctor of type A needs an instance of B, which in turn needs an instance of type A). I often find this out when I run a some test and TestDriven crashes because of a stack overflow. Fun. :)
(I can’t promise this post will talk about anything remotely connected to seeking or destruction. Let’s see where we go.)
So Patrick sais you don’t need an installer. XCopy deployment was one of the great white hopes of .net, and by god we can make it happen.
I strongly disagree.
There are those things in software development that should not be on the table. A proper installer (MSI) in one of them. And the scope or size of the product has nothing to do with this, nor do the deployment complications. It’s like usability testing and security reviews – you just do it.
Now for the “why”:
Installation is a part of the software lifetime on the user’s machine. She is used to it, and should not be surprised when it’s not there. It’s a standard (Next->Next->Finish rings a bell?)
Installation provides a central place for the user to see “what she has” on the machine using the Add/Remove programs screen (appwiz.cpl in the “run” box, if you didn’t know about it. Saves time.) That sort of inventory is important, even to power users and developers.
Installation “often” requires elevated privileges to complete, and the normal operation does not, so burdening runtime with elevation is pointless. I said “often” because.. well… sometimes developers allow themselves to assume there are no security restrictions. (Have you disabled your UAC lately?)
Installation is a good place for the user to decide which features she wants, and how much space to take. Patrick sais:
Certainly, some users missed that point at first glance. But we assume that as soon as the user wishes to integrate NDepend with VisualStudio or Reflector, he knows where to find the integration button.
No, man, this is the point you tell yourself that a) no, they won’t know where to find it. They won’t event think to look; b) if some users missed it - that actually cost you money (developing a feature for less people which gets less word-to-mouth marketing); and c) if you need to post an image in your blog showing the users where the “install advanced features” button is – that’s a UX smell.
Yes, I’ll stop enumerating why installers are important. There are more reasons, some more technical then the others, and a very informative (and rather short) book about Windows Installer can do a better job than me. Dull subject, important read.
Don’t diss installers.
(Title is a response to this nice codeproject article)
A while ago, when starting off with WPF, I asked a collegue of mine if I should keep all my data templates as data templates or replace them with user controls, and have the dataTemplate just contain that control. It seemed more “well formed”.
He said “it really doesn’t matter” and I told myself that in the name of proper separation (not having all the dataTemplates in one place) I should do it.
I have since wanted to inflict myself great pain for that decision.
1) If you just want a separate file for each template – just add a separate file for each template, dumbass. Took me quite a while to get that.
2) If you work with XAML and Resharper – you probably know it has some fine navigation tools (F12ing into a databound property works; renaming a property or class changes the XAML, etc.). But “databound” properties on dataTemplates are F12able, since the type of the VM is well known, and in case of a user control – not so much.
3) Creating new user controls takes longer than templates. And templates probably work Harder, Better, Faster, Stronger because it is just a resource, and not a compiled type (I really have no idea if that is the case, but I don’t mind speculating randomly).
Ok, yes, I made up reasons 1 and 3, and I only care about 2. Sue me.
A friend of mine (Adrian Aisemberg) has created an open source projects called SVN Monitor. It is a client side application (alongside Tortoise), which, as the name suggests, monitors the repository (and the working copy) for any available updates or conflicts. It’s a fine tool. If you use SVN – I highly recommend it.
I am new to SVN. I’ve used MS TFS for a while, gotten used to it, and it’s “connected” work mode.
Imagine my surprise when, starting to use SVN, I’ve had the misfortune to MOVE a folder (and then tried to deal with the mess). Adrian, who is a major SVN geek, told me that “I did it wrong”, and that SVN doesn’t work that way, and I should get acquainted with the tool and what not. Basically – it’s my fault.
But you’re infallible, Ariel! How could he have said that?!
I’m glad you asked. I myself have often wondered.
As my extensive profile describes me – I’m a UX geek. “Learning” is an awful stage in the adoption of a tool. Usually – steps could be taken to ease the user in. Adrian sais I need to learn “how to move folders in SVN” and I say “SVN sucks for making me learn how to do it”. I program for a living, I don’t move folders. It’s a side effect. Make it invisible to me.
Sometimes it is the hammer’s fault.
Sometimes I feel really stupid. You know, first-week-on-my-first-programming-job-ever stupid.
Almost as stupid as writing this code:
Dictionary<string, int> _Dic = new Dictionary<string, int>();
public object Get(string key)
{
try
{
return _Dic[key];
}
catch (KeyNotFoundException)
{
return null;
}
}
Which I didn’t write, let’s be clear about this (I probably did, at some point or another).
But what currently humbled me is that my problems solving techniques are very similar to the above code. I did not evolve. I am an ape.
Long story short - I had code invoking methods on an object across an appDomain boundary, and seldom had a RemotingException thrown at me. So what I did is simply wrap the calls with a lovely tryCatch for these exceptions and then re-created the entire appDomain (it’s a cache, so it is a valid operation regardless of exception management) before re-trying my call.
(What?? It worked!!)
Then I randomly encountered Sasha’s post about this exact issue.
Damn.
More Posts
Next page »