TechSpoken
"Any ideas?" is the most frequently-asked question in technical forums. My answer is: yes.

Sensitivity versus Consistency in Global Communication

December 20, 2008 17:43 by LSN

 My colleague Wisdom posts a comment on this blog, and also asks

 Side talk, why i can't find China in the country List, when i am adding a comment?

Hmmm. 

In looking into this, I checked into the relevant BlogEngine.NET code, which looks something like the following (see CommentView.ascx.cs):

foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
   RegionInfo ri = new RegionInfo(ci.Name);
   if
(!dic.ContainsKey(ri.EnglishName))
   {
      dic.Add(ri.EnglishName, ri.TwoLetterISORegionName.ToLowerInvariant());
   }
   if (!col.Contains(ri.EnglishName))
   {
      col.Add(ri.EnglishName);
   }
}

... that looked perfectly fine. It does seem from other .NET framework communications that it is possible for this code not to be all-inclusive.  And, in fact, the BlogEngine.NET code underscores this potential issue, with the following code in the same method:

// Add custom cultures

if (!dic.ContainsValue("bd"))
{
   dic.Add("Bangladesh", "bd");
   
col.Add("Bangladesh" );
}

It also seems, on further investigation, that other blogs besides mine that are based on Blog.Net have seen this issue specifically with Chinese viewers. 

What's the real problem?

Cultural-appropriateness is in the eye of the beholder

In his response to the question specifically about BlogEngine, Mads Kristensen points out that China is on the list.  It's just listed according to its SpecificCulture-EnglishName value, which is People's Republic of China, not China

 

You can see this illustrated in the MSDN post on the CultureInfo class, in fact, where different "manifestations" of Chinese culture info are shown, in response to the following sample code:

foreach ( CultureInfo ci in CultureInfo.GetCultures( CultureTypes.SpecificCultures ) ) 
{
  if ( ci.TwoLetterISOLanguageName == "zh" )  {
      Console.Write( "0x{0} {1} {2,-37}", ci.LCID.ToString("X4"),
                            ci.Name, ci.EnglishName );
      Console.WriteLine( "0x{0} {1} {2}", ci.Parent.LCID.ToString("X4"),
                            ci.Parent.Name, ci.Parent.EnglishName );
   }
}

 

... like this:

SPECIFIC CULTURE

PARENT CULTURE

