<?xml version="1.0" encoding="UTF-8" standalone="no"?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:gd="http://schemas.google.com/g/2005" xmlns:georss="http://www.georss.org/georss" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:thr="http://purl.org/syndication/thread/1.0"><id>tag:blogger.com,1999:blog-18337532</id><updated>2024-08-29T13:21:39.622+07:00</updated><category term=".NET"/><category term="C#"/><category term="Exception"/><category term="Ideas"/><category term="JavaScript"/><category term="SharePoint"/><category term="Blogging"/><category term="Japan"/><category term="Outsourcing"/><category term="Threading"/><title type="text">Truong Hong Thi on .NET</title><subtitle type="html">Thoughts and ideas on .NET</subtitle><link href="http://thith.blogspot.com/feeds/posts/default" rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default?redirect=false" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/" rel="alternate" type="text/html"/><link href="http://pubsubhubbub.appspot.com/" rel="hub"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><generator uri="http://www.blogger.com" version="7.00">Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-18337532.post-6960394001788294784</id><published>2015-02-15T01:10:00.003+07:00</published><updated>2015-02-15T01:11:44.901+07:00</updated><title type="text">Check out my new blog</title><content type="html">I setup my new blog here:&amp;nbsp;&lt;a href="http://www.mangcut.vn/en/"&gt;http://www.mangcut.vn/en/&lt;/a&gt;&amp;nbsp;(English posts only). If you could read Vietnamese, check out the home page, that is&amp;nbsp;&lt;a href="http://www.mangcut.vn/"&gt;http://www.mangcut.vn&lt;/a&gt;.</content><link href="http://thith.blogspot.com/feeds/6960394001788294784/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/6960394001788294784" rel="replies" title="0 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/6960394001788294784" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/6960394001788294784" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2015/02/check-out-my-new-blog.html" rel="alternate" title="Check out my new blog" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-7383106362075861499</id><published>2010-06-02T02:14:00.002+07:00</published><updated>2010-06-03T02:16:07.754+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint"/><title type="text">Fix the SharePoint's discussion board deleting bug</title><content type="html">Recently, I ran into a very strange SharePoint Discussion Board bug: if you delete the discussion topic (the thread root message), SharePoint will tell 'Cannot complete this action. Please try again'. However, the topic did get deleted in spite of the error message.
&lt;br /&gt;
&lt;br /&gt;
Digging deeper into this, I found out that:&lt;br /&gt;
- the bug happens only if the discussion board resides on the sub-site, or the site collection under 'sites' folder. It does not happens on the root site of the root site collection.&lt;br /&gt;
- it happens only when you click on a discussion topic to view the thread (Flat or Threaded view) -&amp;gt; then click the root message's 'View Properties' button -&amp;gt; then click 'Delete Item' toolbar button.&lt;br /&gt;
- it does not happen if you choose to delete the topic from the context menu; or if you enter 'Properties' screen from 'View Item' context menu.&lt;br /&gt;
- it happens only when deleting the discussion root topic. Deleting the relies does not cause trouble.&lt;br /&gt;
&lt;br /&gt;
Checking the URL carefully, I figured out the reason: the problem is because after deleting, it tries to redirect to the thread view (as specified by the 'Source' query string parameter). However, as the topic has been deleted, there's no place to go back. It is a redirecting problem, not a deleting problem.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The solution:&lt;/b&gt;&lt;br /&gt;
Although at first it seems to be a problem of my specific site, it &lt;b&gt;is&lt;/b&gt; a WSS 3.0 bug. As of WSS 3.0 SP2 (or MOSS 2007 SP2), there is no hot fix for that. I did not yet know if this bug exists in the just-released SharePoint 2010. As there seems to be no existing solution on the Internet, I developed a simple JavaScript solution.
&lt;br /&gt;
&lt;br /&gt;
Add the following JavaScript snippet into discussion board's &lt;i&gt;DispForm.aspx&lt;/i&gt; (if you don't know how to do this, see my post &lt;a href="http://thith.blogspot.com/2010/06/how-to-add-javascript-to-sharepoint.html"&gt;http://thith.blogspot.com/2010/06/how-to-add-javascript-to-sharepoint.html&lt;/a&gt;).
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&amp;lt;script type=&lt;span class="str"&gt;"text/javascript"&lt;/span&gt;&amp;gt;
_spBodyOnLoadFunctionNames.push(&lt;span class="str"&gt;"ChangeAction"&lt;/span&gt;);
function ChangeAction() {
  &lt;span class="rem"&gt;// Topics have titles, replies do not&lt;/span&gt;
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (!HasField(&lt;span class="str"&gt;"Title"&lt;/span&gt;)) {
    &lt;span class="kwrd"&gt;return&lt;/span&gt;;
  }
  var theForm = document.forms[&lt;span class="str"&gt;'aspnetForm'&lt;/span&gt;];
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (!theForm) {
    theForm = document.aspnetForm;
  }
  
  var oldAction = theForm.action;
  var args = oldAction.split(&lt;span class="str"&gt;'&amp;amp;'&lt;/span&gt;);
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (args.length &amp;gt; 0) {
      theForm.action = args[0];
  }
}
function HasField(internalName) {
  var elements = document.getElementsByName(&lt;span class="str"&gt;'SPBookmark_'&lt;/span&gt; + internalName);
  &lt;span class="kwrd"&gt;return&lt;/span&gt; (elements.length &amp;gt; 0);
}
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
The purpose is simple: if it is a discussion root, cleanup the URL. SharePoint will redirect to the list's default view (often &lt;i&gt;AllItems.aspx&lt;/i&gt;) if it does not find the 'Source' query string parameter.
&lt;br /&gt;
&lt;br /&gt;
The script assume that 'ID' is the first query string parameter. It works on our environments. If you want a solution which does not depend on the order of the query string parameters, maybe you could try to parse the query string.</content><link href="http://thith.blogspot.com/feeds/7383106362075861499/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/7383106362075861499" rel="replies" title="2 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/7383106362075861499" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/7383106362075861499" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2010/06/fix-sharepoints-discussion-board.html" rel="alternate" title="Fix the SharePoint's discussion board deleting bug" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-3937910010410216617</id><published>2010-06-02T02:04:00.000+07:00</published><updated>2010-06-02T02:23:29.637+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="SharePoint"/><title type="text">How to add JavaScript to SharePoint list form</title><content type="html">Ever want to add some javascript to list forms (NewForm.aspx, EditForm.aspx, DispForm.aspx) to show/hide items or something like that? You could try one of following ways (tested on WSS 3.0):&lt;br /&gt;
1. Use browser: browse to the form you want to add javascript. Add '&lt;b&gt;&amp;amp;PageView=Shared&amp;amp;ToolPaneView=2&lt;/b&gt;' to the end of the URL then hit Enter. Then you could add a Content Editor webpart to the form and put your javascript there.
&lt;br /&gt;
2. Use SharePoint Designer: open the form, search for &lt;b&gt;MainPlaceHolder&lt;/b&gt; and paste the javascript just bellow the &lt;b&gt;&amp;lt;asp:content&amp;gt;&lt;/b&gt; opening tag.
&lt;br /&gt;
&lt;br /&gt;
Be sure to include &amp;lt;script&gt; and &amp;lt;/script&amp;gt; tags with your javascript.</content><link href="http://thith.blogspot.com/feeds/3937910010410216617/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/3937910010410216617" rel="replies" title="0 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/3937910010410216617" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/3937910010410216617" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2010/06/how-to-add-javascript-to-sharepoint.html" rel="alternate" title="How to add JavaScript to SharePoint list form" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-814658589554612416</id><published>2006-12-04T13:09:00.000+07:00</published><updated>2010-06-02T00:07:42.984+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".NET"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><title type="text">Enable the Registry Editor</title><content type="html">&lt;p&gt;Sometimes, my machine is infected by some virus. Almost all viruses change many registry entries and disable the Windows Registry Editor (Regedt32.exe and Regedit.exe) so that I could not change them back. Of course, that is not a problem if you have some other tool to edit the Windows Registry; but I don't have such tool. Creating a &lt;i&gt;.reg&lt;/i&gt; file and import into the registry often does not help because Windows could be configured to deny running registry editor in silent mode. Trying to enable the Windows registry editor by using Group Policy (gpedit.msc) might still no help, and even the Group Policy could be disabled. Plus, not everyone knows how to edit the &lt;i&gt;.reg&lt;/i&gt; file or using Group Policy. That is why I wrote a small C# tool to enable the registry editor. The source code of the tool is like this:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Win32;
&lt;span class="kwrd"&gt;string&lt;/span&gt; path = &lt;span class="str"&gt;@&amp;quot;Software\Microsoft\Windows\CurrentVersion\Policies\System&amp;quot;&lt;/span&gt;;
&lt;span class="kwrd"&gt;using&lt;/span&gt; (RegistryKey key = Registry.CurrentUser.OpenSubKey(path, &lt;span class="kwrd"&gt;true&lt;/span&gt;))
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (key != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
  {
    Object o = key.GetValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (o != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
      key.DeleteValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
    }
  }
}&lt;/pre&gt;
&lt;p&gt;The snippet above deletes the &amp;quot;DisableRegistryTools&amp;quot;. Note that you achieve the same result by updating the value to 0, which is the default value if the entry is not there. &amp;quot;DisableRegistryTools&amp;quot; is a DWORD whose value could be one of the following:&lt;/p&gt;
&lt;table border="1" width="100%" style="border-collapse: collapse;" cellpadding="4"&gt;
  &lt;tr&gt;
    &lt;td&gt;&amp;nbsp;&amp;nbsp;0&amp;nbsp;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Default. Registry Editor can be started either in interactive mode or in silent mode. &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&amp;nbsp;&amp;nbsp;1&amp;nbsp;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Registry Editor can only be started in silent mode. You can still import an .reg file.&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;&amp;nbsp;&amp;nbsp;2&amp;nbsp;&amp;nbsp;&lt;/td&gt;
    &lt;td&gt;Registry Editor cannot be started at all.&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Some viruses also add &amp;quot;DisableRegistryTools&amp;quot; entry to &lt;i&gt;HKEY_USERS\.DEFAULT&lt;/i&gt;, so I should also delete it:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; (RegistryKey key = Registry.Users.OpenSubKey(&lt;span class="str"&gt;@&amp;quot;.DEFAULT\&amp;quot;&lt;/span&gt; + path, &lt;span class="kwrd"&gt;true&lt;/span&gt;))
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (key != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
  {
    Object o = key.GetValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (o != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
      key.DeleteValue(&lt;span class="str"&gt;&amp;quot;DisableRegistryTools&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
    }
  }
}&lt;/pre&gt;
&lt;p&gt;You may want to start the registry editor right after enabling it:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;System.Diagnostics.Process.Start(&lt;span class="str"&gt;&amp;quot;regedit.exe&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;p&gt;Note that you should first kill every malware process or it will re-disable the tool very soon. Many viruses disable the Windows Task Manager and/or automatically restart the computer when you open it. In that case, you may need a third-party tool, like &lt;a href="http://www.sysinternals.com/Files/ProcessExplorerNt.zip"&gt;Process Explorer&lt;/a&gt;, to identify and kill malicious processes. However, I also included this functionality in my tool. Just drag a list box (lstProcess) and a button (btnKill) onto the form:&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Form1_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.EventArgs e)
{
  lstProcess.Items.AddRange(Process.GetProcesses());
}

&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; btnKill_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, System.EventArgs e)
{
  Process selectedProcess = lstProcess.SelectedItem &lt;span class="kwrd"&gt;as&lt;/span&gt; Process;
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (selectedProcess == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;return&lt;/span&gt;; &lt;span class="rem"&gt;// no item selected&lt;/span&gt;

  &lt;span class="kwrd"&gt;string&lt;/span&gt; exePath = selectedProcess.MainModule.FileName;
  &lt;span class="kwrd"&gt;if&lt;/span&gt; (DialogResult.OK ==
    MessageBox.Show(&lt;span class="str"&gt;&amp;quot;Kill: &amp;quot;&lt;/span&gt; + exePath, &lt;span class="str"&gt;&amp;quot;Confirm kill&amp;quot;&lt;/span&gt;, MessageBoxButtons.OKCancel))
  {
    selectedProcess.Kill();
  }
}&lt;/pre&gt;
&lt;p&gt;After starting registry editor, you should check all programs that automatically run when Windows starts and delete malicious entries and their physical files (some versions of Windows include a good tool for this purpose (msconfig.exe), but some malware might still escape so you had better check the registry - see &lt;a href="http://support.microsoft.com/kb/179365"&gt;Run and RunOnce Registry Keys&lt;/a&gt; to know where to check). Then check and delete malicious scheduled tasks. Also check Windows services (run services.msc). Following are some other registry entries that you should check:&lt;/p&gt;
&lt;p&gt;&lt;small&gt;HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell&lt;br&gt;
HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableTaskMgr&lt;br&gt;
HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\DisableCMD&lt;br&gt;
HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoFolderOptions&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Believe it or not, I have cleaned many viruses on my PC just with the help of my tool and the Windows' search functionality to search for recently created files which are likely malware ones.&lt;/p&gt;</content><link href="http://thith.blogspot.com/feeds/814658589554612416/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/814658589554612416" rel="replies" title="4 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/814658589554612416" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/814658589554612416" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2006/12/enable-registry-editor.html" rel="alternate" title="Enable the Registry Editor" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-523588470354761605</id><published>2006-11-15T13:54:00.000+07:00</published><updated>2006-11-15T19:43:46.220+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogging"/><title type="text">Format code snippets in blogs</title><content type="html">&lt;p&gt;When blogging, I frequently have to copy code and paste it to my post. It is nice if I have the snippet formatted like it is in Visual Studio. In the past, if the snippet is short, I would put it in &lt;i&gt;&amp;lt;pre&amp;gt;&lt;/i&gt; tag and manually colorize keywords, comments and strings. If the snippet was long, I would copy it from Visual Studio and paste into Word then copy to my post.&lt;/p&gt;&lt;p&gt;Recently, a friend of mine told me about &lt;a href="http://www.manoli.net/csharpformat/"&gt;http://www.manoli.net/csharpformat&lt;/a&gt; which can do the job for me. Despite the page's URL, it could format C#, VB, JavaScript, HTML, XML, ASPX, and MSH. The nice thing about code formatted by that page is that it makes use of CSS so I can paste the CSS stuff into my Blogger's template. Imagine some day I want to change the color of the keywords, just update the CSS and it will apply to all snippets in the blog. The page also let me download the source code, so I wrote a winform application myself using that DLL and added support for some other languages, like Java. It works nice, although sometimes it hangs with bad input :). I also changed the CSS a little to make the formatted code look more like that inside Visual Studio. I'll re-format every snippet in my blog.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; HelloWorld
{
    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
        {
            Console.WriteLine(&lt;span class="str"&gt;&amp;quot;Hello World!&amp;quot;&lt;/span&gt;);
        }
    }
}&lt;/pre&gt;&lt;p&gt;The HTML source the tool generates (the HTML source itself is also colorized by the tool):&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;pre&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;csharpcode&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;using&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; System;

