ときどきの雑記帖″

最新ページへのリンク
目次ページへのリンク

一つ前へ 2013年12月(下旬)
一つ後へ 2014年11月(中旬)

ホームへ

2014年01月10日

■_

いきてー 東京都・御茶ノ水でインフォグラフィックスデザインに関する特別セミナー | マイナビニュース

面白そう。なんとなくネットカフェみたいな気もするけど。 London's first pay-per-minute cafe | Hacker News London's first pay-per-minute cafe: will the idea catch on? | Travel | theguardian.com

■_

メモ的に。 時相論理 - Wikipedia 線形時相論理 - Wikipedia 様相論理 - Wikipedia 計算木論理 - Wikipedia I-Scover 基本検索 - ソフトウェア変更に対するバグ予測モデルの精度評価 組込みシステム技術連携研究体 産総研 TODAY 2011.12 VOL.11-12 共同研究事例:形式手法を利用した高信頼ソフトウェアのためのテスト設計技術の開発 『プログラム検証論(林 晋)』 復刊リクエスト投票

■_ yylloc

こんな拡張もしてたのか>Bison

Bison 3.0.2

2.4.2 Grammar Rules for ltcalc

Whether handling locations or not has no effect on the syntax of your language. Therefore, grammar rules for
this example will be very close to those of the previous example: we will only modify them to benefit from the
new information.

Here, we will use locations to report divisions by zero, and locate the wrong expressions or subexpressions.

     input:
       %empty
     | input line
     ;
     
     line:
       '\n'
     | exp '\n' { printf ("%d\n", $1); }
     ;
     
     exp:
       NUM           { $$ = $1; }
     | exp '+' exp   { $$ = $1 + $3; }
     | exp '-' exp   { $$ = $1 - $3; }
     | exp '*' exp   { $$ = $1 * $3; }
     | exp '/' exp
         {
           if ($3)
             $$ = $1 / $3;
           else
             {
               $$ = 1;
               fprintf (stderr, "%d.%d-%d.%d: division by zero",
                        @3.first_line, @3.first_column,
                        @3.last_line, @3.last_column);
             }
         }
     | '-' exp %prec NEG     { $$ = -$2; }
     | exp '^' exp           { $$ = pow ($1, $3); }
     | '(' exp ')'           { $$ = $2; }

This code shows how to reach locations inside of semantic actions, by using the pseudo-variables @n for rule
components, and the pseudo-variable @$ for groupings.

We don't need to assign a value to @$: the output parser does it automatically. By default, before executing
the C code of each action, @$ is set to range from the beginning of @1 to the end of @n, for a rule with n
components. This behavior can be redefined (see Default Action for Locations), and for very specific rules, @$
can be computed by hand. 

■_

2014年01月09日

■_

寒い。

■_

Real World OCaml
Real World OCaml の話。 Book Review and Interview: Real World OCaml

Book Review and Interview: Real World OCaml

(ざっくり略)

InfoQ:  Are there unique features of OCaml that make it stand out?

    The most distinctive aspect of OCaml is its static type system. If you're used to languages like Java,
    you'll be surprised at how effective it is at catching bugs at the earliest stage of development. At the
    same time, the type system is very lightweight, with code that performs like a compiled language but is
    as terse as a scripting language like Python or Ruby.

    OCaml's `match` statement is a particularly effective tool, providing a form of data-structure-driven case
    analyses, where the compiler provides compile-time guarantees that you haven't missed any cases (see here).
    It's also highly efficient and concise (see here). 


InfoQ: How often does the word "monad" occur in the book? Are monads a popular topic in the OCaml
space or does the OCaml community have different solutions for the problems monads in Haskell solve, ie like
the F# community? Bonus question: what's your favorite monad?

    Monads are important in OCaml, but it's different from a language like Haskell where all imperative
    programming must be done with a monad. In Haskell, any program that interacts with the outside world (i.e.,
    any useful program) needs to use monads. Because monads aren't needed for imperative programming, monads
    tend to be more of an advanced topic in OCaml. That said, they're very useful.

    My favorite monad is no doubt Async, a library for concurrent programming where a monad is used to represent
    a computation that may block for a non-deterministic period of time. We use the Async monad to build an HTTP
    client for the DuckDuckGo search engine in Real World OCaml, including error handling. 

以下すっぱりと略

ううむ、本自体に対する質問がほとんどナッシング?

■_

これ、ダムエーで連載してたときから単行本にまとまらないかなあと 待ってたのだけど、ガンダムさんの単行本にいっしょに入ってるというのに気がついたのは だいぶ経ってからだったんだよなあ。で買う気が失せたと。 こうして独立したのになったのは嬉しい限り。 [機動戦士ガンダム]誕生秘話描く「ガンダム創世」 タイトル一新しコミックス化 | マイナビニュース 人気アニメ「機動戦士ガンダム」の誕生秘話を描いたマンガ「『ガンダム』と創った男たち。」(KADOKAWA) が、25日に発売されることが分かった。“ガンダム”シリーズの生みの親として知られる富野由悠季総監督、 キャラクターデザインを担当した安彦良和さん、メカニックデザインを担当した大河原邦男さんら当時の制作スタッフをモデルとしたキャラクターが登場し、 実話を基に、フィクションを加えてガンダム誕生秘話が描かれる。 (略)  大和田秀樹さんの4コママンガ「機動戦士ガンダムさん」5~9巻(いつつめの巻~ここのつめの巻) に収録されている短編「ガンダム創世」のタイトルを一新し、再編集して上下巻でコミックス化。 当時のガンダムに関する新聞や雑誌の記事や写真も掲載されるほか、 月刊誌「ニュータイプエース」Vol.1~7に掲載された「トミノ伝」も収録される。

■_

Finding the Minimum Set of Languages to Learn All Programming Paradigms : programming

■_

■_ マクロがあれば

Stop Writing JavaScript Compilers! Make Macros Instead

Stop Writing JavaScript Compilers! Make Macros Instead

Real macros were born from Lisp in the 1980's with defmacro. It's shocking how often good ideas have roots back
into papers from the 70s and 80s, and even specifically from Lisp itself. It was a natural step for Lisp
because Lisp code has exactly the same syntax as its data structures. This means it's easy to throw data and
code around and change its meaning.

Lisp went on to prove that macros fundamentally change the ecosystem of the language, and it's no surprise that
newer languages have worked hard to include them.

2014年01月08日

■_

ここんところまた音に対する耐性が落ちてるようできつい。 難聴 聴覚過敏症 ではないと思うんだけど…

■_

Python code to solve xkcd 1313 by Peter Norvig | Hacker News Python code to solve xkcd 1313 (Peter Norvig) : programming とその元記事の xkcd 1313: Regex Golf について書こうと思ったが時間がががが

■_ TIOBE

今月はちょっと早い? (10日過ぎくらいの印象が) TIOBE Software: Tiobe Index で、 2013年はTransact-SQL躍進の年、Objective-Cも急成長 - TIOBE人気言語調査 | マイナビニュース CとJavaはこの数年首位の入れ替わりを繰り返してきたが、長期の傾向としてC言語は上り調子にあり、Javaは下がり調子にある。 ってあるんだけど、 Tiobe Index のページにあるグラフ(TIOBE Programming Community Inndex)を見た感じでは Java の Rating が下降傾向にあるというのはともかく C の Rating が上昇傾向だと言っちゃうのは ? な感じが。 「長期の傾向」がどういう期間なのかわからんけども。

■_

■_

こんなイベントやってたとは。 実質、いけるのは今日(木曜日)だけなんだけどううむ… 開催中イベント - ラジカセ・ヴィンテージ家電、オーディオの販売・修理 2014年1月2日より1月10日(金)まで、東京・渋谷ヒカリエ9階、ホワイエAに於いて 特別展示企画「家電黄金時代の傑作たち」を開催しております。 開催中、歴代ラジカセの展示、整備済みラジカセ販売、70年代アナログ家電(書籍)より 家電カタログの原本を展示(一部販売)しています。歴代のラジカセが一堂に見れる機会は なかなかありません。ぜひこの機会にご覧頂ければと存じます。