0x0404 zh-TW Chinese (Taiwan) 0x7C04 zh-CHT Chinese (Traditional)
0x0804 zh-CN Chinese (People's Republic of China) 0x0004 zh-CHS Chinese (Simplified)
0x0C04 zh-HK Chinese (Hong Kong S.A.R.) 0x7C04 zh-CHT Chinese (Traditional)
0x1004 zh-SG Chinese (Singapore) 0x0004 zh-CHS Chinese (Simplified)
0x1404 zh-MO Chinese (Macao S.A.R.) 0x7C04 zh-CHT Chinese (Traditional)

 

So, okay.  That behavior and classification system seems perfectly defensible and understandable... 

  
...But it's not good enough.

Think about it this way: Wisdom,  the consumer of this framework result,  is already working in a language that is not his own, just to read the blog and navigate the list.  I am truly grateful he makes the effort.

Why should he have to realize that the English-speaking world refers to his country as "People's Republic of China", when his motherland-centered heart envisions it as "China", even in English? 

He knows he's supposed be navigating this list according to a sort-order based on an alphabetization that is also not his -- in which "P" is nowhere near "C".   Why should he look near "P"?

I want to point out that Wisdom didn't even ask "why isn't the value in the list".  He asked: "why can't I find  the value in the list."  It's there, but he can't find it.  And it's not his fault, even though he implicitly accepted that the problem was his.

I value Wisdom's comments, and those of the other members of my team.  So, while I "get" the value of the .NET framework generalized approach here, I'm going to include the following, along with the Bangladesh-adding coding example quoted above, in the original code:

//LSN
// add to standard-generated
// <option value="cn">People's Republic of China</option>


dic.Add("China", "cn");
col.Add("China");

Sure, it's a hack.  So what?

No perfect balance

When you work in a globally-dispersed team, as I do, you often have to balance two goals:

  1. Everybody needs to share some common vocabulary and frame of reference.  Consensus isn't real if every member of the group has a different idea of what was discussed and agreed on. 

    From a technical point of view, frameworks like .NET provide a common vocabulary in the guise of a set of shared classes and libraries, with known capabilities, features, and functions.  The fact that the names of the classes are English-based, in many if not all cases, doesn't prevent non-English-speakers from understanding the usage of the classes, although it may make it more difficult for non-English-speakers from guessing at the usage of the classes.

    As the team develops its own libraries, this common vocabulary widens.  The team's "shared muscles" develop strength and agility.

    From a non-technical point of view, the team starts with a few shared cultural assumptions, such as: "We are all software developers" and "We all work for the same company", and it slowly develops its own culture, based on shared jokes, memories, experiences, conversations, and hours.

  2. Everybody needs to respect some boundaries based on cultural disparity.  Because my team has both US and China members, it's not okay for any of us to assume availability of team resources based on our own cultural calendar and holiday schedule. Both US and Chinese team members sometimes generalize about "Americans", but if we had Canadian or Mexican team members, they might take exception. 

    From a technical point of view, frameworks like .NET provide a way to localize user interfaces and feedback mechanisms, calendars, and so on, to express an application's respect for each user's cultural frame of reference.

    From a non-technical point of view, we make all kinds of personal accommodations, from crazy working hours to fine-tuned expectations of communications style.

 

As goals, the drive-to-consensus and respect-for-differences often undercut each other. 

We all do the best we can. So does the .NET Framework, I guess.

There's no moral here.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Waiting for the paint to dry, in software development

November 30, 2008 10:03 by LSN

I am actually waiting for the paint to dry in my bathroom right now.

C and I Did Some Stuff to the bathroom of our new house two weeks ago. We thought we should have the contractor paint one wall a contrasting color after they ripped out, you know, the Stuff, and as part of replacing the Stuff.

This turned out to be a really bad idea for several reasons:

  • It was slightly the wrong type of paint.  This part was a case of imprecise specification on my part; C got high-gloss enamel rather than semi-gloss enamel.
  • Partly because it was the high-gloss, every non-expert brush stroke showed on the wall.  This part was a case of lack of training on the contractor's part.  See below.
  • As it turned out, we hated the new color anyway.  This part was a case of user interface design needing full acceptance testing before the job could be considered done. 
That's okay, sometimes it happens.  We're agile enough to deal.

While I was re-painting this week, I had some time to think about my long-ago training in house painting, and how that training distinguished my paint job from the contractors'.

For real:  my house-painting education occurred as part of work at Lincoln Farm, when I was in late-middle school.  Anybody reading this know about the camp?  I was there for several years, 1968-ish.

The name of the old painter who passed along the advice I'm giving you here was named Art Fuller.  I kid you not.  What a great name for a great painter, and he was a wonderful guy too.

The contractors were in a hurry. I don't blame them, and their rush was partly on my behalf. They were trying not to go over time and not to bill me for more than our quote. 

They told me (with the assurance of the very young) "This is great paint, it covers really well.  We can do one really thick coat, you won't need to do any more.  One thick coat is almost always better than two thin coats.  We're really laying it on here." 

They were laying it on in more ways than one, as it turned out. The one thick coat painting theory showed up in the results: messy and obvious brush strokes. We'll not belabor the part where they ripped off the masking tape while the paint was still wet, in an effort to be "done-done" before they left.  Everybody likes closure on a job.

Art Fuller was never in a hurry, at least not so much that it showed.  And Art always said "Two thin coats cover better than one thick coat, no matter how good the paint.  And make sure you give the first coat time to set.  Go do something else while you wait!" 

Of course, Art was right. 

I didn't have much paint left of the color that we were going to use as a replacement, so I put down a really thin first coat.  This new color was also a much lighter color than the very dark tone we had chosen before.  Still, two thin coats did beautifully.  If I hadn't really liked the new color, also, I would have had the time to sit and consider my next step.

What does this have to do with software development? 

A great deal, or so it seems to me at the moment.  (Feel free to tell me it's just the paint fumes <g>.)

Don't belabor your first design.  If you see flaws as you work to implement it, that's okay.  Don't patch over them and don't feel the need to implement every last detail.

Give your design time to set, consider it in full.  Give your users some time to consider it, at this early stage, too.  Don't be afraid to acknowledge that it's not complete.  What you hear may be dispiriting if you try to rush to fix everything right then -- don't.

Work on something else before you finish. I'm sure you have something else you can do; you won't waste this time. Come back to this feature or this module later and do a real second pass, when you're fresh and have energy for it again. 

You'll end up adjusting more than you would have changed in a single pass, but you'll have a better product.

We're often in a hurry -- often with our customers' interests in mind. But we had better not let it show.  Two thin coats take very little more time than the one thick coat would have taken, and they may possibly take less, in the long run.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5