Fabulous Adventures In Coding
Eric Lippert is a principal developer on the C# compiler team. Learn more about Eric.
Raymond has had lots of great posts over the years on how to not get a question answered. Some of the ways he points out that help ensure that a question goes unanswered are:
I would add that phrasing the question in terms of the attempted solution rather than the underlying problem is a great way to have a question remain unanswered. But I already did that. Today's rant, rather, is:
A great way to not get your question answered is to treat the person that you're asking to share their time and knowledge like they're not a human being.
I understand that this is easy to do.
I understand that when someone is asking a technical question, it is almost always because they're deeply frustrated by their inability to make some important specific complicated thing work the way they'd expect.
I understand that software makers are a big source of frustration in a more general sense. We all use imperfect software every day; little frustrations mentally accumulate in a way that little victories do not.
I understand that programming languages and software in general is often counterintuitive, and that understanding the complex reasoning behind a counterintuitive result is often seemingly of little practical import compared to just getting the problem at hand solved.
I understand that it is very easy to use an email client as an impersonal and automatic information resource something like a search engine, where you just type in your query, you get your result back, and you move on with your day.
I understand that there is an inherent and pervasive bias in pure-text communication which makes statements intended to be good-humoured sound sophomoric, makes statements which were intended to be friendly sound smarmy, makes statements which were intended to be enthusiastic sound brash, makes statements intended to be helpful sound condescending, makes statements which were intended to be precise and accurate sound brusque and pedantic, makes statements which were intended to be positive sound neutral, and makes statements which were intended to be neutral seem downright hostile.
(Boy, do I ever understand that. For over four years I have deliberately tried to pitch the tone of this blog as good-humoured, friendly, enthusiastic, helpful, precise, accurate and positive; I suspect that most of the time I fail badly at most or all of those. Writing is hard.)
I understand all that, from both sides; I've certainly been on both the sending and receiving ends of all of the above, many times.
Which is why I try very hard to be helpful to the complete strangers who send me overtly rude and frequently profane emails capped off with a request for me to to take time out of my day to explain something to them.
I try to see an upset or confused user as an opportunity to make a good impression; sometimes people do a complete 180 when you help them out and are appreciative and grateful. Sometimes they even send an unsolicited note to your manager, which is always pleasant.
But more often, I never hear from them again after their question is answered.
None of this is in their own best interests. It makes the human information sources they rely upon less likely to help them now and in the future.
So, just a friendly reminder. (A friendly, good-humoured, helpful, enthusiastic, positive reminder!) The people you are sending email to about your technical problems are people. It would be smart to briefly introduce yourself, describe your problem without insulting the people who created it, indicate what you've done to attempt to solve it yourself, actually ask for help, and later say thank-you for their time whether they manage to actually help you or not.
It's smart because doing so is in your own best interests.
It would also be nice, but I actually am not particularly concerned about "nice" today. Nice is nice to have I suppose. But not being smart is just dumb.
Couldn't agree with you more... just the other day I got an email from someone
Him: I need you to look at these memory dumps
Me: Sure thing, what's the problem?
Him: Please read the email thread
-- email thread was 58 pages and mostly in german
Me: Sorry, I don't know german, and I want to help you but could you please give me a clue, is it a memory leak, hang, crash? what am I looking for? what are the symptoms?
-- 2 days go by
Me: uhmm, did you want help or not?
Him: yeah, the details are in the email thread, did you look at the dumps yet?
Me: Still didn't take a class in german:) just tell me what the symptoms are and i'll look
never heard from him since:) and believe me, next time he asks, i will not bother even asking for the details...
"We all use imperfect software every day; little frustrations mentally accumulate in a way that little victories do not."
That quote just got Post-It Note'd to my monitor :)
Well written post, and timely. I've spent way too much time lately complaining publicly about software that I use daily that is written by real people, smart people, who may be overextended and not as concerned about quality as I might wish, but they are still people.
Thanks for the reality check.
Well said. Could you follow up with a short essay on how to not get your thoughtful blog comments answered, so that I can avoid those mistakes too? ;-)
Hehe, somebody has pissed you off today =P.
The short version:
I enjoy blogging tremendously, and it gives me great feedback directly from my best customers, that's great, but this will be the 4122nd comment posted to this blog. I simply do not have time to follow up everything in the level of detail I would like.
The long version:
Absense of evidence is not evidence of absense. Just because I don't say anything doesn't mean I'm not listening.
Take, for example, the implied supposition that I am willfully ignoring all the well-stated commentary on my post about limitations of method type inference from method groups.
In reality, I've just spent most of my hours at work for the last two weeks carefully reviewing every line of two completely different implementations of method type inference and comparing them against every clause of FOUR different versions of the type inference specification in order to determine every point of departure of the implementations from every version of the specification and every inconsistency between the specifications, PARTICULARLY with an eye to the question of whether it is possible to consistently make return type inferences from a method group when the parameters are known (and particularly with an eye to a whole lot of issues that nikov has been raising as well).
I gave a ninety minute long and intensely boring presentation about those findings to the rest of the dev team yesterday, and I hope to have a code review of my considerable changes to the implementation and specification that have resulted sometime this week.
I don't blog that stuff. What I do from day to day is not particularly interesting for my readers. That doesn't mean it's not happening.
Unsurprisingly, I have had other priorities as well over the last few months. A rather obscure error in the type inference spec and/or implementation for a far-from-mainline scenario is nowhere near my highest priority for investigation.
It can therefore easily take weeks or months to go from a suggestion or question on a blog or email or "connect" page to an investigation and ultimately a resolution.
So my recommendation is to learn to have some _patience_ and _stop carping_.
A couple of comments fairly specifically for Eric:
1) As far as I'm concerned, this blog almost always achieves the qualities you've been aiming for. The same goes for the other MS blogs I read. I know MS has been trying hard to work better with the community (and trying to balance different forms of engagement) and to my mind, blogs are providing *great* value. The Channel9 videos are great too, but take significantly more commitment to take advantage of, particularly at work.
2) Not hearing from someone again after a question has been answered can be a sign of respect for your time. I personally hate email conversations where neither side seems able to not reply, even though all meaningful dialogue has ended. I can imagine some bizarre company policies stipulating "no customer email goes unanswered" even if that email is just "thanks". Likewise on newsgroups, an absence of thanks can be an indication that someone doesn't want to add noise to the group in general.
On the other hand, a response to one's own question with just "I've fixed it now" is intensely irritating - it's always nice to know *how* someone has found the answer themselves.
When asking technical questions (or explaining how to do so effectively to other people) I find Eric Raymond's guide excellent:
I also find that posting a short but complete example aids matters *hugely*:
(I find it amazing how many people can be asked to provide a short but complete example, including the link above, and then respond with a long and/or incomplete example.)
I'm guilty as charged. My apologies as you answered one of my questions a couple of weeks ago on tertiary operators and I have yet to say thank you and respond. So thank you. I was hoping to have a more appropriate response once my workload goes down a bit and I have a bit of time to do some research. However, ignoring the research aspect, my response is:
Essentially, I agree, although tertiary operators when nested properly do look very similar to lisp's cond statement and therefore can be quite readable. What is more of an issue is memoization or a lack of it in c# as it means that variables are required, which leads to more statement based style of coding rather than expression based.
Preaching to the choir somewhat on this blog I suspect. Still, "amen". My own failings, I suspect, are mostly in the condescending/pedantic neighbourhood.
What I've been doing lately (since my own communications are largely internal to my workplace) is to replace "you" with "we" in my emails whenever it's possible to do so. So instead of
"If you want to achieve result X, you have to stop doing Y, and you probably should consider Z."
, I write
"If we want to achieve result X, we have to stop doing Y, and we probably should consider Z."
I like to pretend it helps a bit.
"I understand that there is an inherent and pervasive bias in pure-text communication..."
Printed in 30pts Helvetica and taped to my wall :). I enjoy your technical articles a lot but this one just made my day. Thanks for your time Eric!
I was reading this on my train ride home and this post made me turn off the podcast i was listening to really take in everything you were saying (vs. the normal skimming i do of blogs).
I definitely agree with what you are saying and am very guilty of many things in this area. After reading your post i almost want to email everyone i have bothered over the last few months and apologize LOL.
Seriously, posts like this are very good reminders of how we should act towards others. Thank you for once again putting this in front for me and getting my attention.
Best Regards and keep up the excellent blog (I agree with Jon, your content quality is excellent)
Your blog title says it all. As far as content goes, I've got no actual use for a fair bit of what you offer here ("High-Dimensional Spaces Are Counterintuitive" comes to mind), but a good-humoured (hang in there, Canuck!), friendly, enthusiastic, helpful, precise, accurate and positive adventure concerning things that interest me beats the living tar out of timely advice that lacks even one of these qualities. Metric tonnes of thanks for every word you post.
Think of it this way: Given my poor skills, I don't think I'd dare to comment if the blog conveyed none of the qualities you list.
I would like to take a moment here to genuinely and sincerely show my appreciation for your effort in writing this blog.
Kind ( and friendly, good-humoured, enthusiastic, and positive) regards,
Many years ago, I asked Eric to help me out in using MS Script control in a multi-threaded application. I was so surprised to see to the length he went to explain and debug things for me. Considering the fact that I was just a fresh (just-out-of-school) graduate and sitting in Karachi (Pakistan) working on a small project, getting help from a senior COM/scripting guy was fascinating. In fact, I was so impressed that I captured the whole conversation here: http://groups.yahoo.com/group/fast2000/message/1152.
And the second time I asked him a question, he wrote a complete blog post about it:
Thank you Eric for all the help. Writing a blog is one thing. Taking out time to answer emails and looking at someone's code to him out is something much demanding. Thanks, again.
Thanks for your response Eric. Since your answer was pretty elaborate, please let me quickly explain why this particular case was so frustrating. First, we both agreed that inference of co/contravariance based on interfaces was evil, because every single change to any interface member could unexpectedly change the inferred behavior. I then relativized that statement, saying that I felt it does not apply to delegates, where a change of co/contravariance based on the signature would be expected, and explicit co/contravariance syntax was so complicated (given the inversion problem) that any attempt to simplify it would almost automatically lead back to infering. However, since your last statement on that topic said "absolutely no inference whatsoever" I was afraid you would not consider this.
Similarly, I proposed a complicated co/contravariance syntax that would make it possible to guess the meaning even if you did not know it before, and it gathered some appreciation in the comment section (along with some similar proposals). I later changed my mind 180 degrees, feeling that this syntax might be analyzable with some effort, but would require this effort each time, and not allow the reader to make the simple association of covariance=goes with and contravariance=goes against. Since you did not comment on this statement, I felt guilty for making a stupid proposal that seemed to be favored by many, and I'm always wary of the C# design process which, while often producing better results than the whole JCP circus, does have a tendency to confront the community with final decisions.
I was not expecting a final statement about anything, but I was under the impression that you wanted a bidirectional discussion, and the decision which comments to reply to and which not seemed a bit strange to me. A short reply to my "please answer" nagging would have made a big difference.
Also, while I think that my carping was not unfriendly, I have to admit that I'm better at that than at patience. I was just hoping to have an interesting discussion here, sorry if I was pushing too hard.
BTW, I've just been to lang.net (presenting our mixin library for C#), and I felt that MS's C# team is the least open of all language teams. Anders gave his standard talk of how all the bits of C# 3 come together to form LINQ, which is great, but quite old now. That was it. The rest of the time was for Ruby, Python and the DLR stuff, F# and even Java and others. Without being to annoying (I hope), I think there is a need to get a conversation going about the future directions of C#. And I think I'm not the only one who thinks so.
I've had the same discussion with Wes Dyer before:
I talked to Anders after his lang.net talk. I spoke about my theory that you should be able to override non-virtual methods using code generation. (In other words, while I understand the reason for requiring the virtual keyword, this should be a language constraint, not a CLR constraint. This works by analogy with reflection: If you call a private member by name, it might fail in the future. If you discover private members at runtime, it's perfectly legal, because any future changes would be discoverd too. Serialization is a good example. Likewise, if you create a subclass proxy at runtime, how does overriding non-virtual methods hurt compatibility?
Anders response was: OK, so you want a way to hook into calls?
End of discussion. Yes, if you take a step back, he's perfectly right. But where does that leave me (and all the other enterprise frameworks that make use of such features, from Castle to Spring.Net up to MS's own Enterprise Libary)? It might be considered. It might be implemented. In a way that might or might not meet my requirements. I'll know when I get the first CTP.
I've talked to Mono's Marek Safar (http://mareksafar.blogspot.com/) about how they participate in the design process, but he said they are basically satisfied with the ECMA process, which ensures that they get all the info to build whatever MS designs.
Don't you think that you could, or should, do more here?
Anyway, like I said, I enjoy your blog, I'm grateful for you reply, and I'll definately feel better getting into deep discussions in the future now that I know that no answer does not mean my input was meaningless.
I am amongst the silent readers who immensely enjoy your blog. Hey, I even like the purple color :) I would not want to cluther your inbox or blog with thank you messages for every post made, but I take this occasion to say that every single one of them is both interesting, insightful and technically accurate and complete. That is no small feast. So my hat's off to you for doing this on top of everything else.