&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;namespace&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; HelloWorld
{
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;class&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; Program
    {
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;static&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;void&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Main(&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;kwrd&amp;quot;&amp;gt;&lt;/span&gt;string&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;[] args)
        {
            Console.WriteLine(&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;class&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;str&amp;quot;&amp;gt;&lt;/span&gt;&amp;quot;Hello World!&amp;quot;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;);
        }
    }
}&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;pre&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Look nice, doesn't it?&lt;/p&gt;&lt;p&gt;There was one problem: in some browsers, the &lt;em&gt;&amp;lt;pre&amp;gt;&lt;/em&gt; tag does not wrap. In many pages (like ones in this blog), long lines would go out of the border of its containing panel and there is no way to see the obscured parts. Fortunately, there is a way out: update CSS to make &lt;em&gt;&amp;lt;pre&amp;gt; &lt;/em&gt;wrap as described at &lt;a href="http://myy.helia.fi/~karte/pre-wrap-css3-mozilla-opera-ie.html"&gt;http://myy.helia.fi/~karte/pre-wrap-css3-mozilla-opera-ie.html&lt;/a&gt;. After I updated the Blogger template, everything was fine.&lt;/p&gt;&lt;pre class="csharpcode"&gt;.csharpcode, .csharpcode pre {
    font-size: small;
    color: black;
    font-family: Consolas, "Courier New", Courier, Monospace;
    background-color: #f4f4f4;
    white-space: pre-wrap;       /* css-3 */
    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
    white-space: -pre-wrap;      /* Opera 4-6 */
    white-space: -o-pre-wrap;    /* Opera 7 */
    word-wrap: break-word;       /* Internet Explorer 5.5+ */
}&lt;/pre&gt;&lt;p&gt;Sorry the CSS code is not colorized as the tool does not support CSS yet.</content><link href="http://thith.blogspot.com/feeds/523588470354761605/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/523588470354761605" rel="replies" title="6 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/523588470354761605" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/523588470354761605" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2006/11/format-code-snippets-in-blogs.html" rel="alternate" title="Format code snippets in blogs" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-499229115784988201</id><published>2006-10-27T17:38:00.000+07:00</published><updated>2006-11-15T15:46:05.751+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".NET"/><category scheme="http://www.blogger.com/atom/ns#" term="Exception"/><category scheme="http://www.blogger.com/atom/ns#" term="Ideas"/><title type="text">What makes an API good</title><content type="html">&lt;p&gt;Today, once again, one of my colleagues called me to his desk and asked why  the following code did not work as expected:&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;pre class="csharpcode"&gt;Debug.WriteLine(&lt;span class="str"&gt;"Message received: {0}"&lt;/span&gt;, receivedMessage);&lt;/pre&gt;&lt;p&gt; &lt;/p&gt; &lt;p&gt;It should print out something like "Message received: Hello", right?&lt;/p&gt; &lt;p&gt;I've seen someone else have this problem before, and I myself did run into it.&lt;/p&gt; &lt;p&gt;- Look at the infotip. The first param is the message, and the second one is  its category.&lt;/p&gt; &lt;p&gt;- Uh oh, category. How could I miss that!&lt;/p&gt; &lt;p&gt;I know why. He, as well as me and many other developers, expect  Debug.WriteLine to work the same way as Console.WriteLine; so much that we do  not notice the infotip's contents. Because Console.WriteLine is too well-known, I consider  the signature of Debug.WriteLine bad design.&lt;/p&gt; &lt;p&gt;Good API is intuitive. The key to that is being consistent with well-known  and widely used patterns. It is ideal if developers could code without looking at  the documentation. Although computer is getting faster, it still takes some time  to load the documentation. That reduces productivity and tests the developer's  mentality. Thanks to good modern IDEs, we now less and less have to consult  documentation. The usual reason I still have to look at the doc is to check out  the &lt;i&gt;Exceptions&lt;/i&gt; section. Of course, sometimes I have to consult the other  information like thread safety, remarks, examples, etc. - but that is for more  complex API when looking at the documentation is necessary.&lt;/p&gt; &lt;p&gt;I always wish that the IDE should somehow let users view exception  information, at least for system types, in some form of intellisense dialog.  It could do this by parsing the XML comments. The pitfall of this is that it  might mislead the developer to trust that exception information which will  certainly cause troubles if the method is poorly XML documented (it might still  be documented well in some form else, but not XML comments). Exception  documentation is just a good practice, not a contract. Java has experimented  exception specification, with some benefits and some drawbacks. I am thinking of  some solutions, like ExceptionAttribute, but none of them really helps.&lt;/p&gt; &lt;p&gt;Nevertheless, a good API should expose as much useful information as possible,  in form of contracts, metadata (attributes), or at least standardized  comments/documentation. Consistent style, self-documented names, commonly-used  members/features emphasized. Good API + good IDE save developers' lives. &lt;/p&gt;</content><link href="http://thith.blogspot.com/feeds/499229115784988201/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/499229115784988201" rel="replies" title="0 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/499229115784988201" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/499229115784988201" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2006/10/what-makes-api-good.html" rel="alternate" title="What makes an API good" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-4316540397277890226</id><published>2006-10-26T16:45:00.000+07:00</published><updated>2006-11-15T15:57:09.562+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".NET"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Exception"/><category scheme="http://www.blogger.com/atom/ns#" term="Ideas"/><title type="text">Why exception so verbose?</title><content type="html">&lt;p&gt;I remember, on my first days with VS.NET, I wanted to add some exception  classes to my project. I launched the &lt;i&gt;Add New Item&lt;/i&gt; dialog trying to find some item  like exception. There was no such item (it even did not have an item for  interface! - VS2005 fixed this). I had to add a regular class, typed in the code for its standard  constructors, then copied and pasted to create other exception classes. Although  my application used a bunch of exceptions, none of them contained additional  fields or methods - just the standard constructors. The way current languages  support exception make exception's type so important and often solely adequate.&lt;/p&gt; &lt;p&gt;Later, I figured out how to add a template into VS.NET and made it appear on  the &lt;i&gt;Add New Item&lt;/i&gt; dialog. Since then, I did not have to manually type the  exception code again (except for the infrequent case when I want to add some  extra stuff into the exception).&lt;/p&gt; &lt;p&gt;However, every time I look at the code of a "standard" exception, I keep  asking myself why on earth it has to be so verbose? Wouldn't it be neater to be  one-line concise like this:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public exception&lt;/span&gt; MyException;&lt;/pre&gt;&lt;p&gt;or if the exception should have a parent other than &lt;code&gt;System.Exception&lt;/code&gt;:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public exception&lt;/span&gt; MySpecificException: MyException;&lt;/pre&gt;&lt;p&gt;The compiler will compiles it into a "standard" exception. This is  essentially the way &lt;code style="color: rgb(0, 0, 255);"&gt;delegate&lt;/code&gt; keyword in C# works.&lt;/p&gt; &lt;p&gt;Then you and me - the code typists - will have some time for a cup of tea.&lt;/p&gt;</content><link href="http://thith.blogspot.com/feeds/4316540397277890226/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/4316540397277890226" rel="replies" title="0 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/4316540397277890226" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/4316540397277890226" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2006/10/why-exception-so-verbose.html" rel="alternate" title="Why exception so verbose?" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-113090707992234985</id><published>2005-11-02T11:37:00.000+07:00</published><updated>2015-02-15T00:58:29.841+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".NET"/><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Threading"/><title type="text">C# Interlocked</title><content type="html">----------&lt;br /&gt;
&lt;b&gt;Note&lt;/b&gt;: a more recent and revised version of this post could be found here: &lt;a href="http://www.mangcut.vn/blog/2015-02-14-atomicity-interlocked-memory-operation-optimizations-csharp.html"&gt;http://www.mangcut.vn/blog/2015-02-14-atomicity-interlocked-memory-operation-optimizations-csharp.html&lt;/a&gt;&lt;br /&gt;
----------&lt;br /&gt;
&lt;br /&gt;
Multithread programming, together with unit testing and exception handling, is among the tough and hard-to-do-cleanly things a software developer has to do on virtually every project. When starting learning about threads, a developer usually spend a lot of time to figure out how to create, start, and stop threads, how to make use of the thread pool, how to programming with the asynchronous delegates, etc. However, as I see it, the hardest thing to master is thread synchronization, that is, when and where you need to lock a code block to ensure accuracy and consistency. However, locking is reputed as expensive as it is often used ineffectively and create performance bottlenecks in the application.  Effective locking primarily refers to locking at the correct level and correct granularity. Quite often, low level locking becomes useless as higher level code has its own business rules and may requires to lock a chunk of methods-something like "integration locking". Sometimes, two blocks of code are wrongly guarded by the same object which results in unnecessary contention. I am not a fan of lock-free tricks as it is too difficult to understand and might even be proven incorrect some time. However, there are some circumstances in which avoiding locking is just simple and elegant.  I guess some of you might have seen code like following: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;lock&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;)
{
    a++; &lt;span class="rem"&gt;// or a--, a = b, you name it&lt;/span&gt;
}&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;/pre&gt;
We all learned that even a simple operation like increment might include several steps: load the variable into a register, increment it, save its value back from the register. So the lock in the code snippet above is necessary to prevent some other thread from intervening those steps (for this to work, the two threads must be guarded by the same lock). The only comment you might make about that snippet is that: avoid locking on &lt;code&gt;this&lt;/code&gt; (or any public object if it is not designed for that purpose) since it might be accidentally be locked on by other code for a different purpose, which usually leads to a deadlock or at least execution inefficiency.&lt;br /&gt;
&lt;br /&gt;
However, the .NET does provide a brilliant class called System.Threading.Interlocked. This class contains a handful of useful methods such as assignment and increment/decrement, each one is performed as an atomic operation. So the above code could be better rewritten as simple as: Interlocked.Increment(ref a). How nice!&lt;br /&gt;
&lt;br /&gt;
"Atomic operation" is sometimes incorrectly interpreted as volatility. Let's take a look at section 5.5 of the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/csharpspecstart.asp" target="_blank"&gt;C# Language Specification&lt;/a&gt; which said: &lt;i&gt; &lt;b&gt;5.5 Atomicity of variable references&lt;/b&gt; Reads and writes of the following data types are atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types. In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. Reads and writes of other types, including long, ulong, double, and decimal, as well as user-defined types, are not guaranteed to be atomic. Aside from the library functions designed for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement. &lt;/i&gt; Hmm...  atomic again. Does that means in C#, the two following snippets are identical?  Variables a, b, c are declared at class level: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; a, b, c;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;/pre&gt;
Snippet 1: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;a = 1;
b = c;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;/pre&gt;
Snippet 2: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;Interlocked.Exchange(&lt;span class="kwrd"&gt;ref&lt;/span&gt; a, 1);
b = c;&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;/pre&gt;
The answer is no. An atomic operation is indivisible. For example, an atomic write guarantees that no other thread can read while the write operation not yet finished and end up reading a partially updated value. However, for performance reason, the JIT or the hardware may decide to apply some optimizations such as reordering or even eliminating instructions as long as they do not break the logic from a single thread's perspective. For instance, in snippet 1, the processor might decide to fetch the value of &lt;code&gt;c&lt;/code&gt; before writing &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;a&lt;/code&gt;. That is OK if the program is single-threaded. However, what if a second thread updates the value of &lt;code&gt;c&lt;/code&gt; in the meantime? The first thread then uses a stale value of &lt;code&gt;c&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;Interlocked&lt;/code&gt; class is just more than atomicity. In fact, each one of its methods uses a memory barrier which prevents any instruction being reordered crossing the barrier. The &lt;code&gt;Interlocked.Exchanged&lt;/code&gt; method call in snippet 2 prevents the reading of &lt;code&gt;c&lt;/code&gt; from happening before &lt;code&gt;1&lt;/code&gt; is written to &lt;code&gt;a&lt;/code&gt;. Interlocked class is also safe on multiprocessor systems, where, because of caching issues, the sequence of instructions executed on one processor can appear to be different from other processors' perspective.  In addition, the specification says C# does not guarantee functions such as increment and decrement to be atomic. The &lt;code&gt;Interlocked&lt;/code&gt; class provides two super-handy methods for those purposes: &lt;code&gt;Interlocked.Increment&lt;/code&gt; and &lt;code&gt;Interlocked.Decrement&lt;/code&gt;. It should be noted that there are overloaded versions of these two methods that accept a long argument. This surprised me at first since it guarantees increment and decrement of a 64-bit number as an atomic operation. However, I soon realized that there is no magic under the scene since MSDN remark section of this method says that &lt;i&gt;"The 64-bit versions of Increment and Decrement are truly atomic only on systems where a System.IntPtr is 64 bits long. On other systems, these methods are atomic with respect to each other, but not with respect to other means of accessing the data.”&lt;/i&gt;. Aha, that means on 32-bit systems, they can only be considered atomic only if increment and decrement are the two only operations you ever want to perform on the variable. That behavior could be simulated by letting the two methods acquire a lock on the same static internal object.&lt;br /&gt;
&lt;br /&gt;
Besides the methods above, Interlocked class also provides a less-used method: CompareExchange. This method, as its name suggests, carries out a comparison first, and then exchanges the values if that test succeeded. Note that compare and exchange operations are performed as a single atomic operation. The &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemthreadinginterlockedclasscompareexchangetopic1.asp" target="_blank"&gt;example MSDN provides&lt;/a&gt; for this method is very interesting. This method reminds me of the DB optimistic concurrency problem which I had to deal with recently: you should only update a value if it is not been updated by someone else since the last time you queried it. Otherwise, that updated value will be replaced by your value. This method can also be used to implement the Singleton pattern: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="csharpcode"&gt;Interlocked.CompareExchange(&lt;span class="kwrd"&gt;ref&lt;/span&gt; singleton,
           &lt;span class="kwrd"&gt;new&lt;/span&gt; SingletonClass(), &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;/pre&gt;