2014年01月07日

■_

とりあえずこの辺がとっかかりになりそう (時相論理じゃなくて様相論理だけど) Amazon.co.jp: 情報科学における論理 (情報数学セミナー): 小野 寛晰: 本

■_

■_

早くもやる気が危機的レベルで下降中

2014年01月06日

■_

2014年出社一日目。 あれやらこれやら。

■_ numfmt

numfmt - jarp, ということでどんなんだか見てみた numfmt invocation - GNU Coreutils

numfmt invocation - GNU Coreutils

4.2 numfmt: Reformat numbers

numfmt reads numbers in various representations and reformats them as requested. The most common usage is
converting numbers to/from human representation (e.g. ‘4G’ ==> ‘4,000,000,000’).

     numfmt [option]... [number]

numfmt converts each number on the command-line according to the specified options (see below). If no numbers
are given, it reads numbers from standard input. numfmt can optionally extract numbers from specific columns,
maintaining proper line padding and alignment.

An exit status of zero indicates success, and a nonzero value indicates failure.

(略)

4.2.3 Examples of using numfmt

Converting a single number from/to human representation:

     $ numfmt --to=si 500000
     500K
     
     $ numfmt --to=iec 500000
     489K
     
     $ numfmt --to=iec-i 500000
     489Ki
     
     $ numfmt --from=si 1M
     1000000
     
     $ numfmt --from=iec 1M
     1048576
     
     # with '--from=auto', M=Mega, Mi=Mebi
     $ numfmt --from=auto 1M
     1000000
     $ numfmt --from=auto 1Mi
     1048576

(略)

With locales that support grouping digits, using --grouping or --format enables grouping. In ‘POSIX’ locale,
grouping is silently ignored:

     $ LC_ALL=C numfmt --from=iec --grouping 2G
     2147483648
     
     $ LC_ALL=en_US.utf8 numfmt --from=iec --grouping 2G
     2,147,483,648
     
     $ LC_ALL=ta_IN numfmt --from=iec --grouping 2G
     2,14,74,83,648
     
     $ LC_ALL=C ./src/numfmt --from=iec --format="==%'15f==" 2G
     ==     2147483648==
     
     $ LC_ALL=en_US.utf8 ./src/numfmt --from=iec --format="==%'15f==" 2G
     ==  2,147,483,648==
     
     $ LC_ALL=en_US.utf8 ./src/numfmt --from=iec --format="==%'-15f==" 2G
     ==2,147,483,648  ==
     
     $ LC_ALL=ta_IN ./src/numfmt --from=iec --format="==%'15f==" 2G
     == 2,14,74,83,648==

へー、なかなか芸が細かい

■_

で、coreutils に入ってるのには何があるのだろうか確認

GNU Coreutils

Output of entire files: cat tac nl od base64
Formatting file contents: fmt pr fold
Output of parts of files: head tail split csplit
Summarizing files: wc sum cksum md5sum sha1sum sha2
Operating on sorted files: sort shuf uniq comm ptx tsort
Operating on fields: cut paste join
Operating on characters: tr expand unexpand
Directory listing: ls dir vdir dircolors
Basic operations: cp dd install mv rm shred
Special file types: mkdir rmdir unlink mkfifo mknod ln link readlink
Changing file attributes: chgrp chmod chown touch
Disk usage: df du stat sync truncate
Printing text: echo printf yes
Conditions: false true test expr
Redirection: tee
File name manipulation: dirname basename pathchk mktemp realpath
Working context: pwd stty printenv tty
User information: id logname whoami groups users who
System context: date arch nproc uname hostname hostid uptime
SELinux context: chcon runcon
Modified command invocation: chroot env nice nohup stdbuf timeout
Process control: kill
Delaying: sleep
Numeric operations: factor seq 

幾つかなじみのないのがあるな

■_

そしてソースコード。

(略)

/* Parse a numeric value (with optional suffix) from a string.
   Returns a long double value, with input precision.

   If there's an error converting the string to value - exits with
   an error.

   If there are any trailing characters after the number
   (besides a valid suffix) - exits with an error.  */
static enum simple_strtod_error
parse_human_number (const char *str, long double /*output */ *value,
                    size_t *precision)
{
  char *ptr = NULL;

  enum simple_strtod_error e =
    simple_strtod_human (str, &ptr, value, precision, scale_from);
  if (e != SSE_OK && e != SSE_OK_PRECISION_LOSS)
    {
      simple_strtod_fatal (e, str);
      return e;
    }

  if (ptr && *ptr != '\0')
    {
      if (_invalid != inval_ignore)
        error (conv_exit_code, 0, _("invalid suffix in input %s: %s"),
               quote_n (0, str), quote_n (1, ptr));
      e = SSE_INVALID_SUFFIX;
    }
  return e;
}


/* Print the given VAL, using the requested representation.
   The number is printed to STDOUT, with padding and alignment.  */
static int
prepare_padded_number (const long double val, size_t precision)
{
  /* Generate Output. */
  char buf[128];

  /* Can't reliably print too-large values without auto-scaling. */
  unsigned int x;
  expld (val, 10, &x);
  if (scale_to == scale_none && x > MAX_UNSCALED_DIGITS)
    {
      if (_invalid != inval_ignore)
        error (conv_exit_code, 0, _("value too large to be printed: '%Lg'"
                                    " (consider using --to)"), val);
      return 0;
    }

  if (x > MAX_ACCEPTABLE_DIGITS - 1)
    {
      if (_invalid != inval_ignore)
        error (conv_exit_code, 0, _("value too large to be printed: '%Lg'"
                                    " (cannot handle values > 999Y)"), val);
      return 0;
    }

  double_to_human (val, precision, buf, sizeof (buf), scale_to, grouping,
                   _round);
  if (suffix)
    strncat (buf, suffix, sizeof (buf) - strlen (buf) -1);

  devmsg ("formatting output:\n  value: %Lf\n  humanized: %s\n",
          val, quote (buf));

  if (padding_width && strlen (buf) < padding_width)
    {
      size_t w = padding_width;
      mbsalign (buf, padding_buffer, padding_buffer_size, &w,
                padding_alignment, MBA_UNIBYTE_ONLY);

      devmsg ("  After padding: %s\n", quote (padding_buffer));
    }
  else
    {
      setup_padding_buffer (strlen (buf) + 1);
      strcpy (padding_buffer, buf);
    }

  return 1;
}

static void
print_padded_number (void)
{
  if (format_str_prefix)
    fputs (format_str_prefix, stdout);

  fputs (padding_buffer, stdout);

  if (format_str_suffix)
    fputs (format_str_suffix, stdout);
}

/* Converts the TEXT number string to the requested representation,
   and handles automatic suffix addition.  */
static int
process_suffixed_number (char *text, long double *result, size_t *precision)
{
  if (suffix && strlen (text) > strlen (suffix))
    {
      char *possible_suffix = text + strlen (text) - strlen (suffix);

      if (STREQ (suffix, possible_suffix))
        {
          /* trim suffix, ONLY if it's at the end of the text.  */
          *possible_suffix = '\0';
          devmsg ("trimming suffix %s\n", quote (suffix));
        }
      else
        devmsg ("no valid suffix found\n");
    }

  /* Skip white space - always.  */
  char *p = text;
  while (*p && isblank (*p))
    ++p;
  const unsigned int skip_count = text - p;

  /* setup auto-padding.  */
  if (auto_padding)
    {
      if (skip_count > 0 || field > 1)
        {
          padding_width = strlen (text);
          setup_padding_buffer (padding_width);
        }
      else
        {
          padding_width = 0;
        }
     devmsg ("setting Auto-Padding to %ld characters\n", padding_width);
    }

  long double val = 0;
  enum simple_strtod_error e = parse_human_number (p, &val, precision);
  if (e == SSE_OK_PRECISION_LOSS && debug)
    error (0, 0, _("large input value %s: possible precision loss"),
           quote (p));

  if (from_unit_size != 1 || to_unit_size != 1)
    val = (val * from_unit_size) / to_unit_size;

  *result = val;

  return (e == SSE_OK || e == SSE_OK_PRECISION_LOSS);
}

