BOX@Eelこの広告は、90日以上更新していないブログに表示しています。シェルスクリプト「JavaScript文字列リテラル用のエスケープ」という表現は微妙だけど、要はサーバサイドでJavaScriptを動的生成する時に、文字列リテラルとして任意のパラメータを出力したい場合のエスケープ処理。先日(というか先月)書いたHTMLエスケープ用のシェルスクリプトは、通常のHTMLエスケープ用だ。HTMLの文法にて特別扱いされる最小限の文字をエスケープするので、HTML要素の内容(Content)ないし属性値として使用する文字列に対して適用するのが正しい。eel3.hatenablog.comサーバサイドではJavaScriptを動的生成することも時々ある。JavaScriptの文字列リテラルとして任意のパラメータを出力するスタイルだ。このケースでのエスケープは一般的なHTMLエスケープとは異なる。出力したJavaScriptの文字列リテラルをJavaScriptコード中で以下のプロパティ/メソッドに適用していて、かつHTML要素として解釈されたくない場合は、HTMLエスケープする。HTMLDocument.write()HTMLDocument.writeln()HTMLElement.innerHTMLJavaScriptの文字列リテラルとして許容される内容にエスケープする。「\」を「\\」に置換する。「'」を「\'」に置換する。「"」を「\"」に置換する。制御文字をエスケープシーケンスに置換する(例えば改行を「\n」に置換する等)追加の処理。JavaScriptのコードの出力先が何らかのタグの属性値の部分であるなら、属性値全体をHTMLエスケープする。JavaScriptのコードの出力先がscriptタグの中であるなら、「</script>」を含まないようにする。JavaScriptのコードの出力先がCDATAの中であるなら、「]]>」を含まないようにする。JavaScriptの文字列リテラルの範囲内で「</script>」や「]]>」と等価な別の表現にすればよい。Unicodeエスケープシーケンスに置き換えるのだ。変換元テキストがUTF-8であるという前提で、試しにシェルスクリプトでエスケープ処理を実装してみた。escape-jsstrという名前だ。'\n'面倒なので全てUnicodeエスケープシーケンスに変換している。hexdump(1)を使用できる環境なら、もう少し簡単に実現できる。"%02X"'とはいえ、いつもhexdump(1)を使えるとは限らない。LinuxやmacOS、FreeBSDなどを使う分には困らないが、Cygwinでは標準では含まれない(別途util-linuxを入れる必要がある)。商用UNIXは触ったことがないが、やはり怪しいようだ。echo(1)ライクに引数の文字列をエスケープするシェルスクリプトはこんな感じ。escape-jsstrHTMLエスケープネタと同様にとりあえず作ってみたけど、需要あるのかなあ?終わりに最終的には、こんな感じになった。シェルスクリプトPHPやPerlでのHTMLエスケープの話はよく目にするけど、そういえばシェルスクリプトでは見かけないなあ、なんて思った次第でございます。動的Webコンテンツの先駆けであるCGIの普及期でさえ言語としてPerlが大々的に使われていたわけで、そもそもサーバサイドの言語としてシェルスクリプトが使われる機会は圧倒的に少ない。なればシェルスクリプトでのHTMLエスケープネタが見つからないのも当たり前というもの。無いとかえって作りたくなるもので、変換元テキストがUTF-8であるという前提で、試しにシェルスクリプトで最小限のHTMLエスケープを実装してみることにした。HTMLエスケープ処理の本体。escape-htmlという名前だ。${@+"$@"}標準入力ないし引数指定したファイルに対して最小限のHTMLエスケープを行い、標準出力に書き出す。この出力結果は、HTML要素の内容(Content)ないし属性値としてのみ使用できる(ただし属性値として使用する場合は前後をクォート文字で囲むこと)。末尾の改行を付加しないスタイルになることが多いと思う。作ってみたけど、果たして需要はあるのだろうか?終わりに最終的には、こんな感じになった。Updateが原因でPCガー」的な場面に遭遇したのは初めてである。2521が2台転がっていて、実験用に使おうとしたのだ。Ver.1803が入っている。Updateが未適用の状態だった。ATTEMPT)になってしまう状態に陥った。2521本体のタッチパッドで操作しようとするとブルースクリーンになることが分かった。試しにUSBマウスを使うようにしたら、ブルースクリーンを回避できた。Update前には普通に使えていた。Updateをかけたか否か」だけ。Updateが疑わしく見えるシチュエーションに遭遇すると、一周回って感心してしまうものだ。ブルースクリーンについては、遅れてKB4346084(今月再リリースされた版)が自動適用されたら、発生しなくなった。KB4346084は「Intel製CPUのマイクロコード更新する」という少々特殊なパッチなのだが......適用順でブルースクリーンなる、という情報は見つけられていない。Ver.11プログラミング2019-06-30現在のステータス。1年経て、こうなっている。CSS、HTML、XMLはひとまず除外する。人工言語ではあるけれども「プログラミング言語」という括りに含められるか否かは議論が分かれる気がする。(Gawk)単純なテキストレコードの処理はAWKで十分間に合う。awk単体で実装するのは苦行すぎて*2皆無なものの、シェルスクリプトやMakefileにAWKのコードを埋め込むなどして他のコマンドと組み合わせて使う機会は依然として多い。シェル上でワンライナーでテキスト処理する時にも重宝している。これはこれで十分AWKらしい使い方ではないだろうか?C++ちょくちょくお仕事で使うが、本職のC++使いではない。Cでも使う価値がある。C言語使いからすると、C++03時代よりも充実度が進んだ標準ライブラリ・ラムダ式・autoによる型推論など、便利で羨ましい限りだ*3。あと、Swift時代のクロスプラットフォームC++ライブラリ作者は、どうあがいてもARCから逃れられないので、C++11以降のスマートポインタは必須だ*4。正規表現とスレッドも標準ライブラリに加わったので、あとはソケット(低水準ネットワークAPI)をサポートしてくれないだろうか。低水準の処理を行いつつも便利な機能で実装時間を短縮できる点は便利で、少なくともシステムプログラム言語としての利点だと思う。機能多すぎ/複雑すぎなところはなんとかならないものか。強力な反面、使い手を選ぶ言語だ。C言語お仕事での主力言語。シンプルかつ低水準の世界が垣間見れるところが割と好き。いえ最近の他の言語と比較すると、シンプルすぎて安全機構が欠けていたり標準の便利機能が少なかったりするので、入門用の言語としては薦められない。かかわらず、プログラミング未経験者向けのC言語の本は毎年出版されている――謎だ。クロスプラットフォームなモジュール屋としては、今までC89を採用してきたものの、いい加減そろそろC99とかC11とか次世代の言語とか使いたい。Studioもサポートしたいから、C99すら2023年~2024年ぐらいまで使えない。DOSバッチファイルプログラミング言語に含まれるかどうか不明だが、含めてしまう。した自動化や、複数ツールを組み合わせて使うときのラッパーとしてよく使う。コマンドプロンプトはシバン(shebang)に対応していないので、スクリプト言語で書いたツールを起動するラッパーとしても多用している。意外と色々なコマンドが用意されているので、単純にそれらを叩く分には十分だが――言語機能がショボいので、バッチファイルでifやforのような制御構文系コマンドが必要になってきたら、何かを決定的に間違えているのではないかと考え直すようにしている。2017直後の過渡期なので、JavaよりもKotlinでの経験値の方が多い。モダンな「強い静的型付け」の、割とええ感じの言語やね。3をつまみ食いして半年以上経ってからKotlinをつまみ食いしたこともあり、未だに両者の概念・機能が頭の中でごった煮になっている。7/8・Kotlinを行ったり来たり。Swiftもそうだが、「強い静的型付け」の言語は「開発環境込み」で高い生産性とコードの安全性を両立させる方向に進んでいる気がする。Makeはそこそこプログラミング言語的か。Guileなところが。Make(pmake)を使うが、いずれも独自拡張アリアリだ。Pythonではlazyなスタイルでのコーディングが許されず、整然とコードを記述する必要がある。5やRubyとは随分と雰囲気が異なる。気になるのは、インデントが必須な言語仕様であるために、シェルスクリプトに埋め込んで使うのが苦痛な点だ。Pythonだけでコードを書く分には気にならないのだけど。sedプログラミング言語に含まれるかどうか不明だが、DSL扱いで*5。シェルスクリプトやMakefileにて他のコマンドと組み合わせて使う。いうか正規表現でのテキスト置換以外の機能を使った記憶が......あったな、dとiとpと=とブレースによるグループ化ぐらいだが。私のレベルではsedでFizzBuzzを書けないので、sedで難しい処理を記述しないようにしている。10でデフォルトで利用できるv5.1に留まったままである。Frameworkを叩けてダイナミックスコープでスクリプトブロック(という名の無名関数)と、無茶でピーキーで完全にプログラマ向けな代物だ。Microsoftもよくもこんなエライ代物を出したものだ。残念なことに、コマンドプロンプトの代替という観点では、外部ツールとの親和性が微妙にイマイチだ(特に文字コードとか)。Serverの管理スクリプトを書くためのスクリプト言語」扱いしている。アクション』級の最新バージョン対応の言語解説書が出版されてくれないだろうか。(/bin/sh)プログラミング言語に含まれるかどうか不明だが......いや、私的にはシェルスクリプトは立派なプログラミング言語だ。基本的な用途は、バッチファイルと同じくちょっとした自動化や複数コマンドを組み合わせて使うときのラッパーだが、実現できる内容は遥かに多い。言語本体(?)がバッチファイルよりも高機能だし、Unixユーザランドはコマンドが充実している。Linux)で環境構築すべきだろう。Cygwinでは、主要な処理をシェルスクリプトで記述しておき、bashからはシェルスクリプトを利用し、コマンドプロンプトではラッパーのバッチファイル経由でシェルスクリプトを叩く使い方をしている。Windows上では処理速度が妙に遅くなる点が不満だ。Pascal初心者(ただし他言語の経験者)向けの良い資料が少なくて難儀している。HANDBOOK―マルチデバイス開発ツールDelphiのためのプログラミング言語完全ガイド』を買ってしまおうかしら。Java生まれて初めて触れたプログラミング言語その2。実のところ、職業プログラマとして本格的に使用することは一生ないと思っていた。Androidアプリ開発も、Kotlin採用後に本腰入れて関わるようになったので、Kotlinメインだ。ぬるい感じに時々Javaのコードを触っている。APIが使えないと身体が拒否反応を示す。少なくとも、構文の見た目こそ保守的なオブジェクト指向プログラミングをしているC++に似ているけど、中身はC++とは似ても似つかない代物だということは体感している。Objective-C++時代はSwiftだと言われているけど、どっこいObjective-CとObjective-C++は生きている。いうかSwiftのコードにC++で書かれたライブラリを直接組み込むことができない以上、両者を繋げるグルー言語として生き残ることになるよね。最近流行の言語と比べると良くも悪くも80年代的だが、アプリケーションプログラミング用としてはC言語よりマシだし、C++ほど複雑怪奇*6ではない。C言語やC++で書かれた既存のライブラリをそのまま使える。Objective-Cのハイブリッドな所は好きだが、Objective-C++はハイブリッドすぎて微妙。C++のクラスとObjective-Cのクラスを、C++のラムダ式とObjective-Cのブロック構文を同時に使うのは大変だ。便利ではあるんだけどね。5時々、やむをえない事情で触ることがある。基本的によく分からない。何というか、あの記号の羅列っぽさに中々慣れないというか、自分は余りに自由度が高すぎる言語は苦手だと気づいたというか。(言語仕様に慣れているなら)半ば使い捨てなテキストフィルタとかをさっと書くには、悪くない言語だと思うのだが。QML宣伝文句のとおり、QMLはGUIの記述に非常に向いている。それも、単に標準のUI部品(エレメント)を使うだけでなく、少し改造して使うとか、オリジナルのUI部品を作って使うとか、それらを別のアプリケーションに使いまわすとか、そういう時に威力を発揮する。あと、プロパティバインディングやレイアウトのアンカー指定など、画面サイズの変更に追随するUIを作りやすい機能も揃っている。JavaScriptでちょっとした処理も記述できる――とはいえ、やりすぎるとパフォーマンスの罠が......。少なくとも、JavaScriptでゴリゴリコードを書くのはQML的ではない。QMLは宣言的に、シンプルに書くものだ。力技でロジックでゴリ押しすると、色々と罠に嵌る言語だ。Ruby自作ツール実装にて、AWKの代替言語の最有力候補だった(でも最近はPythonが多いんだな、これが)。テキスト処理でも割と重宝するが、バイナリデータへの変換が絡んでくるとAWKよりもRubyを使った方が効果的だ*7。irbを電卓代わりに使うスタイルも板に付いてきた気がする。to_s(16)やto_s(2)で基数変換して表示できるところが好き。SQL生まれて初めて触れたプログラミング言語その3ぐらいに位置する。組み込みの人なのでSQLとは無縁だと思っていたが、まさかTransact-SQLを少しだけ触ることになるとは。Swift「コンパイラによる強力な型推論と型安全性のチェック」がお仕事用のメジャーな言語にまで降りてきたという点で、Swiftは静的型付け言語界のJavaScript*8だと思っている。ユーザ数的には、Kotlinが「静的型付け言語界のJavaScript」ポジションなのかもしれない。互換性のない言語仕様の変更が発生し難くなってきた感じかなあ。2003で書かれたコードを時々メンテ中。2013移行したけど。最近使ってないが、縁は切れてないbash最近はデフォルトシェルがbashな環境も多いので、自分用のツールぐらいは素の/bin/shではなくbashで書いても大丈夫な気がしてきた。shよりbashの方が遥かに便利だからなあ――PerlやRuby等には負けるけど。bashでスクリプトを書くときの唯一の欠点は、メジャーバージョンごとの差異や各ディストリでのビルドオプションの違いにより、同じbashという名前でも実は千差万別なところだと思う。PerlやRubyのバージョンは気にするけど、これがシェルになると意外とバージョンに無頓着になってしまう。(yacc)プログラミング言語に含まれるかどうか不明だが、DSL扱いで。構文解析系統のコードを自作するのは割に合わない――だなんてうそぶきつつ、LALR法とか全く知らないままに、既存のyaccのコードを切り貼りして遊んでいるところ。1文字で痛い目(shift/reduce)に遭った。flexと組み合わせた上でのエラー処理(エラーメッセージの改善)が課題だ。2.0を少し触ろうとするも未完に終わった過去をもつ私。2013をインストールして、また少しだけ触ることに。変数の型推論・ラムダ式・LINQ、デフォルト引数は便利だ。それにしても、クラスが必須ではないC言語やC++に慣れてしまった弊害か、アプリケーション・メインエントリすらclass内に定義しなくてはならないC#には、なかなか慣れない。II生まれて初めて触れたプログラミング言語その1。何だかんだで、後でCプログラマになってからも低水準での思考ツールとして微妙に役に立っている。考えるための言語であって実用言語ではない。仮に実用的な処理系*9があったとしても余りに命令がシンプル過ぎて悶絶するなあ、なんてFizzBuzzしてみて思った。(lex)プログラミング言語に含まれるかどうか不明だが、DSL扱いで。何らかのアクション」という内容を記述するためのツールだった。「何らかのアクション」をC言語で書けることと、flex自体ではパターンマッチングをせずに「パターンマッチングするC言語のコード」を生成することが少々風変わりなだけ。grep(1)やsed(1)その他で小ツールを実装して運用しつつ、性能が求められたらflexで専用ツール化する――とか考えたけど、普通にgrep(1)やsed(1)を使う方が高速だった。Go寡作ながらもいくつか小ツールを書いてみたが、標準ライブラリが充実しているコンパイラ型言語っていいっすね。C言語に比べればC++の標準ライブラリも充実しているが、どちらかといえばプリミティブな機能が中心だ。PythonやRubyばりの標準ライブラリを抱えているGoには及ばない。その辺は、やはりCプログラマ(特にCでフィルタやデーモンの類を書く層)には受けそうな言語だと思う。並列処理周り(goroutines)とかARM対応とかが気になる。CPUはありえないからなあ、スマホやタブレット以外では。Guideでも影響を受けた言語として真っ先にSmalltalkが挙げられているから、あながち思い違いでもないだろう。7つの世界』のIoの章を読み終えたので、ちょっとしたコード片を書いているが......Windows版のバイナリが古いためか、リファレンス通りなのに動作しないコードに直面している。JavaScript(クライアントサイド)クライアントサイドJavaScriptのコードを書いたこともあったけど、スキル的にはもう何もかも賞味期限切れだよなあ。2015以降を使うなら、それ以前とはコードのスタイルから変えないと不味そう。何か処理系もNode.jsに収束してきた印象が。LuaWiresharkのパケット解析スクリプトを書いてから数年。今度はC言語で書かれたUnixデーモンの設定ファイル用に組み込むことに。Windowsのことを考えなければ、自前でライブラリをビルドしてアプリに組み込むのは結構簡単だった。SchemeGaucheのWindowsネイティブ環境用バイナリは実験版だが、私が触る分には何の支障もない*10ことに気づいて久しい今日この頃。LispではなくGauche(Scheme)の勉強をする方向に転換しようか検討*11しているうちに何年たったのやら。Gaucheはフィルタ・ライクな小ツールの実装用としても良い感じだ。多い利用方法はREPLを電卓代わりにすることだ*12。うーん、作業環境がmacOSかLinuxに移ったなら、大手を振ってGaucheでフィルタを書くのだが。Tcl/TkTclは書き方を忘れた頃にテキスト処理ツールを書いている気がする。Tclは結構独特な言語だ。構文がシェルスクリプトばりに全てコマンドだったり、値が全て文字列だったり、実はリスト構造だったり、意外とTCPソケット通信が得意だったり......。それでも慣れれば結構使いやすい。意外とプロトタイピングに向いている気がする。8.6以降ではオブジェクト指向プログラミングもOKだが、それよりも例外処理用のtry末尾呼び出しの最適化用のtailcallの方が興味深い。これからメジャーになる可能性は低そうだ。Tkは......小規模なGUIツールをさくっと構築できるところは便利だが、Webアプリ全盛の時代にどれだけ訴求力があるのやら。script少し触ってみた分には、exコマンドの拡張(=コマンドの羅列)とは気づかない程度にはプログラミング言語らしいと思う。いえ妙なところで嵌ったり微妙に一貫性のない部分があったりするので、その辺りで好き嫌いが別れる気がする。XSLT縁が切れたと思いきや、仕事でXHTMLから特定要素を抜き出す作業に使うことに。XMLからテキストレコードに変換してしまえば、後はUnix流テキストフィルタの世界が待っている。餅は餅屋というもので、定型的なXMLの変換はXSLTで記述すると楽だ。一気に入らないのは、xsl:sortでアルファベットの大文字と小文字を区別してソートすることができないこと。これから(また)使うかもしれないAlloy形式手法の中では比較的カジュアルに使えそうなので期待中。入門書も処理系も入手した。私の場合、先に何か論理型の言語をかじった方がよいのかも。Lisp2009年に勉強しようと思い立ったものの、未だに進んでいない。階乗とかハノイの塔とかiotaぐらいは書いたが、目標は「ちょっとしたツールを自作する」だ。最近は時々CLISPを簡易電卓代わりにしている。Coqソフトウェアの基礎が気になるので、処理系だけ入手。Lisp「.emacsにコピペ」限定で。LispやSchemeを触ったためか、何となく内容を追えるようになってきた気がしていたが、勘違いだった。F#OCamlは「Windows上で日本語を扱う」という視点では処理系がちょっと微妙なので、いっそのことF#に乗り換えようかと......。『実践F#』が積読状態になっている。ForthpForthをMinGWでビルドしたので処理系は手元にある。スタック指向の言語はいつか勉強したい。LOGOそういえばLOGOを触ったことがない。REXX思うところがあって処理系とIBM謹製のドキュメントを入手したものの、そこから先の進展は無いまま。REXXっぽい感じで触っているからなあ。Lispを勉強するはずが、いつの間にか触っていた言語。一応、階乗ぐらいは書いた。時間が取れたらもうちょっとしっかりと勉強したいが、面倒なのでF#に移行しようか検討中。Ozふと思い立ってUbuntuにMozartを入れた。『Scheme手習い』の次はCTMCP片手にOzで勉強かなあ。道は遠いな......。Processing入門書も処理系も入手して、あとは弄る時間をつくるだけ。Prolog少し前に触っていた言語。『7つの言語、7つの世界』の地図の色分けプログラムには衝撃を受けた。何というか「正しい問い」を見つけられるか否かが肝なのか。この辺は、根底の部分でAlloyに通じる何かがあるように思う。Prologで論理プログラミングと宣言的なスタイルに慣れておけば、形式手法にて「論理で宣言的に」記述するときに戸惑いが減るのではないかと期待している。Rust仕事柄「C/C++の次のシステムプログラミング言語」はそれなりに興味の対象で、Go言語やD言語ほどではないが、Rustも......まあ、気にならなくはない。ちなみに、これら3言語と同列にObjective-CやSwiftが挙げられることもあるようだが、個人的見解としては、システムプログラミング言語としてのこの2言語には全く期待していない。あれは、Appleというしがらみからは逃れられないでしょうな。Pharo)Smalltalkは有名な古典的プログラミング言語だというのに、触ったことがない。いうことでSqueakとPharoの処理系のみ準備完了。うーん、「環境」付きなのが気になる――言語を弄くる基準が「コンソール上でテキストフィルタ」という変な人種な私だからなあ。Smalltalkも用意してみた。Applications)今までVBAから逃げ回っていたのだが、ついに使うことになりそうな予感。BasicVBScripを触りだした影響で、時々思い出しては弄くっていた。ほんの少しだけ触って放置して、すっかり忘れてからまた触る――これを繰り返していた気がする。毎度初めて触るのと同じ状態だった。:)bcその昔、Windows標準の電卓アプリの代わりに使おうとして色々あって挫折した。今はirbかclisp/goshで計算しているからなあ。APIを叩くスクリプトを書けるので非常に便利。Scalaの型推論とか、便利っすね。言語仕様はJavaよりも好みだ。1.0をWindows上に用意して触ってみた。なんというか、COBOLの名前と生まれた時代が示すように基幹業務(というかお金や帳簿が絡んでくるところ)向けの言語だよなあ、といった感じ。2002のフリーフォーマットを採用するだけでも使い勝手が変わる気がしたが、世の中にはまだ広まらないのだろうか。CoffeeScript仕事で使う予定はない。RubyやPythonその他の影響を受けているだけあり、その手のスクリプト言語っぽい感じでコードを書けるので、慣れれば素のJavaScriptで直接コーディングするよりは楽だ。標準ライブラリ回りや処理系絡みの機能やサードパーティのライブラリなど、結局はJavaScriptを知らないとCoffeeScriptでコードを書けないと思う。それに生成されたJavaScriptのコードを見て「うわぁ、これあまり効率的でないなあ」と感じる時もあって、高速化が必要な部分では生成されるコードを気にしながら記述したりCoffeeScriptを諦めてJavaScriptで書くことになるので、やはりJavaScriptを知らないとマズイ。いえ便利なのは確かだ。CoffeeScriptのコードは即Node.jsで実行できるので、その辺りから「CoffeeScriptでテキストフィルタ」的な文化が生まれると面白いかも。6の存在で、今までCoffeeScript独自の機能だった部分の多くがES6で取り込まれるので、今後ES6対応が進むにつれてCoffeeScriptの立場がどうなっていくのか、少々興味深い。2.x仕事柄「C/C++の次のシステムプログラミング言語」はそれなりに興味の対象で、Go言語ほどではないが、D言語も気になる存在だ。D言語はシンタックスがC・C++に近いだけでなく、コーディングしている時のアプローチ・判断についても、CやC++での流儀がそこそこ通用しやすい気がする。少なくとも、Go言語でコーディングするよりは、文化的背景の違いによるモヤモヤは感じにくい。catchにスッキリまとめることができて、ちょっと驚いた。throwされる例外のメッセージ文字列が、ちょうどよい塩梅の内容だったため、メッセージを変更する(いったんcatchして、再throwする)必要がなかった。残念なのは、マルチバイト対応だが......。95あたりは結構近代的な言語だと思う。用途次第ではC言語よりもFortranの方が遥かにマシな選択だろう。配列がらみの処理はFortranの方が得意だし、言語機能としてのモジュール化の方法はC言語には存在しない。可変長な文字列の扱いに微妙な制限がある点はマイナスな気もするが、まあ基本的に数値計算プログラム用の言語だからなあ。Debugger)......いやGDBはデバッガとして使っているが、GDBのスクリプトを書く機会は(FizzBuzz以外に)ない。勉強不足なだけかもしれない。APIを叩くスクリプトを書けるので非常に便利。動的型付け言語っぽくいくもよし、@CompileStaticや@TypeCheckedで型推論するもよし。言語仕様はJavaよりも好みだ。コンソールアプリを書く人としては、オプション引数解析用の機能を標準で持っている点で、GroovyはClojureやScalaよりもポイントが高い*13。VMベース」の言語としてどこに活路を見出すのが、興味深く見守りたいところ。Processor)FizzBuzzで楽しんでみたが、何というか他言語経験者には受けが悪そうな命令体系だと思う。初心者がプログラミングという行為に深入りせずにWindows用のGUIな何かを作る分には、あの命令体系でも十分な気がしないでもない。ところで元々は「HSPで職業プログラマ的な良いコードを書くと、どんな感じになるか?」というネタを思いついて処理系を用意したのだけど、そちらは全く進展がないまま。WSH他人が使うテキスト処理ツールの実装に使って以来、時々触ってきた。Windows用の配布可能な小ツールを実装する時の定番言語だった。XAMLで代替できそうだ。他のメリットは「JavaScript(ECMAScript)でフィルタを書ける」だったが、WSHのなかなか目的にたどり着けないオブジェクト階層にイライラするよりも、Node.jsやPhantomJSを使ったほうが精神衛生的にマシだ。m4その昔テキスト処理用に触ろうとして、Windows用のどの処理系も日本語の置換に何かしらの問題を抱えていたので泣く泣く諦めた。思うところがあって改めて少し触ってみたが――なるほど、確かに中毒性のある言語*14だ。REXXっぽい方向に走っていた。Frameworkと無関係でいられるのなら、バッチファイルの代替としてはREXXあたりがほどよい塩梅だと感じる。最近流行の言語とは随分と勝手が違うし、日本語の情報も少ない。メインフレーム以外の世界で流行る可能性は少ないだろう。Studioに入っていたのか。機能多すぎで色々と便利なツールを見逃しているんだな、やっぱり」と思いつつ触ってみた。テンプレート変換の用途ではピカ一だと思う。Studioをインストールする」or「MonoDevelopをインストールする」なので、何となく「単体で手軽に使えるツール」ではないというイメージが......。まあC#やVBで処理を記述するので、それらの処理系が必要だという面での制約なのだろう。WSHJScriptほどではないが「Windows上で他人も使えるツールを書くためのLL」扱いしていた言語。Server管理の関係で触っていた。いうかWebで入手可能なWSHのサンプルの大半がVBScriptで書かれていたり、ADSI関連のコレクションをJScriptで舐めれなかったりして、結局は必要に駆られて使用することに。明快に記述できる文法は評価に値するが、スクリプト言語としては少々冗長だ。配列は自動拡張しないし、組み込み関数はプリミティブ気味だし、冗長気味な文法との合わせ技でコードがさらに冗長になっていく......。文法や言語仕様の詳細なドキュメントが見つからないのだが、どこにあるのだろうか?*15秀丸マクロ7年ほど秀丸エディタを使っていたが、マクロを書く機会はなかった。一念発起してFizzBuzzしてみて感じたのは、最近の便利な言語に慣れた身としては色々とモヤモヤ感がある言語仕様だということ(歴史的経緯的に仕方ないのだが)。いえちょっとした拡張ツール的なものを手軽に作れそうではあった。CSS」の組み合わせなら、チューリング完全の疑惑があったり、JavaScript使わずにCSSでWebチャットを作った猛者がいたりと、色々と怪しいのだけど。*2:「独立性の高い単体のツールを実装する」という視点では、現代ではAWKよりも便利な言語が山ほどある。Framework含む)と比較したり、型推論まわりをKotlinやSwiftと比較してはいけない。以前よりも随分と便利になったのだけど、だけど、隣の芝生を見てしまうと、うーん。*4:SwiftではC++の機能を直接呼び出すことができないので、Objective-Cでラッピングした上で利用することになる(インタフェースはObjective-Cで、内部実装はObjective-C++)。この時、Objective-Cクラスのインスタンス変数として「C++クラスのインスタンスを保持するスマートポインタ」を持つ構成にしておくと、Objective-Cクラスのインスタンスがdeallocされる時に、スマートポインタ経由でC++クラスのインスタンスもdeleteされるのである。*5:これでもsedはチューリング完全な言語だと証明されているらしい。*6:少なくともC++の言語仕様は私の手には余る。自分が把握している範囲の機能でコードを書くのは好きなのだけど。*7:とはいえ、ついついC++を使ってしまうのだよなあ。*8:私の認識では、JavaScriptは、第一級関数やクロージャがお仕事用のメジャーな言語に組み込まれて、少なくない人が使う契機となった言語だ。*9:――といってもシミュレータだけど。*10:支障がある部分を触るほど深入りするには、あと20年ぐらい掛かるのではないか?*11:Schemeの勉強というよりも、再帰の勉強なのか?*12:現状はirbかclispかgoshの3択だ。*13:ClojureやScalaに関しては、同様の機能を私が見逃している可能性も高いのだが。*14:m4はマクロプロセッサなのでプログラミング言語ではないはずだけど......。*15:MSDNの資料では物足りない。掘り下げた内容のものが欲しい。WindowsWindowsでUSBメモリなどを取り外す際にタスクトレイから行う「ハードウェアの安全な取り外し」の操作をコマンドプロンプトから実現しようとして、依然として失敗し続けている。備忘録として、時系列順に記録を残しておこうと思う。何か進展があったら追記するつもりだ。Workgroupで運用しているNASがある。このNASには、NTFSでフォーマットしたUSB-HDDが取り付けてある。USB-HDDは、Windowsバックアップツールを利用した定例バックアップ先として使用している。USB-HDDは、定例バックアップの時だけ接続している。バックアップ終了後には、取り外し可能な状態にした上で、USB-HDD本体の電源をOFFにしている。諸々の事情で、定例バックアップはWbadmin.exeを叩くパッチファイルをタスクスケジューラで実行することで実現している。定例バックアップ完了後に、毎回NASにログオンして「ハードウェアの安全な取り外し」の操作をするのが面倒である。同様の操作をパッチファイルから実行することで自動化したい。2016の標準の機能か、もしくはMicrosoftが公開しているツールなどで実現したい。サードパーティのツールは導入したくない。以上の理由より、コマンドプロンプト(正確にはパッチファイル)から標準/準標準の機能で「ハードウェアの安全な取り外し」と同等の処理を実現しようと試みているのだが、未だに成功する気配がない。今のところ得られている結果は「そもそもアンマウントすらできない」か「運用上問題となる副作用が発生する」のどちらかである。EjectPowerShellを使ってCD-ROMドライをイジェクトするネタがあるのだが、同じ方法でUSBデバイスもいけるという情報を得たので、試してみた。Shell.Application).Namespace(17).ParseName('F:').InvokeVerb('Eject')結果:アンマウントすらされない。Sysinternalsのsync.exe/sync64.exeのオプション-eでイジェクトできるとの情報を得たので、試してみた。F結果:アンマウントすらされない。使う標準コマンドmountvolのヘルプを見たところ、オプション/pにそれっぽい内容の記述があったので、試してみた。/p結果:ディスクがアンマウントされ、オフラインになる。その後にタスクトレイでの取り外し操作は必要だが、既にオフライン状態なので、直ぐに取り外し可能状態になる。問題点:この後ディスクの電源をONにした時、ドライブレターの割り当てが外れている。/p」でFドライブのUSB-HDDを取り外した場合、そのUSB-HDDを再度接続した時、ドライブレターが全く割り当てられない(なのでエクスプローラーの「デバイスとドライブ」からはUSB-HDDにアクセスできない)。オフラインにするPowerShellのSet-Diskでゴニョゴニョできる、という情報を得たので、試してみた。-IsOffline:$true結果:ディスクがアンマウントされ、オフラインになる。その後にタスクトレイでの取り外し操作は必要だが、既にオフライン状態なので、直ぐに取り外し可能状態になる。問題点:この後ディスクの電源をONにした時、ディスクがオフラインのままになる。Set-Diskを使うなどして明示的にオンライン状態にしないとUSB-HDDが使えない。ソフトウェア・テスト5年前の今頃は、なにやらTDDで熱かったらしい。QiitaTDDには全く何も取り組んでいない身なのだが、しかし傍から見聞きしているだけでも、TDDには参考となる面が色々とある。それらの「参考となる面」は、TDDそのものというよりも、TDDによる副産物による部分が多い気がしてならない。本エントリでは、TDDの部外者がTDDを見聞きした上で有用であると感じた面を挙げることで、TDDの別の側面にフォーカスを当ててみたいと思う。ソフトウェア・テスト:第三次接近遭遇よくあるTDDの例では、少なくとも(伝統的な開発工程でいう)詳細設計および実装のフェーズと単体テストが一体化している。この結果として、プログラマはどうあがいてもソフトウェア・テストの一部工程(下位Vモデルでのテスト工程の一部)と主体的に関わらざるをえなくなる。考えれば、これは意外と革新的なことだったのではないかと思う。ものすごく伝統的な職業プログラマの世界では、プログラマとテスターは分かれているし、双方の間に厳然たる身分差があることも多い。プログラマはコードを書き、書いたコードがビルド可能かつ何となく動いているっぽいことを漫然と観察するだけ。テスターはアプリ/システム全体を対象としたテストケースを書き、テストを行い、不具合報告書をあげるだけ。両者は異なる身分で、時にいがみ合っていることもある。あたりでテストの基礎知識をおざなりに学んだか、初めてプロジェクトに配属された際の役割がテスターだった程度で、コードを書くようになってからはテストとは無縁だったりする。「そんなこたぁテスターにやらしときゃええのよ」。私自身はそこまで「ものすごく伝統的な職業プログラマの世界」な場面に直面したことはないが、組み込み開発の「プログラマが責任もって単体・結合テストを担当」なプロジェクトと、PCアプリの「単体・結合テストは行わず、アプリ全体のシステムテストで済ます」プロジェクトの双方を経験している。その経験を元に、誤解を恐れずに書くなら、ソフトウェア・テストに通じているプログラマと通じていないプログラマとでは、明らかにコードの書き方が異なる。「単体テストや結合テストでコードの正当性を検証すること」を強く意識しているコードと、その辺りを全く意識していないコード(単体テストや結合テストを形式的にしか実施していないコードを含む)の間には、その書き方に差異が見られる。ソフトウェア・テストと真剣に向き合っているプログラマは、よくある単純な不具合事例を回避するために防御的にコードを書くし、問題が起きやすい部分(例えば境界値がらみとか、マルチスレッドでの排他など)を実装する際には細心の注意を払う。境界値を気にかけるプログラマは、境界条件における極端なふるまいを考慮し、ときに設計・仕様の不備や矛盾に起因する問題を実装前に発見する。真剣に単体テストを行うプログラマは、段々とテスタビリティを考慮したコーディングをするようになる。「単体テストによる正当性の検証」を視野に入れたプログラマは、できるだけ結合度が低く単機能の関数/メソッドを志すようになる。ソフトウェア・テストの知見の有無は、書いたコードの品質に良い影響を与える。ソフトウェア・テストを強く意識することで、テスト実施の有無にかかわらずバグの数が低減する可能性がある。その意味において、プログラマがテストのことをあまり意識する必要がなかった伝統的な環境から、プログラマが低水準のテスト(単体テストや結合テスト)を通じてテストのことを強く意識する切欠を与える環境への移行は、ソフトウェアの品質を向上させるチャンスではないだろうか?無論、従来の延長線上に「単体テストをちゃんと実施しましょう」という工程を付け加えるだけでも効果があるかもしれないが、TDDの場合、(「そんな単体テストで大丈夫か?」的問題は発生しうるものの)実装と単体テストが不可分であるので単体テストをサボりにくい、という利点があるといえる。テストをやらずに済むならなにも意識せずにスルーできるが、テストせざるをえないなら否応なく意識することになるのだ。単体テストによるコスト削減の可能性TDDの話は、結構な割合で関数/メソッド単位の単体テストとセットになっている。これはつまり、ソフトウェアの品質向上の面では、いわゆる「テスト担当者がシステムを触ってバグを出す」というレベルのテストとは別に、よりソースコードに密着した開発者テストを実施することも有効である、ということだ。(実施するテストが増えている点に注意。TDDを行ったからといって、従来の「テスト担当者によるテスト」が不要になるわけではない)このことは、実のところ今更書くようなことではない。昔から「単体テスト・結合テスト・統合テスト・システムテスト」と言われてきたではないか。出てくるほどに鉄板のネタだ。組み込み開発のように高品質が求められる分野では、関数/メソッド単位での単体テストを実施することが多い。形式的に、ではなくキッチリと実施していれば、それなりにソフトウェアの品質向上に結びつく効果がある。なければ、単体テストが行われなくなって久しいはずだ。組み込み業界にいる私からすれば、関数/メソッド単位の単体テストや結合テストは「プログラマの嗜み」というか、「開発者テスト」として責任を持って行うべきものだ。本職のテスター*1には劣るが、ソフトウェア・テストの基礎知識を学んだ上で実務への適用方法を試行錯誤するのは当然のことだ。単体テストや結合テストで得られた知見から、コードの書き方を見直すこともある。一方で、その組み込み業界においても、例えばデバイスと連携するPCアプリやモバイルアプリの開発では、様々な事情で関数/メソッド単位での単体テスト・結合テストを行わずにアプリ全体を対象としたテスト(システムテストなど)で済ましてしまうことがある。いうアプリは、一見して正しく動作しているようで、実は隠れた爆弾を抱えていたりすることがある。そんなアプリの改修に関わって痛い目に遭った経験がある私としては、最低でも関数/メソッド単位の単体テストぐらいはキッチリと行ってほしいのだが......。ソフトウェア・テストは、ある意味においてコンクリートのひび割れや空洞の検査に似ている。アプリケーション全体をブラックボックスと見立てた普通のシステムテストは、コンクリートを目視で検査するようなものだ。優秀なテスターなら、打音調査や超音波による検査を行うだろう。目視や打音調査などよりも確実な手法がある。コンクリートをスライスして断面を調べることだ。コンクリートの検査では不可能だが、ソフトウェア・テストでは可能だ。コードリーディングによるレビュー、静的解析ツールによるインスペクション、関数/メソッド単位の単体テスト・結合テストが該当する。関数/メソッド単位の単体テストが行われないのは、効果が分かりにくいからだ。あるアプリケーションを実装まで行い、その後の工程を「同じ環境、同じ人員」にて「単体テストあり」と「単体テストなし」に分けて行うことが可能ならば、両者の比較から有意な差の有無が判明するだろう(と私は妄想している)。手戻り」によるコストの低減だろう。前者の「品質向上」は、関数/メソッド単位の単体テストを実施すべき論拠としてはやや弱めだろう。顧客からみて「一定以上の品質が保たれている」と感じられるのなら、そこからどれだけ品質を向上しても、直接的な収益に結びつかないからだ。職業プログラマの場合、論理的には「費用対効果」より求められる品質が決まるはず*2なので、仮に「関数/メソッド単位の単体テストをせずとも要求された品質をクリアしている」という状態*3ならば、関数/メソッド単位の単体テストの実施は「過剰品質」となる。結合テスト以降の工程のコストが低減するのなら話が変わってくる。開発期間の短縮や、場合によっては売上原価の圧縮に結びつくからだ。システムのライフサイクルという観点では、経験的に、関数/メソッド単位の単体テストを行っていないコードは「保守・改修」の工程に禍根を残すことも多い気がする。この直感が正しいならば、関数/メソッド単位の単体テストを実施することによりライフサイクル全体におけるコストが低減する可能性がある、とも考えられる。いった、計測の難しい部分のコストへの影響を明らかにすることが可能ならば、単体テストの重要性について開発者以外に説明する際に、有力な論拠となりうるだろう。計測が可能か否か、またどう計測するか、という問題はあるが......。テスタビリティの高さ≒コードの品質の良さ先に書いたが、「単体テストや結合テストでコードの正当性を検証すること」を強く意識しているコードと、その辺を全く意識していないコードには、大きな差異がある。良いコードを書こうとするプログラマは、よくある単純な不具合事例を回避するために、防御的にコードを書くようになる。C言語系統の言語で度々話題となる「{}を付けるか否か」問題だ。防御的にコーディングする人は必ず{}を付けるし、{}を省く人でも明らかに「この程度なら大丈夫だろう」というケース(例えば単文ifでの即時returnによる引数エラーチェックの羅列とか)にとどめることが多い。(0)」で囲むこともある。防御的にコードを書こうとするプログラマは、同時に、よく問題が起きやすい部分を実装する際には細心の注意を払うようになる。境界値絡みとか、マルチスレッドでの排他・競合などだ。境界値・境界条件を気にかけるプログラマは、境界条件においてプログラムがどう振る舞うか、またどう振る舞うべきか、時間を割いて検討することが多い。境界条件では「極端な振る舞い」が発生する可能性がある。その辺を考察することで、時に設計・仕様の不備や矛盾に起因する問題を実装前に発見することがある。byteのファイル」のケースを、「1行1レコード」のデータファイルなら「改行コードのみの行を含むファイル」や「ファイル末尾に改行コードが存在しないファイル」のケースを考慮するものだ。ここまでは、テストによる正当性の検証にこだわっていなくても、良いコードを書こうとしている人なら取り組んでいることが多い。単体テストに取り組むようになると、ここからどう変化するのだろうか?真剣に単体テストを行うプログラマは、段々とテスタビリティを考慮したコーディングを行うようになる。複雑な条件式は、組み合わせを網羅するテストケースを考えるのが難しいし、また実際にテストする際に「どこまでテストしたか?」という点が曖昧になってしまうものだ。テスタビリティを考慮して、複数の「単純な条件式」に分解するようになる。C言語系の言語にある三項演算子は、便利な反面、複雑で怪しげなコードを書いてしまいやすいという欠点がある。そこで代替案として、短いけど入れ子になって複雑な三項演算子の塊を、あえて複数のif文を用いて「冗長だけど分かりやすい」コードに書き直すことを提案される場合がある。これなども、実のところテスタビリティの観点から同様な結論に達することがままあるものだ。「多少冗長だけど分かりやすい」コードの方がテストケースを考えやすいからだ。「単体テストによる正当性の検証」を視野に入れているプログラマは、可能な限り結合度が低く且つ単機能の関数/メソッドを書こうとする。理由は簡単で、その方が単体テストのテストケースを考えやすいからだ。単純な話、数千行あるような最長不倒関数には大抵色々な機能が詰め込まれているものだ。そんな関数のテストケースを考えるのも、テストケースを充足できるに足るような自動テストスイートを用意するのも、ライフワークとなりかねない危険で複雑な作業だ。そのような危険を避けようとすると、自然と各関数は単機能になるし、引数の数は少なめになるし、行数は短めになるし、グローバル変数やインスタンス変数の参照を抑えた結合度の低い実装になる。結果として、実装された関数は、自然とモジュール強度(凝集度)が高く且つモジュール結合度が低いものが多くなる。不思議なもので、テスタビリティを考慮してコードを書くことで、自ずとコードの品質が良い方向に変化するのである。この辺りは、テスタビリティなんて考えず、形式的にしか単体テストを行わない開発者には無理な話だろう。「テストケース作成」による「仕様」の網羅、明確化(先に誤解されないように書いておく。TDDにおけるテストは、単体テストとは限らない。その矛盾や曖昧な点をどうするか確認した結果、今までの実装の少なくない部分を破棄してやり直す破目になったことはないだろうか?TDDは「Test」の名を関する手法な訳だが、ソフトウェア・テストには少々興味深い特性がある。テストする前にバグやバグがありそうな場所を発見できることがあるのだ。ホワイトボックス・テストやグレーボックス・テストを除けば――要はブラックボックス・テストなのだが――テストケースは仕様書を読み解いて作成することになる。ここで、テストの期待結果を明確に記述できないテストケースを発見したなら、おそらく関連する仕様に抜けや漏れがあるか、仕様が曖昧であるはずだ。その周辺にバグが潜んでいる可能性がある。不具合とまでは言えないが、お客様に確認していただいたら「そこって、そうじゃないんだよねぇ」とちゃぶ台返しとなるかもしれない。別の例として状態遷移が挙げられる。仕様書に状態遷移図が書かれていたり、もしくは状態遷移図は書かれていないものの状態遷移っぽい部分が存在することがある。考慮し忘れ)があったり、そもそも状態遷移表に書き直せない(=矛盾がある)ことがある。いった部分には、バグが潜んでいる可能性が高い。ソフトウェア・テストは、テストを実施すること以上に、実施するテストを考えることが重要だ。テストケースを考えている時点で、未だテストを実施していないのにもかかわらず、バグがありそうな場所が見えてくることがある。テストケース作成で炙り出せるバグは、仕様策定や設計の段階に遡ることができる問題であることも多い。これはつまり、言い方を変えるならば、「テストケース作成」という形で仕様や設計をレビューしているに等しい。通常のレビューとは別に、再度レビューを行うことで、仕様がより明確となるし、仕様書を隅から隅までチェックすることによる網羅も期待できる。TDDでは割と早い段階でテストケースを作成する。それは、TDDの入門書のように単体テストかもしれないし、単体テストよりも上位のテスト(システムテストなど)かもしれないが、いずれもテストケース作成を通じて仕様や設計を網羅し、不明点を明確にし、漏れや矛盾をさらけ出す効果を期待できる。何も考えずに形式的にテストケースを作成してしまっては、何の効果も得られないだろう。仕様を網羅するように、且つ怪しそうな部分をピンポイントで狙い撃つ。よいテストケースの作成は難しい。作れるようになるまで時間がかかるものだ。それでも、実装の前に良質なテストケースを作成できれば、仕様に遡るような問題を減らした状態でコードを書き始めることができる。実装フェーズや、その後のテストフェーズにて、仕様策定や設計の段階への手戻りが発生する可能性は低くなるはずだ。自動テストスイートによる「気軽にテスト再実施」TDDの話では、「関数/メソッド単位の単体テスト」と同じくテスト自動化もセットになっていることが多い。テスト自動化は、初期投資のコストがかかる。関数/メソッド単位の単体テストの自動化は比較的コストが低い部類に入るのだが、それでも手間がかかる。忙しいと、ついつい単体テストともども省略してしまいたくなるものだ。UIのテストなど、システム全体にまたがるテストを自動化しようものなら、仕組みを作る/導入するコストは更に大きくなる。一度仕組みを用意してしまえば、「これほど心強い味方はいない」と言わしめるほど役に立つ。ソフトウェアのバグ修正、既存機能の改良、新機能の追加の度に、修正を加えた部分のテストケースのみ手を加えた上で全体をテストし直すことで、追加・変更点の再テストと同時に既存部分のリグレッションテストを済ますことができる。ソフトウェアに変更を加えた後の再テストは意外と大変だ。変更を加えた部分だけでなく、変更が波及するだろう部分もテストし、デグレードがないことを確認しなくてはならない。デグレードを見つけるには、変更の波及が想定される部分を推定してそこだけテストするか、ソフトウェア全体を再テストするしかない。変更の波及箇所を推定する方法、実施範囲を抑えることができる反面、見落としによるテスト漏れが発生する可能性がある。安全なのは「全体を再テスト」だが、テスト方法が全て手動ならばコストが高くつくし、プレッシャーの下で手作業でテストしているならば、どこかで手順間違いなどのミスが起こりうる。テストが自動化されていれば、ソフトウェア全体を再テストする際のコストが低くなる。コストが低ければ、気軽にテストすることができる。見落とされがちだが、「気軽にテストできる」ということは重要だ。リリースしたソフトウェアが、保守・改良されつつ長く長く使われ続けるほどに、自動テストは開発期間の短縮と一定品質の保持という効果をもたらす。パッケージソフトや組み込み製品開発など、競合が多数存在する分野においては、初版リリース後のバグ修正や新機能追加におけるフットワークの軽さは武器の一つとなりうる。その意味においては、自動化の対象を単体テストに絞る必要はない。いや、もちろん単体テストの自動化も効果があるのだが、より広範囲の、システム全体にまたがるテストの自動化も重要となる。それこそ、Webアプリ界隈ではブラウザの互換性の問題もあり、GUIに関わるテストを自動化しようという動きが見られる。こまめに修正・改良とデプロイを繰り返したいのなら、テストの自動化は必須なのだ。この特徴ゆえに、テスト自動化は反復型開発と親和性が高く、反復型であるアジャイル開発(特に変化を前提とするXP)にて取り上げられるのだろう。テスト自動化については、保守コストが発生する点も考慮する必要がある。継続的に開発を続けていくプロジェクトでは、刻一刻と変化していく環境に合わせて自動テスト・システムも改良されていくし、プロジェクトが継続している以上は自動テスト・システムも存在し続けても大丈夫だろう。「Ver.1完成→チーム解散→数年後にVer.2開発開始」というスタイルの開発では、例えばVer.1の自動テスト・システムをVer.2開発で使用しようと試みた際、改めて自動テスト・システムが動作する環境を構築し直す作業が発生するし、OSや開発ツールや開発マシンの変化に一気に追随する大きな手間もかかるだろう。仮に今後、テスト自動化を広めていきたいのならば、この種の保守コストとどう向き合うべきか考える必要があるだろう。場合によっては、「プロジェクト」のあり方を議論する必要があるかもしれない。まとめTDD部外者から見て、TDDには次のような有用な要素が含まれている。開発者にソフトウェア・テストを強く意識させる(他人事だと思わせない)。ソースコードに近いレイヤーのテスト(単体テストなど)の有用性を明示している。テストを意識することで、テスタビリティの高い、ソースコードの読者からみて見通しのよいコードを書くようになる契機となりうる。テストケース作成にあたり、開発対象の仕様を明確化し、漏れのないよう網羅しようという意識が(プログラマにも)働く。自動テストにより、リグレッションテストのコストを引き下げる。リリース後のバージョンアップ等における開発期間を短くする効果がある。上記の各要素、特に2~4は、よく見てみれば昔から指摘されてきた。