&lt;pre class="csharpcode"&gt;&lt;/pre&gt;
However, this approach requires a new instance of SingletonClass to be created even if &lt;code&gt;singleton&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
So now if you ever want to lock a block of code which performs only a simple operation on a variable, let’s first see if you can get the same effect with Interlocked class!</content><link href="http://thith.blogspot.com/feeds/113090707992234985/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/113090707992234985" rel="replies" title="9 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/113090707992234985" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/113090707992234985" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2005/11/c-interlocked.html" rel="alternate" title="C# Interlocked" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-18337532.post-113049060532234517</id><published>2005-10-28T16:06:00.003+07:00</published><updated>2009-05-23T20:16:54.348+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Japan"/><category scheme="http://www.blogger.com/atom/ns#" term="Outsourcing"/><title type="text">A Touch of Japan</title><content type="html">&lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;October 2005. The first time I visited &lt;st1:place st="on"&gt;&lt;st1:country-region st="on"&gt;Japan&lt;/st1:country-region&gt;&lt;/st1:place&gt; was also the first time I went abroad. The initial feeling when the plane was about to land at Narita airport was about the peace and tranquility here. It was slightly cold. I got straight to Hitachi Software building and my one-month working onsite here began.&lt;br&gt;
&lt;br&gt;
However, everything soon turned to be some kind of frustration. Japanese people seemed to be too shy to start conversation, and it was rare to find someone who can speak English well. It took me some time to get used to the railway system. I wish they used Romaji (the alphabetic representation of Japanese) instead of Kanji and Hiragana letters on their maps.&lt;br&gt;
&lt;br&gt;
As having out-sourced for companies in both the &lt;st1:country-region st="on"&gt;US&lt;/st1:country-region&gt; and &lt;st1:country-region st="on"&gt;&lt;st1:place st="on"&gt;Japan&lt;/st1:place&gt;&lt;/st1:country-region&gt;, I feel tempted to make a comparison of the two. Most Japanese could read English well, but their writing, speaking, and listening are usually limited and insufficient to work with offshore teams in English. Plus, they seem to be too shy about their English and prefer to use Japanese even if they can speak English pretty well. As a result, a lot of effort have to be put in communication, and delaying and misunderstanding often occurs. Another thing is that many Japanese companies still make use of old software technologies, architectures, and processes, even when building new systems. One of the reason is that these systems have to inter-operate with legacy ones. However, as I see it, it is also because of their "legacy way of thinking". Japanese companies often consider that it is safer to use old methods, which are guaranteed to work but not very flexible and reusable. I must say that sketching out the system architecture, analyzing and designing in an object-oriented manner, and refactoring the code are among my favorite stuff. However, with Japanese companies I don’t have much chance to do them. A Japanese company often requires many kinds of reports and metrics, and it takes hours to explain them why a simple item of data does not match their norm.&lt;br&gt;
&lt;br&gt;
I am waiting for the weekend when I could go and see something interesting in &lt;st1:city st="on"&gt;Tokyo&lt;/st1:City&gt; and &lt;st1:city st="on"&gt;&lt;st1:place st="on"&gt;Yokohama&lt;/st1:place&gt;&lt;/st1:City&gt;. Geee&lt;/span&gt;&lt;/p&gt;</content><link href="http://thith.blogspot.com/feeds/113049060532234517/comments/default" rel="replies" title="Post Comments" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/18337532/113049060532234517" rel="replies" title="1 Comments" type="text/html"/><link href="http://www.blogger.com/feeds/18337532/posts/default/113049060532234517" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/18337532/posts/default/113049060532234517" rel="self" type="application/atom+xml"/><link href="http://thith.blogspot.com/2005/10/touch-of-japan.html" rel="alternate" title="A Touch of Japan" type="text/html"/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/15249069123623107491</uri><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>1</thr:total></entry></feed>