{"id":36693,"date":"2005-01-14T07:00:00","date_gmt":"2005-01-14T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/01\/14\/cleaner-more-elegant-and-harder-to-recognize\/"},"modified":"2005-01-14T07:00:00","modified_gmt":"2005-01-14T07:00:00","slug":"cleaner-more-elegant-and-harder-to-recognize","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050114-00\/?p=36693","title":{"rendered":"Cleaner, more elegant, and harder to recognize"},"content":{"rendered":"<p>\nIt appears that some people interpreted the title of\n<a HREF=\"\/oldnewthing\/archive\/2004\/04\/22\/118161.aspx\">\none of my rants from many months ago,\n&#8220;Cleaner, more elegant, and wrong&#8221;<\/a>,\nto be\n<a HREF=\"http:\/\/www.google.com\/search?q=cache:www.cs.wisc.edu\/condor\/doc\/thain-dissertation.ps\">\na reference to exceptions in general<\/a>.\n(See bibliography reference [35]; observe that the citer\neven changed the title of my article for me!)\n<\/p>\n<p>\nThe title of the article was a reference to a specific code snippet\nthat I copied from a book, where the book&#8217;s author claimed that\nthe code he presented was &#8220;cleaner and more elegant&#8221;.\nI was pointing out that the code fragment was not only cleaner\nand more elegant, it was also wrong.\n<\/p>\n<p>\nYou <strong>can<\/strong> write correct exception-based programming.\n<\/p>\n<p>\nMind you, it&#8217;s hard.\n<\/p>\n<p>\nOn the other hand, just because something is hard doesn&#8217;t mean\nthat it shouldn&#8217;t be done.\n<\/p>\n<p>\nHere&#8217;s a breakdown:\n<\/p>\n<table CELLSPACING=\"5\">\n<tr>\n<th>Really easy<\/th>\n<th>Hard<\/th>\n<th>Really hard<\/th>\n<\/tr>\n<tr>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">Writing bad error-code-based code<br \/>\nWriting bad exception-based code<\/td>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">Writing good error-code-based code<\/td>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">Writing good exception-based code<\/td>\n<\/tr>\n<\/table>\n<p>\nIt&#8217;s easy to write bad code, regardless of the error model.\n<\/p>\n<p>\nIt&#8217;s hard to write good error-code-based code since you have to check\nevery error code and think about what you should do when an error occurs.\n<\/p>\n<p>\nIt&#8217;s <strong>really<\/strong> hard to write good exception-based\ncode since you have to check every single line of code (indeed,\nevery sub-expression) and think\nabout what exceptions it might raise and how your code will react to it.\n(In C++ it&#8217;s not quite so bad because C++ exceptions are raised only\nat specific points during execution.\nIn C#, exceptions can be raised at any time.)\n<\/p>\n<p>\nBut that&#8217;s okay.  Like I said, just because something is hard\ndoesn&#8217;t mean it shouldn&#8217;t be done.\nIt&#8217;s hard to write a device driver, but people do it,\nand that&#8217;s a good thing.\n<\/p>\n<p>\nBut here&#8217;s another table:\n<\/p>\n<table CELLSPACING=\"5\">\n<tr>\n<th>Really easy<\/th>\n<th>Hard<\/th>\n<th>Really hard<\/th>\n<\/tr>\n<tr>\n<td VALIGN=\"TOP\">\n<table>\n<tr>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">\n        Recognizing that error-code-based code is badly-written<\/td>\n<\/tr>\n<tr>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">\n        Recognizing the difference between bad error-code-based code and\n        not-bad error-code-based code.<\/td>\n<\/tr>\n<\/table>\n<\/td>\n<td VALIGN=\"TOP\">\n<table>\n<tr>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">\n        Recognizing that error-code-base code is not badly-written<\/td>\n<\/tr>\n<\/table>\n<\/td>\n<td VALIGN=\"TOP\">\n<table>\n<tr>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">\n      Recognizing that exception-based code is badly-written<\/td>\n<tr>\n<tr>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">\n      Recognizing that exception-based code is not badly-written<\/td>\n<\/tr>\n<tr>\n<td VALIGN=\"baseline\" STYLE=\"border: solid black 1px\">\n      Recognizing the difference between bad exception-based code\n      and not-bad exception-based code<\/td>\n<\/tr>\n<\/table>\n<\/td>\n<\/table>\n<p>\nHere&#8217;s some imaginary error-code-based code.  See if you can\nclassify it as &#8220;bad&#8221; or &#8220;not-bad&#8221;:\n<\/p>\n<pre>\nBOOL ComputeChecksum(LPCTSTR pszFile, DWORD* pdwResult)\n{\n  HANDLE h = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ,\n       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n  HANDLE hfm = CreateFileMapping(h, NULL, PAGE_READ, 0, 0, NULL);\n  void *pv = MapViewOfFile(hfm, FILE_MAP_READ, 0, 0, 0);\n  DWORD dwHeaderSum;\n  CheckSumMappedFile(pvBase, GetFileSize(h, NULL),\n           &amp;dwHeaderSum, pdwResult);\n  UnmapViewOfFile(pv);\n  CloseHandle(hfm);\n  CloseHandle(h);\n  return TRUE;\n}\n<\/pre>\n<p>\nThis code is obviously bad.  No error codes are checked.\nThis is the sort of code you might write when in a hurry,\nmeaning to come back to and improve later.\nAnd it&#8217;s easy to spot that this code needs to be improved big time\nbefore it&#8217;s ready for prime time.\n<\/p>\n<p>\nHere&#8217;s another version:\n<\/p>\n<pre>\nBOOL ComputeChecksum(LPCTSTR pszFile, DWORD* pdwResult)\n{\n  BOOL fRc = FALSE;\n  HANDLE h = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ,\n       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n  if (h != INVALID_HANDLE_VALUE) {\n    HANDLE hfm = CreateFileMapping(h, NULL, PAGE_READ, 0, 0, NULL);\n    if (hfm) {\n      void *pv = MapViewOfFile(hfm, FILE_MAP_READ, 0, 0, 0);\n      if (pv) {\n        DWORD dwHeaderSum;\n        if (CheckSumMappedFile(pvBase, GetFileSize(h, NULL),\n                               &amp;dwHeaderSum, pdwResult)) {\n          fRc = TRUE;\n        }\n        UnmapViewOfFile(pv);\n      }\n      CloseHandle(hfm);\n    }\n    CloseHandle(h);\n  }\n  return fRc;\n}\n<\/pre>\n<p>\nThis code is still wrong, but it clearly looks like\nit&#8217;s trying to be right.  It is what I call &#8220;not-bad&#8221;.\n<\/p>\n<p>\nNow here&#8217;s some exception-based code you might write in a hurry:\n<\/p>\n<pre>\nNotifyIcon CreateNotifyIcon()\n{\n NotifyIcon icon = new NotifyIcon();\n icon.Text = \"Blah blah blah\";\n icon.Visible = true;\n icon.Icon = new Icon(GetType(), \"cool.ico\");\n return icon;\n}\n<\/pre>\n<p>\n(This is actual code from a real program in an article about\ntaskbar notification icons, with minor changes\nin a futile attempt to disguise the source.)\n<\/p>\n<p>\nHere&#8217;s what it might look like after you fix it to be correct\nin the face of exceptions:\n<\/p>\n<pre>\nNotifyIcon CreateNotifyIcon()\n{\n NotifyIcon icon = new NotifyIcon();\n icon.Text = \"Blah blah blah\";\n icon.Icon = new Icon(GetType(), \"cool.ico\");\n icon.Visible = true;\n return icon;\n}\n<\/pre>\n<p>\nSubtle, isn&#8217;t it.\n<\/p>\n<p>\nIt&#8217;s easy to spot the difference between bad error-code-based code\nand not-bad error-code-based code:  The not-bad error-code-based code\nchecks error codes.  The bad error-code-based code never does.\nAdmittedly, it&#8217;s hard to tell whether the errors were handled\ncorrectly, but at least you can tell the difference between\nbad code and code that isn&#8217;t bad.  (It might not be good, but at least\nit isn&#8217;t bad.)\n<\/p>\n<p>\nOn the other hand, it is extraordinarily difficult to see the\ndifference between bad exception-based code and not-bad\nexception-based code.\n<\/p>\n<p>\nConsequently, when I write code that is exception-based,\nI do not have the luxury of writing bad code first and then\nmaking it not-bad later.  If I did that, I wouldn&#8217;t be able to find\nthe bad code again, since it looks almost identical to not-bad code.\n<\/p>\n<p>\nMy point isn&#8217;t that exceptions are bad.\nMy point is that exceptions are too hard and I&#8217;m not smart\nenough to handle them.  (And neither, it seems, are book authors,\neven when they are trying to teach you how to program with exceptions!)\n<\/p>\n<p>\n(Yes, there are programming models like RAII and transactions,\nbut rarely do you see sample code that uses either.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It appears that some people interpreted the title of one of my rants from many months ago, &#8220;Cleaner, more elegant, and wrong&#8221;, to be a reference to exceptions in general. (See bibliography reference [35]; observe that the citer even changed the title of my article for me!) The title of the article was a reference [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-36693","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>It appears that some people interpreted the title of one of my rants from many months ago, &#8220;Cleaner, more elegant, and wrong&#8221;, to be a reference to exceptions in general. (See bibliography reference [35]; observe that the citer even changed the title of my article for me!) The title of the article was a reference [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36693","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=36693"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36693\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=36693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=36693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=36693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}