/* Skip the requested number of fields in the input string.
   Returns a pointer to the *delimiter* of the requested field,
   or a pointer to NUL (if reached the end of the string).  */
static inline char * _GL_ATTRIBUTE_PURE
skip_fields (char *buf, int fields)
{
  char *ptr = buf;
  if (delimiter != DELIMITER_DEFAULT)
    {
      if (*ptr == delimiter)
        fields--;
      while (*ptr && fields--)
        {
          while (*ptr && *ptr == delimiter)
            ++ptr;
          while (*ptr && *ptr != delimiter)
            ++ptr;
        }
    }
  else
    while (*ptr && fields--)
      {
        while (*ptr && isblank (*ptr))
          ++ptr;
        while (*ptr && !isblank (*ptr))
          ++ptr;
      }
  return ptr;
}

/* Parse a delimited string, and extracts the requested field.
   NOTE: the input buffer is modified.

   TODO:
     Maybe support multiple fields, though can always pipe output
     into another numfmt to process other fields.
     Maybe default to processing all fields rather than just first?

   Output:
     _PREFIX, _DATA, _SUFFIX will point to the relevant positions
     in the input string, or be NULL if such a part doesn't exist.  */
static void
extract_fields (char *line, int _field,
                char ** _prefix, char ** _data, char ** _suffix)
{
  char *ptr = line;
  *_prefix = NULL;
  *_data = NULL;
  *_suffix = NULL;

  devmsg ("extracting Fields:\n  input: %s\n  field: %d\n",
          quote (line), _field);

  if (field > 1)
    {
      /* skip the requested number of fields.  */
      *_prefix = line;
      ptr = skip_fields (line, field - 1);
      if (*ptr == '\0')
        {
          /* not enough fields in the input - print warning?  */
          devmsg ("  TOO FEW FIELDS!\n  prefix: %s\n", quote (*_prefix));
          return;
        }

      *ptr = '\0';
      ++ptr;
    }

  *_data = ptr;
  *_suffix = skip_fields (*_data, 1);
  if (**_suffix)
    {
      /* there is a suffix (i.e. the field is not the last on the line),
         so null-terminate the _data before it.  */
      **_suffix = '\0';
      ++(*_suffix);
    }
  else
    *_suffix = NULL;

  devmsg ("  prefix: %s\n  number: %s\n  suffix: %s\n",
          quote_n (0, *_prefix ? *_prefix : ""),
          quote_n (1, *_data),
          quote_n (2, *_suffix ? *_suffix : ""));
}


/* Convert a number in a given line of text.
   NEWLINE specifies whether to output a '\n' for this "line".  */
static int
process_line (char *line, bool newline)
{
(略)

C で書かれたプログラムとしては小さめで 読み慣れてない人が読むにはいいんじゃなかろうか。 色々お約束なこともやってるし(オプション解析とか)。 とはいえC を読み書きすることの必要性が以下略

■_

2014年01月05日

■_

新年早々面倒な話が降ってきた。 いや、蒸し返されたというべきか。

第1次世界大戦から100年 歴史の再検証も NHKニュース 以前にも書いたことがあると思うんだけど、ずーーーっと以前にNHK(教育(当時)のほうだったかも)で 放映した海外ドキュメンタリーの第一次世界大戦とりあげてたのをもう一度みたい。 番組名も覚えてないんだけど。

やっべ先行予約期間ぎりぎりー 【先行予約】31バイトでつくるアセンブラプログラミング ~アセンブラ短歌の世界~ | マイナビブックス 【先行予約】Rubyで作る奇妙なプログラミング言語 ~ヘンな言語のつくりかた~ | マイナビブックス

■_

twitter から。 リンカー辺りまで含めてどうにかしないといけないんじゃないかなあ とは思ってるんですがさて。>再設計

■_

2014年01月04日

■_

久しぶりに明倫館に行ったが、買おうか悩んでいた本(売価一万円)がなくなっていた。 売れたんだろうなあ。

この辺を扱ったもので良い本ないでしょうか 時相論理 - Wikipedia

Amazon.co.jp: プログラミング言語の基礎概念 (ライブラリ情報学コア・テキスト): 五十嵐 淳: 本 このシリーズ(ライブラリ情報学コアテキスト)の11番て、 「プログラム意味論の基礎」とかいうタイトルなんですね。 まだ刊行されてないみたいだけど。

■_ %

コミケで買ったPerl6本を読んでいたら % を使った見慣れない記述があったので調べてみた。

S05

Any quantified atom may be modified by an additional constraint that specifies the separator to look for
between repeats of the left side. This is indicated by use of a % between the quantifier and the separator.
The initial item is iterated only as long as the separator is seen between items:

    <alt>+ % '|'            # repetition controlled by presence of character
    <addend>+ % <addop>     # repetition controlled by presence of subrule
    <item>+ % [ \!?'==' ]   # repetition controlled by presence of operator
    <file>+%\h+             # repetition controlled by presence of whitespace

Any quantifier may be so modified:

    <a>* % ','              # 0 or more comma-separated elements
    <a>+ % ','              # 1 or more 
    <a>? % ','              # 0 or 1 (but ',' never used!?!)
    <a> ** 2..* % ','       # 2 or more 

The % modifier may only be used on a quantifier; any attempt to use it on a bare term will result in a parse
error (to minimize possible confusion with any hash notations we choose to support in Perl 6 regexes).

A successful match of a % construct generally ends "in the middle" at the %, that is, after the
initial item but before the next separator. Therefore

    / <ident>+ % ',' /

can match

    foo
    foo,bar
    foo,bar,baz

but never

    foo,
    foo,bar,

ううむこんなのいつの間に…

S05

VERSION

    Created: 24 Jun 2002

    Last Modified: 28 Dec 2013
    Version: 169

おおう。

■_

2014年01月03日

■_

テレ玉で、1/1と1/2にそれぞれ0083(ジオンの残光)と逆シャアを放送してまして。 機動戦士ガンダム0083 STARDUST MEMORY - Wikipedia 封切日 1992年8月29日 機動戦士ガンダム 逆襲のシャア - Wikipedia 公開 1988年3月12日 なるほど絵に時代を感じるわけだw しかし 0083 からでも20年以上経ってるのねえ… 機動戦士ガンダム0083 -ジオンの残光- [Blu-ray]
機動戦士ガンダム0083 -ジオンの残光- [Blu-ray] 機動戦士ガンダム 逆襲のシャア [Blu-ray]
機動戦士ガンダム 逆襲のシャア [Blu-ray]

ブルーバックスでJavaScript本がっ Amazon.co.jp: 入門者のJavaScript (ブルーバックス): 立山 秀利: 本 Amazon.co.jp: とある弁当屋の統計技師(データサイエンティスト) 2 ―因子分析大作戦―: 石田 基広: 本 また,さらに本書の内容をソフトウェアで追体験できるよう,本書用のソフトウェア・パッケージを開発し公開する予定です。 お、これは。

■_

■_

A Hard Case for Memory Safety - pcwalton

=============================
A Hard Case for Memory Safety
=============================

Quick quiz: In this C++ program, is the definition of munge guaranteed to be memory safe? (Assume that the
definition of increment_counter uses only modern C++ idioms and doesn’t do anything like dereference an
invalid pointer.)

クイズ: 次の C++ プログラムにおける munge の定義は memory safe であることを保証するでしょうか?
(increment_counter の定義では Modern C++ の idiom のみを使い、invalid pointer の dereference のようなことは行
わないと仮定します)

  #include <iostream>
  #include <vector>
  
  class foo {
  public:
      std::vector<int> indices;
      int counter;
  
      foo() : indices(), counter(0) {
          indices.push_back(1);
          indices.push_back(2);
          indices.push_back(3);
      }
  
      void increment_counter();
  
      int &get_first_index() {
          assert(indices.size() > 0);
          return indices[0];
      }
  
      void munge() {
          int &first = get_first_index();
          increment_counter();
          std::cout << first << std::endl;
          first = 20;
      }
  };
  
  int main() {
      foo foo;
      foo.munge();
      return 0;
  }
  
The answer: Even with this caveat, we can’t tell! It depends on the definition of increment_counter.
If increment_counter has this definition, the code is memory safe:

解答:
Even with this caveat, we can’t tell!
increment_counter の定義に依存しているのです。
もし increment_counter が次のような定義であれば、上記のコードは memory safe です:


  void foo::increment_counter() {
      counter++;
  }

But if increment_counter has this definition, for example, then it isn’t:

しかし increment_counter がたとえば次のような定義であった場合は memory safe ではありません

  void foo::increment_counter() {
      indices.clear();
      counter++;
  }

This definition would cause the first reference in munge to become a dangling reference, and the call to
std::cout and subsequent assignment of first will have undefined behavior. If first were not an int but were
instead an instance of a class, and munge attempted to perform a virtual method call on it, then this would
constitute a critical security vulnerability.

この定義では munge における first reference が dangling reference を引き起こす可能性があります。また std::out
に対する呼び出しとそれに続く先頭要素の代入は undefined behavior になっています。最初の要素が int ではなくある
クラスのインスタンスであり、かつ、munge がそれに対して virtual method を呼び出そうとした場合には これは
critical security vulnerability の一部となってしまうでしょう。


The point here is that determining memory safety in C++ requires non-local reasoning. Any analysis that tries
to determine safety of C++ code, whether performed by a machine or performed by a human auditor, has to analyze
many functions all at once, rather than one function at a time, to determine whether the code is memory safe.
As this example illustrates, sticking to modern C++ coding styles, even with bounds checks, is not enough to
prevent this.

ここでのポイントは C++ における memory safety の determining が non-local な証明 reasoning を要求するということ
です。C++ コードの safety を determine しようとする analysis はすべて、対象のコードがmemory safe であるかどうか
決定するためには一度に一つの関数を調べるのではなく多数の関数を一度に調べなければなりません。これは機械によって
行うのか人手で行うのかにはよりません。この例が示すように、modern C++ coding style に sticking することは
bounds checks を使ったとしてもこの問題を prevent するには充分ではありません。


There are a few ways around this:
対処法はいくつかあります


    For each function call, analyze the source to the called function to determine whether it’s memory safe in
    the context of the caller. This doesn’t always work, though: it’s hard or impossible when function
    pointers or virtual methods are involved (which function ends up being called?), and it’s hard with
    separately compiled code (what if the called function is in a DLL that you don’t have source for?)

    たとえば、関数の呼び出しごとに、その呼び出し元のコンテキストでの memory safe がどうであるか決定するために呼
    び出された関数のソースを解析するというやり方があります。しかしこれは毎回うまくいくというわけではありません。
    関数ポインターや仮想メソッドがいつ involve されるかの判断というものは、困難であるかあるいは不可能ですらあり
    ます (最終的にどの関数が呼びされるのでしょうか?)。また、分割コンパイルされたコードに対しても難しいものがあり
    ます (もし呼び出された関数があなたがソースコードを持っていない DLL に存在しているものであったらどうなるでし
    ょうか?)。


    Change the type of indices to std::vector<std::shared_ptr<int>>; i.e. use reference counting to
    keep the pointer alive. This has a runtime cost.

    添え字の型を std::vector<std::shart_ptr<int>> に変更する。つまり参照カウンターを使うというもの
    ですが、これには実行コストがかかります。

    Inline the body of increment_counter, so that the memory safety of munge is immediately clear.

    increment_counter の本体をインライン展開 inline し、munge の memory safety を即座に clear する。


    Make increment_counter a class method (or just a function) instead of an instance method, and have it take
    counter by reference. The idea here is to prevent the possibility that increment_counter could mess with
    indices in any way by shutting off its access to it.

    increment_counter をインスタンスメソッドからクラスメソッド(もしくは単なる関数)に変更し、かつ、counter を
    参照で take させる。このアイデアでは increment_counter が mess with indices になってしまう可能性を、それ
    に対するアクセスを shutting off することによって prevent しています。

What does this have to do with Rust? In fact, this error corresponds to a borrow check error that Brian
Anderson hit when working on the scheduler. In Rust, the corresponding code looks something like this:

Rust で行わなければならないことはなんでしょうか? 実際にこのエラーは Brian Anderson がスケジューラーの作業をし
ているときに遭遇した borrow check error に対応したものです。Rust での corresponding code は次のようなものにな
ります:

  impl Foo {
      fn get_first_index(&'a mut self) -> &'a mut int {
          assert!(self.indices.len() > 0);
          return &mut indices[0];
      }

      fn munge(&mut self) {
          let first = self.get_first_index();
          self.increment_counter(); // ERROR
          println(first.to_str());
          *first = 20;
      }
  }
 
This causes a borrow check error because the first reference conflicts with the call to increment_counter. The
reason the borrow check complains is that the borrow check only checks one function at a time, and it could
tell (quite rightly!) that the call to increment_counter might be unsafe. The solution is to make
increment_counter a static method that only has access to counter; i.e. to rewrite the self.increment_counter()
line as follows:

これは borrow check error を引き起こします。なぜならその first の参照が increment counter の呼び出しと conflict
するからです。borrow check が complains する理由はその borrow check が一度に一つの関数しか check しないので、
increment counter の呼び出しを unsafe とみなしてしまう可能性がある (quiterightly!) からです。これに対する
solution は、increment counter を counter に対するアクセスしか持たない static method にするというものです。つま
り、self.increment_counter() の行を次のように書き変えます。 


   Foo::increment_counter(&mut self.counter);


Since the borrow check now sees that increment-counter couldn't possibly destroy the first refrence, it now
accepts the code.

increment-Counterが first refrence を destroy できなくなっているか borrow check で確認するようになったので、
code は accept されます。 


Fortunately, such borrow check errors are not as common anymore, with the new simpler borrow check rules. But
it’s interesting to see that, when they do come up, they’re warning about real problems that affect any
language with manual memory management. In the C++ code above, most programmers probably wouldn’t notice the
fact that the memory safety of munge depends on the definition of increment_counter. The challenge in Rust,
then, will be to make the error messages comprehensible enough to allow programmers to understand what the
borrow checker is warning about and how to fix any problems that arise.

幸いなことにそういった borrow check のエラーは、新しいもっと単純な borrow check rules によって、もはやそれほど
一般的なものではなくなりました。それでも borrow check は manual memory management を行うすべての言語に影響する
本当の問題 real problems を警告します。大部分のプログラマーは、前述の C++ コードにおいて munge の memory safety
が increxnent_counter の定義に依存していることに気がつかないでしょう。そして Rust の challenge とは、borrow
checker が警告していることと、発生しているすべての問題を解決するための方法をプログラマーが理解できるくらい
error message を 充分に comprehensible なものにすることなのです。

2014年01月02日

■_

更新まだだろか Technology Radar May 2013 | ThoughtWorks

news - the future of computing

■_ The Lost Art of

The Lost Art of C Structure Packing | Hacker News なんだいこれとリンク先を見てみれば書いたのは Eric S. Raymond。

reddit でも取りあげられてた。 The Lost Art of C Structure Packing : programming

The Lost Art of C Structure Packing

1. Who should read this

This page is about a technique for reducing the memory footprint of C programs - manually repacking C structure
declarations for reduced size. To read it, you will require basic knowledge of the C programming language.

(略)

2. Why I wrote it

This webpage exists because in late 2013 I found myself heavily applying a C optimization technique that I had
learned more than two decades previously and not used much since.

I needed to reduce the memory footprint of a program that used thousands - sometimes hundreds of thousands -
of C struct instances. The program was cvs-fast-export and the problem was that it was dying with out-of-memory
errors on large repositories.

There are ways to reduce memory usage significantly in situations like this, by rearranging the order of
structure members in careful ways. This can lead to dramatic gains - in my case I was able to cut the
working-set size by around 40%, enabling the program to handle much larger repositories without dying.

今回の例のように、構造体のメンバーの並びを注意深く並び替えることによってメモり使用量を大幅に縮小する
手法がいくつかあります。これは dramatic gains に繋がります。
わたしの例の場合、ワーキングセットの大きさを40%くらいにまで小さくでき、
プログラムがより大きなリポジトリを落ちずに扱えるようになったのです。

But as I worked, and thought about what I was doing, it began to dawn on me that the technique I was using has
been more than half forgotten in these latter days. A little web research confirmed that C programmers don’t
seem to talk about much it any more, at least not where a search engine can see them. A couple of Wikipedia
entries touch the topic, but I found nobody who covered it comprehensively.

しかし今回わたしが行ったように、また自分の行ったことを振り返ってみると自分の使ったこういったテクニックが
今日ではあらかた忘れさられてしまっていることが残念に思えてきたのです。
#チョー訳
web でちょっと検索してみると、C プログラマーたちは最早こういったことについて話しあうことはしていないようでした。
少なくとも検索エンジンでは見つけられませんでした。
Wikipedia にはいくつかこのことに触れているエントリーがありましたが、
包括的にカバーしているものは見つけられませんでした。

There are actually reasons for this that aren’t stupid. CS courses (rightly) steer people away from
micro-optimization towards finding better algorithms. The plunging price of machine resources has made
squeezing memory usage less necessary. And the way hackers used to learn how to do it back in the day was by
bumping their noses on strange hardware architectures - a less common experience now.

But the technique still has value in important situations, and will as long as memory is finite. This document
is intended to save C programmers from having to rediscover the technique, so they can concentrate effort on
more important things.

しかし今回使ったようなテクニックは、メモリーが有限である限り重要なシチュエーションでは今でも価値があります。
このドキュメントはテクニックの再発見をしなければならない状況からC プログラマーを助けて、
彼らがより重要なことに注力できるようにするのを目指すものです。

うう、なんか見慣れない表現が多くて辛い bumping their noses on とか

■_ iron

こんなツイートを見かけた

「Soldering iron」でなかったっけ? soldering iron - Google 検索 で、たしか Think GNU (シンク グヌー) に「半田ごて」を英語でなんと言うかわからなくて…というエピソードがあったよなあと検索 (まさか「はんだ」と「ソーダリング・アイロン」のように仮名書きされてるとは思わなかったのでちょっと時間かかった) はんだ site:x19290.appspot.com - Google 検索

Think GNU 第 3 回 □ボストン編□

 脱線ついでに、英語事件も暴露しよう。はんだごて事件である。 はんだごてを英語で言うと、ソーダリング・アイロン。 使っていた MIT の Sun と先に繋いでいたパソコンとの間のケーブル (RS232C) のはんだ付けが悪くて、 rms に言って直す道具を借りようとした。 はんだ付けのことをソーダリングと言うのは知っていたのでハンダごてのことを ソーダリング・ヒータと呼ぶのだろうと勘違いして、rms に「ソーダリング・ヒータどこかにある ?」と尋ねた。 彼からは「ソーダをホットにすることは可能だけど、誰もホットにしないよ。冷たくするもんだよ」という返事。 つまり、ソーダ水とはんだのソーダが入れ違ってしまった。こうなったら、モノを見せて繋げたいんだと言うしかなく、 見せたところようやく理解してもらえた。その後が問題で、これが rms には大うけで、 大笑いしてあちこちの研究員の友達の部屋に顔を突っ込んでは、この話をして回ったのであった。

他の回も読みふけってしまいしばし遠い目をしたなど。

■_

2014年1月1日

■_

事情により新年の挨拶は控えさせていただきます。

■_ 2013年を振り返る

と言ってもろくすっぽアウトプットなかったよねえという…

■_

Rebel without a clause: 5 ways to misuse exception handling

Introduction

Do you consider yourself a Java expert?
あなたは自分を Java のエキスパートだとみなしていますか?

Think you know everything about exception handling ?
自分は例外処理について何でも知っていると考えていますか?

Can you quickly spot five exception handling problems below?
以下のプログラムにある例外処理に関する問題点を五つ、即座に指摘できますか?


  OutputStreamWriter out = ...

  java.sql.Connection conn = ...

  try {
      Statement stat = conn.createStatement();
      ResultSet rs = stat.executeQuery(
                  "select uid, name from user");
      while (rs.next())
      {
          out.println("User ID : " + rs.getString("uid") +
            ", name : " + rs.getString("name"));
      }

      conn.close();
      out.close();  }
  catch(Exception ex)
  {
      ex.printStackTrace();
  }


Every Java developer should be able to spot at least two. If you can't spot all five, then read on – there is
something in here for you.

すべての Java developer は、少なくとも二つは指摘できるべきでしょう。もし五つすべてを指摘できないなら、この記
事の続きを読んでください。あなたのためものがあります。


Rather than generalities and pontifications, we decided to use what we call anti-patterns : (unfortunately)
common bad programming practices that we have seen time and again in Java code. Our purpose is to familiarize
you with these counter-examples so that you can quickly spot them, and avoid or remediate them.

わたしたちは generalities や pontifications をするのではなく、わたしたちがアンチパターンと呼ぶ、Java code で
よく見かける (残念なことに) 一般的な bad programming practices を使うことにしました。わたしたちの目的はこのよ
うな counter-examples にあなたを familiarize させることであなたがそういったものを即座に指摘できるようにし排除
したり正したりできるようにするというものです。

And now for our hall of shame – the six most common misuses and abuses of exception handling.


exception handling について
最も一般的な六つの misuses と abuses 


Anti-pattern #1 : try-catch-bury
アンチパターン 1 : 

  catch(Exception ex)  {

    ex.printStackTrace();


This is the bane of Java programming – catching an exception and not doing anything about it. In terms of
frequency and severity, this is probably comparable to the infamous unchecked buffer problem in C and C++. If
you see this anti-pattern, you can be 99% sure that it is wrong (there are a few cases where it might make
sense, but they should be carefully commented to make it clear to the maintenance developer).

これは the bane of Java programming (Java プログラミングの破滅?) です。例外を捕捉するけれどもそれに対する
処理を一切行わない。頻度と重大度から言うとこれは、C や C++ において悪名高いチェックなしバッファー問題
(unchecked buffer problem) に匹敵するものでしょう。もしあなたがこのアンチパターンを見たのなら、99% それが
間違いであると確信できるでしょう (このようにすることに意味があるケースが、数は少ないものの存在しています。
しかしその場合でも maintenace developer に対してその意図を明確にするために注意深くコメントを残しておくべ
きです)。


This is wrong because an exception (almost) always means that something bad (or at least unexpected) has
happened. Yet we choose to ignore and silence that cry for help. Calling printStackTrace does not qualify as
“handling an exception” – it’s OK for debugging but should not be present past that initial step.

これが間違いなのは、例外というのものは (ほぼ) 常に何かがおかしい (少なくとも期待したものではない) ことが起き
たことを意味しているからです。わたしたちはそれでも例外を無視することを選択し、cry for help を黙殺しました。
printStackTrace の呼び出しは “handling an exception”として qualify されません。
デバッグのために printStackTrace を使うことはかまいませんが、present past that initial step すべきではありま
せん。


This problem is frighteningly pervasive. If you look at the documentation for the JDK class ThreadDeath, you
will see the following comment : "The class ThreadDeath is specifically a subclass of Error rather than
Exception, even though it is a "normal occurrence", because many applications catch all occurrences
of Exception and then discard the exception." This means that this poor programming practice is so common
that, in an unhealthy feedback loop, it has affected the design of Java itself. Grunt.

この問題は frighteningly pervasive です。JDK の class ThreadDeath のドキュメントを見ると次のようなコメントが
あります。"The class ThreadDeath is specifically a subclass of Error rather than Exception, even though it
is a " normal occurrence", because many applications catch all occurrences of Exception and then
discard the exception." (ThreadDeath クラスは、それが "normal occurence" であっても specifically には
Exception のサブクラスではなく Error のサブクラスとなっています。それは多くのアプリケーションで、発生した例外
すべてを捕捉してもその例外を捨ててしまっているからです) このことはこの poor programming practice が Java 自身
の設計に影響されていて unhealthy な feedback loop の中であまりにも一般的 (so common) であることを意味していま
す。


What should you do instead ? You basically have four options :
代わりにすべきことは何でしょうか? 基本的には四つの選択肢があります。


 1.  Handle the exception : do something about it. Correct the problem, notify someone or something, whatever
     makes sense in this particular situation. Once again, calling printStackTrace does not qualify as
     “handling the exception”.

     その例外を処理する: 例外に関する何かを行います。問題を修正する。誰か(もしくなにか) に notify する。特定の
     シチュエーションで意味のあることを行う、もう一度繰り返しますが、printStackTrace の呼び出しは“handling
     the exception”として qualify しません。

 2.  Re-throw the exception. This is not uncommon if your exception handling code examines the exception for
     additional information, and decides that it cannot handle it after all.

     その例外を再送出する: あなたの例外処理コードが additional information のためにその例外の検査をしていて、
     その結果その例外を handle できないと判断したのであればそれは uncommon ではありません。

 3.   Translate the exception into another exception. Most often this is used to translate a low-level
      exception into an application-level exception.

      その例外を別の例外に translate する: ほとんどの場合これは low-level な例外を application-level の例外へ
      translate するのに使われます。

 4.   Don't catch the exception – if you're not going to do anything about it, why bother catching it? Let it
      go (and, if necessary, declare it in the signature of your method).

      例外を捕捉しない: もしなにもするつもりがないのならなぜその例外を捕捉したのでしょうか?
      Let it go (and, if necessary, declare it in the signature of your method).
      なすがままに (そしてもし必要なら、捕捉する例外をメソッドのsignatrue で宣言する)


Solution 1 : if you catch an exception, do something about it. Do not bury it.
解決策1:  例外を捕捉したら、それに対する何らかの処理を行うこと。握りつぶしてはいけません。

Anti-pattern #2 : Pokémon® – Gotta catch’em all
アンチパターンその2:

  catch(Exception ex)

It is often tempting to have a very general catch statement. The most common is undoubtedly catch(Exception ex).
In almost all cases, that is a bad idea. Why?

very general な catch statement を頻繁に作ろうとしてしまうこと。最も一般的なのはまず間違いなく
catch(Exception ex) ですが、ほとんど全てのケースでこれは bad idea です。なぜでしょうか?


To understand why, we need to step back and consider the purpose of a catch statement. You use a catch
statement to indicate that you anticipate certain exceptions, and that you are willing to handle them. The
class of the exception(s) is how you tell the Java compiler which exceptions you want to handle. Since the
vast majority of exceptions inherit directly or indirectly from java.lang.Exception, specifying that in your
catch statement effectively says that you want to handle almost any exception.

それがなぜなのかを理解するには、 step back して catch 文の目的を考察する必要があります。catch 文は特定の
exceptions を anticipate しているのを indicate して、それを handle する意志があるということを示すために使いま
す。例外のクラスは、あなたが handle したいと望んでいる例外をJava コンパイラーに指示するものです。例外の vast
majority は直接間接に java.langa.Exception を継承したものですから、あなたがcatch 文で specifying したのはあな
たがほぼすべての例外 (almost any exception) を handle したいということだと効果的に述べています。


Let's look at the code sample again. What kind of exceptions are we likely to catch - The most obvious one
is of course SQLException, quite likely to happen any time you deal with JDBC.  IOException is another
possibility – we are dealing with a stream writer. You can already see the problem : it does not make sense to
handle these two (very different) types of error in the same catch block. It would make a lot more sense to
have two catch blocks, one for SQLException, one for IOException.

ではもう一度サンプルコードを見てみましょう。例外の種類はわたしたちが catch しようとしているものです。もっとも
明白なのはもちろん SQLException で、これは JDBC を扱うときにはいつでも発生しうるものです。IOException はもう
ひとつの候補ですが、ここでは stream writer を取りあげましょう。あなたはすでに問題を理解しています。これら二つ
の (非常に異なった) 型のエラーをひとつの catch block で handle することには意味がありません。SQLExcetption の
ためのものと IOExceptiono のためのものの二つの catch ブロックを持つことのほうがずっと意味のあるやり方です。


In addition, there is a large number of other exceptions that could occur. What if, for some obscure reason,
executeQuery returns null ― You'll get a NullPointerException in the next line, yet that (unexpected)
exception will be ignored (unless you happen to be looking at the console for your program – and even then,
unless you wrote that code yourself, what good does that do you ?).

加えて、発生する可能性のある数多くの other exceptions があります。いくつかの奇妙な理由によって executeQuery が
null を返したとすると、次の行で NullPointerException が発生します。そしてこれはこれは無視することのできない(し
かも予期していなかった)例外です。
(unless you happen to be looking at the console for your program
– and even then, unless you wrote that code yourself, what good does that do you ?).


The better approach is to be more specific. In this case, we should have two catch blocks, one for
SQLException, the other for IOException. For one thing, this makes it clear to the next reader of this code
that you have thought about these scenarios. But what about all the other exceptions, you ask - Let them go.
Do not handle them (unless you have a reason to). You cannot (and in fact should not) try to handle all
possible exceptions – let them bubble up, someone else will deal with them (the JVM if no one else).

もっと良いアプローチはより specific にすることです。このケースでは、SQLException のためのものとそのほかの
IOException のためのものという、ふたつの catch ブロックを持つべきなのです。
For one thing,
これはそのコードの次の読者のために、あなたがそのコードでthese secanios で考えていたことを明確にします
しかしそのほかすべての例外に対しては (理由がない限りは) それらを handle してはいけません。放置しましょう。
あなたは可能性のある例外をすべて handle することを試みることはできません(し、すべきではありません)。
– let them bubble up, someone else will deal with them (the JVM if no one else).


There are some instances where catching Exception is a good idea especially when doing testing or debugging.
Once you have isolated the cause of the problem you need to remove the catch Exception and replace it with the
appropriate kind of Exception(s).

とくにテストやデバッグをしているときには、例外の catch が good idea であるようないくつかのインスタンスが存在
しています。問題の原因を insolate できたら、その catch Exception を取り除いて適切な種類の例外で置き換える必
要があります。


Solution 2 : Be as specific as possible in your catch statements, and use multiple catch statements if
necessary. Do not try to handle all possible exceptions.

解決策その2
自分の catch statemens は可能な限り specific にする。そして必要であれば multiple catch statements を使う。
可能性のある例外すべてを handle しようとはしない。


Anti-pattern #3 : The forgotten bathroom key
アンチパターンその3


  try {
      Statement stat = conn.createStatement();
      ResultSet rs = stat.executeQuery("select uid, name from user");
      while (rs.next())
      {
           out.println("User ID : " + rs.getString("uid") +
               ", name : " + rs.getString("name"));
      }
      conn.close();


One of us used to work in a small office with only one bathroom. To go there, you had to use a key, which was
hung on a nail. One programmer was notorious for often neglecting to return the key to its rightful place,
thereby inconveniencing the rest of the office. Often, this was because he would get interrupted while coming
back to his desk, and he would forget to return the valuable resource to its place.

わたしたちの一人は bathroom が一つしかない small office で働いていました。そこへ行くためには爪の大きさほどの
鍵を使わなければなりませんでした (違うか)。
あるプログラマーはこの鍵を正しい場所に戻すのをしばしば忘れてしまっていて、そのせいで
オフィスの他の人たちに不便を強いていました。
彼は自分の机に戻っている最中にも割り込みを受けることがあり、正しい場所にこの valuable resource を戻すことを忘
れてしまうのでそのような事態が頻繁に起きていました。


Similarly, when an exception occurs, it affects the execution path of your program. It is easy to verlook that
simple fact. If you use resources such as files, sockets, JDBC connections, etc…, you need to make sure that
they are properly closed and released even if an exception occurs. Java has a mechanism designed just for such
a thing : finally.

これと同様に、例外は発生したときにあなたのプログラムの実行パスに影響を及ぼします。そんな単純な事実を overlook
してしまうのは容易なことです。ファイル、ソケット、JDBC connections, etc…, のようなリソースを使ったのなら、例
外が発生した場合であってもそれらを確実にクローズしたりリリースしなければなりません。Java にはそのために設計さ
れた仕組みがあります。それが finallyです。


Finally is a wonderful thing : it allows you to guarantee that your cleanup code will be executed before the
end of the try/catch/finally block, regardless of whether an exception is being thrown or not. Think of it as a
knot on your finger, which will remind you to return the bathroom key, even if something distracts you. And yet,
finally is rarely used, even by intermediate programmers.

finally は wonderful thing です。例外が throwされたかどうかには関係なく、try/catch/finally ブロックの終端の直前
で claenup code が実行されるのを保証するのを可能にします。
あなたが何かに気をとられてしまっていても bathroom の鍵を返すのを思い出させる指先の結び目を考えてみてください。
And yet, intermediate programmers によってさえ finally はめったに使われません。


Of course, finally blocks should be written with great care. In particular, you should be careful about
exceptions being thrown in a finally block – this is your final chance to clean things up, don’t let it slip.
In some cases, it may be acceptable to bury an exception that is thrown in a finally block. Think of it as a
best effort. Regardless, use your best judgment, or better yet, ask someone more experienced.

もちろん finally ブロックは大いに注意を払って記述されるべきものです。とくに、finally block で throw される
exception については注意深くあるべきです。
そのような場面はなにかを片付ける最後のチャンスなのですから don't let it slip。
一部のケースでは finally block で throw される exception は bury してしまうのが acceptable かもしれません。
これは best effort とみなされます。
あなたが best judgment しているか better yet なのかには関係なく、もっと経験をつんでいる人に尋ねてみましょう。



Solution 3 : Make sure that all resources are properly released. Use finally liberally.
解決策その3 すべてのリソースを確実に適切に解放する。finally を liberally に使う。


Anti-pattern #4 : If you don't know why I am mad, I won't tell you
アンチパターンその4


  try {
      Statement stat = conn.createStatement();
      ResultSet rs = stat.executeQuery(

      "select uid, name from user");
      while (rs.next())
      {
          out.println("User ID : " + rs.getString("uid") +
            ", name : " + rs.getString("name"));
      }
      conn.close();
      out.close();

  }
  catch(Exception ex) {
      ex.printStackTrace();


Look at the code again : what happens if an exception occurs during the execution of the loop ― Will we get
information which can tell us what causes the loop to fail? Not really. All we will get is an indicator of
something wrong in the area of the class that is doing the processing, but may not get any input as to what
caused the problem within this loop.

コードをもう一度良く見てください。ループを実行中に例外が発生したときになにが起きているでしょうか? ループを失
敗させた原因を区別できるような情報を得られるでしょうか? Not really. わたしたちが手に入れられるものは、処理を
行っていたクラスの領域で何か間違ったことが起きたという indicator がすべてです。そして、ループの中で問題を引
き起こした原因となった入力については一切手に入れられません。


The basic “Stack trace” which shows the path of execution to the class that caused the exception is cryptic,
and not easily parsed.  It also causes any tester without a Java development background to report application
problems with a very general description such as “encountered an ugly Java problem”. If such an exception is
wrapped to display a more user-friendly message they are more likely to repeat the specific message displayed
to them.  Not everyone who tests business applications is experienced in the delicate art of stack trace
interpretation.

exception を引き起こしたクラスの実行パスを show した基本的な“Stack trace”は cryptic で、解析も容易ではありま
せん。Java の development の background を持たない tester すべてに、アプリケーションの問題で
“encountered an ugly Java problem” のような very general な report をさせてしまいます。
もしそういった例外が more user-friendly なメッセージで wrap されていれば、
tester たちは表示された specific message を repeat するでしょう。
ビジネスアプリケーションのテストをする人が皆、stack trace の解釈 interpretation という delicate art の
経験豊富というわけではないのです。


In addition to displaying a more user friendly message, there is great benefit in providing a little extra
data such as the Class, Method, and a text message. While it is true this information can be obtained from
the stack trace, it is much easier to read when it is isolated. Also, taking the extra time to describe the
behavior when you are creating the code will greatly expedite resolving the problem later.

よりユーザーフレンドリーなメッセージを表示することに加えて、クラスやメソッド、テキストメッセージのような
little extra data を provide することには大きな利益があります。
そういった情報がスタックトレースから得られはしますが、isolate されたことでより読みやすいものになるのです。
あなたがコードを書くときに behavior を describe するのに余計な時間をかけることで、
あとで問題を解決するときに greatly expedite するのです。


One solution is to embed a snippet like the one below wherever exceptions get logged in the application.
You can use the this.getClass().getName() method, and to insert the method named and a text message
everytime the program reports a checked exception.  This practice makes exceptions easy to read and
easy to parse.

解決策の一つは、例外が発生したときにアプリケーションのどこで起きたのかを記録する snipet を埋め込むというものです。
プログラムがchecked exception を report する度にメソッド名とテキストメッセージを埋め込むのに
this.getClass().getName() method が使えます。この practice は例外処理を読んだり解析するのを簡単にします。


  this.getClass().getName(), “mymethod”, “some message”


One caveat to this approach is that with a static method call you need to manually need to insert the class
name because the “this” object reference does not have a this to refer to. Simply replace the
this.getClass().getName() with your class name “myClass”.

このアプローチの one caveat は static method call を伴う場合にはクラス名を自分で挿入する必要があることです。
それは、"this" オブジェクトの reference がオブジェクトへの参照である this を持っていないためです。
this.getClass().getName() を単純に自分のクラス名“myClass”で置き換えます。


Solution 4 : report a reasonable amount of data in a way that is easy to read
解決策その4 読みやすい方法で適切な量のデータをレポートする



Anti-pattern #5 : overzealous try
アンチパターンその5 熱心すぎる try


  try {
      Statement stat = conn.createStatement();
      ResultSet rs = stat.executeQuery(

      "select uid, name from user");

      while (rs.next())
      {
          out.println("User ID : " + rs.getString("uid") +
            ", name : " + rs.getString("name"));
      }
      conn.close();
      out.close();


Putting too much activity in a single try block is a bad programming practice, even though it is common. The
reason it is a common practice is that it takes extra time to isolate what in a particular block could go
wrong and what exceptions could get created as a result of this processing. Wrapping too many statements in a
giant catch is like packing your household goods for a move using refrigerator-sized boxes.  Sure, all your
goods are in one place but imagine the sorting task you will have in the near future.  For the inexperienced
developer it is easier to put a bunch of statements in a try block, and wrap it all up in a generic catch
Exception than to isolate the statements. This practice makes troubleshooting Exceptions that get generated
during program execution that much more difficult because there are more variations to check to find out
what caused the Exception.

ひとつの try ブロックに多すぎる activity を押し込めることは、それが一般的に行われていることであっても bad な
プログラミング practice です。これが一般的な practice である理由は、go wrong する可能性のある特定のブロックと
その処理の結果として生成される可能性がある例外とを isolate するのには extra time を take するためです。多すぎ
る statements を巨大な catch で wrapすることは、引っ越しするのに冷蔵庫大の箱を使って household goods をパッキ
ングすることに似ています。確かにあなたの goods はすべて一つの場所にありますが、近い将来に行うことになるであろ
う sorting task を想像してみてください。あまり経験をつんでいない developer のために、try block に bunch of
statements を put してそれをまるごと isolate the statements するよりも generic catch Exception で wrapする
方がより簡単になっています。この practice は、ずっと困難なプログラム実行中に生成された Exception を解決します。
それはその Exception を引き起こしたのが何かを見つけ出すための検査にはもっと多くの variations があるからです。


For lack of space, the code example does not really illustrate this fully, but this is a common problem. 

スペースが足りないので例に挙げたコードはこのことを完全には表現していませんが、これは一般的な問題です。

Solution 5 : keep try blocks as small as possible, but no smaller
解決策その5 try ブロックを可能な限り小さく、ただし小さすぎないようにする。


Anti-pattern #6 : incomplete execution
アンチパターンその6
不完全な実行
 

  while (rs.next())
  {
    out.println("User ID : " + rs.getString("uid") +
      ", name : " + rs.getString("name"));
  }


This is the silent killer of Java systems.  Look at the code again, and imagine what happens if an exception
is thrown in the middle of the loop. The execution of the loop will be interrupted, the catch block will be
executed, and that's about it. But what about the data that we are writing out? It will be silently incomplete.
Whoever or whatever is supposed to use this data will receive incomplete (and hence incorrect) data, but will
probably have no idea that it is incomplete. For some systems, that is a problem far more serious than any
crash.

これは Java システムの silent killer です。コードをもう一度よーく見て、そしてループの途中で例外が送出されたと
きに何が起きるのかを想像してください。その例外は interrupt され、例外に対応する catch ブロックが実行されます。
しかし、わたしたちが書き出したデータはどうなるでしょうか? それは silently に incomplete なものになってしまう
でしょう。このデータを誰が使うと仮定したとしても incomplete な (したがって incorrect な) データを受けとるで
しょうが、それが不完全なものであるかどうかはおそらくわかりません。一部のシステムではこれはクラッシュするより
ももっと深刻な問題となります


A better approach here would be to attempt to write a message to the output, signaling that the data could not
be completely written. Another possibility would be to buffer the output (if possible) and write it out only
once we have it all ready to go.

ここでのより良いアプローチは、メッセージを出力に書き出すことを attempt してデータが完全には書き出せなかったこ
とを signaling することでしょう。もうひとつの possibility は、(可能であれば)出力をバッファリングしてすべての
準備が完了したときにそれを一度だけ書き出すというものです。


Solution 6 : consider all likely exceptions and how they will affect the flow of execution
解決策その6 すべての likely exceptions を考慮し、それがどのように実行の流れに影響するかを考えてください。

 
Example (re-written)
書き直した例

Given these facts, let's see now how the same code would look like. Note that it is quite a bit more verbose.
That is not a bad thing – good code always includes a lot of error handling.

以上のことを踏まえて、コードがどのようになるのか見てみましょう。
it is quite a bit more verbose であることに注意してください。
それは悪いことではありません。優れたコードは常に多くのエラーハンドリングを含んでいるのです。


  OutputStreamWriter out = ...
  java.sql.Connection conn = ...
  try {
      Statement stat = conn.createStatement();
       ResultSet rs = stat.executeQuery(
             "select uid, name from user");
       while (rs.next())
       {
           out.println("User ID : " + rs.getString("uid") +
             ", name : " + rs.getString("name"));
       }

  }
  catch(SQLException sqlex)
  {
      out.println("Warning : data incomplete due to exception");
      throw new ApplicationException(
            "SQL error while reading", sqlex);
  }
  catch(IOException ioex)
  {
      throw new ApplicationException(
              "I/O error while writing", ioex);
  }
  finally
  {
      if (conn != null)
          try {
              conn.close();
          }
          catch(SQLException sqlex2)
          {
              System.err(this.getClass().getName() +
                ".mymethod - cannot close JDBC connection : " +
              sqlex.toString());
          }

      if (out != null)
          try {
               out.close();
          }
          catch(IOException ioex2)
          {
              System.err(this.getClass().getName() +
                 ".mymethod - cannot close outfile" +
                ioex2.toString());
          }
   }


Conclusion 結論

All the anti-patterns in this article were inspired by actual code, written by professional programmers.
Before you snicker, ask yourself whether your code is really free from these poor practices. Even the most
experienced programmers sometimes fall back into them, simply because they are easy (we certainly do). Think
of them as bad habits – they are notoriously difficult to shake off, but just trying makes you a better person.

本 article で取りあげたアンチパターンはすべて、プロのプログラマーが書いた実際のコードに inspire されたものです。
Before you snicker、 自分のコードが本当にこれら poor practices のようなものではないか自身に問うてみてく
ださい。経験豊富なプログラマーの大部分でさえ fall back into them してしまうことがありますが、なぜならそれは、
アンチパターンとはそうなりがちなもの (やってしまいがちなもの) であるからです。そういった習慣は、悪い習慣 (bad
habits) だと考えてください。それは shake off するのが notoriously difficult なものでありますが、
(shake off に) try するだけでもあなたを better person にするでしょう。


Of course, nothing in this article should be taken as gospel. Use your common sense and your experience. For
each anti-pattern described here, you could certainly come up with counter-examples. As long as the rules are
broken willingly and thoughtfully, you have ourblessing, but we do beg for one favor : if what you do is not
obvious, please write a nice comment. You'll thank yourself later. Also, share the your wealth of knowledge
with others on your team; extra time spent on training is a small price to pay in comparison to a massive
refactoring effort at the end of the development cycle.

もちろんこの article には gospel として受け取るべきものはありません。あなたの常識 common sense と経験 experience
を使ってください。ここで説明したアンチパターンのそれぞれについて、counter-example をいくつか提示できるでしょう。
ルールが willingly かつ thoughtfully に破られている限りは
あなたには our blessing がありますが、わたしたちは one favor を求めます。
もしあなたのしていることが明確でないのなら、どうか nice なコメントを書いてください。
あとで自分自身に感謝することになるでしょう。
また、the your wealth of knowledge をあなたのいるチームの他のメンバーと共有してください。
トレーニングのために必要な extra time は
a massive refactoring effort at the end of the development cycle
に必要な費用と比較すれば小さなものです。


References 参照

Practical Java: Programming Language Guide – Peter Haggar - ISBN: 0201616467. An invaluable resource, a must-read for any Java programmer.

The Elements of Java Style - Scott W. Ambler  Alan Vermeulen  Greg Bumgardner - ISBN: 0521777682. A collection of good coding practices, all neatly grouped in a small booklet. You may not agree with it all, but if you have a team, you need to either adopt this book, or write your own. Adopting this one (perhaps with amendments) is a lot easier.

The Sun Java online tutorial : http://java.sun.com/docs/books/tutorial/essential/exceptions Does a good job of introducing the basic concepts, but does not go beyond that.

Effective Java: Programming Language Guide – Josh Bloch - ISBN: 020131005-8. Another excellent reference that is easy to read.


About the authors
著者について

We'd love to hear from you ! Please don't hesitate to send your comments, suggestions 
and criticisms to either of us.

Craig Dewalt is a surfer who likes to lead Java development teams.  He can be reached 
at goflyr@yahoo.com. Max Tardiveau is a solution architect for Versata. He can be 
reached at max@tardiveau.com.

■_

■_

いいなあこれ。 アルゴリズムとデータ構造についてOSSから勉強する会 1回目 - connpass


一つ前へ 2013年12月(下旬)
一つ後へ 2014年11月(中旬)

ホームへ


リンクはご自由にどうぞ

メールの宛先はこちらkbk AT kt DOT rim DOT or DOT jp