Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

Computing Curricula 1991における12の頻出概念

ACMIEEE-CSは、1991年に計算機分野における教育カリキュラム案「Computing Curricula 1991」*1を作成している。

この中では、コンピュータ・サイエンスにおける基本的発想が、12個の頻出概念(または再起概念、Recurring Concepts)という形でまとめられている。

私が2001年に大学で受けていた授業「知識情報工学実験*2」では「『こいつがわかっていないやつは、同業者と認めたくない』といいたくなるような内容」とか言われていてちょっと面白かったので列挙しておく*3

  • Binding
  • Complexity of large problems
  • Conceptual and formal models
  • Consistency and completeness
  • Efficiency
  • Evolution
  • Levels of abstraction
  • Ordering in space
  • Ordering in time
  • Reuse
  • Security
  • Trade-offs and consequences

*1:Allen B. Tucker. 1991. Computing Curricula 1991. Commun. ACM 34, 6 (June 1991), 68–84. https://doi.org/10.1145/103701.103710

*2:12個の頻出概念それぞれについて具体例を挙げてその内容を説明しよう、という内容があった

*3:知識情報工学実験の資料は、2001年には豊橋技術科学大学 知識情報工学系 情報教育学研究室のサイトに載っていたのだが、Wayback Machineのクローラをrobots.txtで弾いていたか何かで過去のデータが取れなかった

ASCIIとLatin-1の各文字の文字タイプ

以下のスクリプトを実行し、ASCIIおよびLatin-1の各文字の文字タイプがUnicodeでどう定義されているか確認した。

# Compile a helper type with P/Invoke declarations for enabling / disabling VT support.
# Note: This incurs a once-per-session peformance penalty.
$consoleHelper = Add-Type -PassThru -Namespace "NS$PID" -Name ConsoleHelper -MemberDefinition @'
  [DllImport("kernel32.dll", SetLastError=true)]
  static extern bool SetConsoleMode(IntPtr hConsoleHandle, int mode);
  [DllImport("kernel32.dll", SetLastError=true)]
  static extern bool GetConsoleMode(IntPtr handle, out int mode);
  [DllImport("kernel32.dll", SetLastError=true)]
  static extern IntPtr GetStdHandle(int handle);

  public static void EnableVtSupport(bool enable = true) {
    IntPtr outHandle = GetStdHandle(-11); // -11 == STD_OUTPUT_HANDLE
    int mode;
    GetConsoleMode(outHandle, out mode);
    SetConsoleMode(outHandle, enable ? (mode | 0x4) : (mode & ~0x4)); // 0x4 == ENABLE_VIRTUAL_TERMINAL_PROCESSING
  }
'@

function Show-ControlCharacters {
    param (
        [string]$inputString
    )

    $visualMap = @{
        # ASCII C0 control codes (ANSI X3.4)
        ("{0}" -F [Char]0) = "␀";
        ("{0}" -F [Char]1) = '␁';
        ("{0}" -F [Char]2) = '␂';
        ("{0}" -F [Char]3) = '␃';
        ("{0}" -F [Char]4) = '␄';
        ("{0}" -F [Char]5) = '␅';
        ("{0}" -F [Char]6) = '␆';
        ("{0}" -F [Char]7) = '␇';
        ("{0}" -F [Char]8) = '␈';
        ("{0}" -F [Char]9) = '␉';
        ("{0}" -F [Char]10) = '␊';
        ("{0}" -F [Char]11) = '␋';
        ("{0}" -F [Char]12) = '␌';
        ("{0}" -F [Char]13) = '␍';
        ("{0}" -F [Char]14) = '␎';
        ("{0}" -F [Char]15) = '␏';
        ("{0}" -F [Char]16) = '␐';
        ("{0}" -F [Char]17) = '␑';
        ("{0}" -F [Char]18) = '␒';
        ("{0}" -F [Char]19) = '␓';
        ("{0}" -F [Char]20) = '␔';
        ("{0}" -F [Char]21) = '␕';
        ("{0}" -F [Char]22) = '␖';
        ("{0}" -F [Char]23) = '␗';
        ("{0}" -F [Char]24) = '␘';
        ("{0}" -F [Char]25) = '␙';
        ("{0}" -F [Char]26) = '␚';
        ("{0}" -F [Char]27) = '␛';
        ("{0}" -F [Char]28) = '␜';
        ("{0}" -F [Char]29) = '␝';
        ("{0}" -F [Char]30) = '␞';
        ("{0}" -F [Char]31) = '␟';
        # ("{0}" -F [Char]32) = '␠';
        ("{0}" -F [Char]127) = '␡';

        # ISO/IEC 6429 C1 Control codes
        ("{0}" -F [Char]128) = "<PAD>";
        ("{0}" -F [Char]129) = "<HOP>";
        ("{0}" -F [Char]130) = "<BPH>";
        ("{0}" -F [Char]131) = "<NBH>";
        ("{0}" -F [Char]132) = "<IND>";
        ("{0}" -F [Char]133) = "<NEL>";
        ("{0}" -F [Char]134) = "<SSA>";
        ("{0}" -F [Char]135) = "<ESA>";
        ("{0}" -F [Char]136) = "<HTS>";
        ("{0}" -F [Char]137) = "<HTJ>";
        ("{0}" -F [Char]138) = "<VTS>";
        ("{0}" -F [Char]139) = "<PLD>";
        ("{0}" -F [Char]140) = "<PLU>";
        ("{0}" -F [Char]141) = "<RI>";
        ("{0}" -F [Char]142) = "<SS2>";
        ("{0}" -F [Char]143) = "<SS3>";
        ("{0}" -F [Char]144) = "<DCS>";
        ("{0}" -F [Char]145) = "<PU1>";
        ("{0}" -F [Char]146) = "<PU2>";
        ("{0}" -F [Char]147) = "<STS>";
        ("{0}" -F [Char]148) = "<CCH>";
        ("{0}" -F [Char]149) = "<MW>";
        ("{0}" -F [Char]150) = "<SPA>";
        ("{0}" -F [Char]151) = "<EPA>";
        ("{0}" -F [Char]152) = "<SOS>";
        ("{0}" -F [Char]153) = "<SGC>";
        ("{0}" -F [Char]154) = "<SCI>";
        ("{0}" -F [Char]155) = "<CSI>";
        ("{0}" -F [Char]156) = "<ST>";
        ("{0}" -F [Char]157) = "<OSC>";
        ("{0}" -F [Char]158) = "<PM>";
        ("{0}" -F [Char]159) = "<APC>";

        # Add more mappings as needed
    }

    foreach ($key in $visualMap.Keys) {
        $inputString = $inputString -replace $key, $visualMap[$key]
    }

    return $inputString
}

# Temporarily turn off VT support.
$consoleHelper::EnableVtSupport($false)

0..255 | ForEach-Object { $c = [Char]$_; $type = [System.Globalization.CharUnicodeInfo]::GetUnicodeCategory($c); "[{0:x}],[{1}], [{2}]" -F $_, (Show-ControlCharacters($c)), $type }

結果は以下。

[0],[␀], [Control]
[1],[␁], [Control]
[2],[␂], [Control]
[3],[␃], [Control]
[4],[␄], [Control]
[5],[␅], [Control]
[6],[␆], [Control]
[7],[␇], [Control]
[8],[␈], [Control]
[9],[␉], [Control]
[a],[␊], [Control]
[b],[␋], [Control]
[c],[␌], [Control]
[d],[␍], [Control]
[e],[␎], [Control]
[f],[␏], [Control]
[10],[␐], [Control]
[11],[␑], [Control]
[12],[␒], [Control]
[13],[␓], [Control]
[14],[␔], [Control]
[15],[␕], [Control]
[16],[␖], [Control]
[17],[␗], [Control]
[18],[␘], [Control]
[19],[␙], [Control]
[1a],[␚], [Control]
[1b],[␛], [Control]
[1c],[␜], [Control]
[1d],[␝], [Control]
[1e],[␞], [Control]
[1f],[␟], [Control]
[20],[ ], [SpaceSeparator]
[21],[!], [OtherPunctuation]
[22],["], [OtherPunctuation]
[23],[#], [OtherPunctuation]
[24],[$], [CurrencySymbol]
[25],[%], [OtherPunctuation]
[26],[&], [OtherPunctuation]
[27],['], [OtherPunctuation]
[28],[(], [OpenPunctuation]
[29],[)], [ClosePunctuation]
[2a],[*], [OtherPunctuation]
[2b],[+], [MathSymbol]
[2c],[,], [OtherPunctuation]
[2d],[-], [DashPunctuation]
[2e],[.], [OtherPunctuation]
[2f],[/], [OtherPunctuation]
[30],[0], [DecimalDigitNumber]
[31],[1], [DecimalDigitNumber]
[32],[2], [DecimalDigitNumber]
[33],[3], [DecimalDigitNumber]
[34],[4], [DecimalDigitNumber]
[35],[5], [DecimalDigitNumber]
[36],[6], [DecimalDigitNumber]
[37],[7], [DecimalDigitNumber]
[38],[8], [DecimalDigitNumber]
[39],[9], [DecimalDigitNumber]
[3a],[:], [OtherPunctuation]
[3b],[;], [OtherPunctuation]
[3c],[<], [MathSymbol]
[3d],[=], [MathSymbol]
[3e],[>], [MathSymbol]
[3f],[?], [OtherPunctuation]
[40],[@], [OtherPunctuation]
[41],[A], [UppercaseLetter]
[42],[B], [UppercaseLetter]
[43],[C], [UppercaseLetter]
[44],[D], [UppercaseLetter]
[45],[E], [UppercaseLetter]
[46],[F], [UppercaseLetter]
[47],[G], [UppercaseLetter]
[48],[H], [UppercaseLetter]
[49],[I], [UppercaseLetter]
[4a],[J], [UppercaseLetter]
[4b],[K], [UppercaseLetter]
[4c],[L], [UppercaseLetter]
[4d],[M], [UppercaseLetter]
[4e],[N], [UppercaseLetter]
[4f],[O], [UppercaseLetter]
[50],[P], [UppercaseLetter]
[51],[Q], [UppercaseLetter]
[52],[R], [UppercaseLetter]
[53],[S], [UppercaseLetter]
[54],[T], [UppercaseLetter]
[55],[U], [UppercaseLetter]
[56],[V], [UppercaseLetter]
[57],[W], [UppercaseLetter]
[58],[X], [UppercaseLetter]
[59],[Y], [UppercaseLetter]
[5a],[Z], [UppercaseLetter]
[5b],[[], [OpenPunctuation]
[5c],[\], [OtherPunctuation]
[5d],[]], [ClosePunctuation]
[5e],[^], [ModifierSymbol]
[5f],[_], [ConnectorPunctuation]
[60],[`], [ModifierSymbol]
[61],[a], [LowercaseLetter]
[62],[b], [LowercaseLetter]
[63],[c], [LowercaseLetter]
[64],[d], [LowercaseLetter]
[65],[e], [LowercaseLetter]
[66],[f], [LowercaseLetter]
[67],[g], [LowercaseLetter]
[68],[h], [LowercaseLetter]
[69],[i], [LowercaseLetter]
[6a],[j], [LowercaseLetter]
[6b],[k], [LowercaseLetter]
[6c],[l], [LowercaseLetter]
[6d],[m], [LowercaseLetter]
[6e],[n], [LowercaseLetter]
[6f],[o], [LowercaseLetter]
[70],[p], [LowercaseLetter]
[71],[q], [LowercaseLetter]
[72],[r], [LowercaseLetter]
[73],[s], [LowercaseLetter]
[74],[t], [LowercaseLetter]
[75],[u], [LowercaseLetter]
[76],[v], [LowercaseLetter]
[77],[w], [LowercaseLetter]
[78],[x], [LowercaseLetter]
[79],[y], [LowercaseLetter]
[7a],[z], [LowercaseLetter]
[7b],[{], [OpenPunctuation]
[7c],[|], [MathSymbol]
[7d],[}], [ClosePunctuation]
[7e],[~], [MathSymbol]
[7f],[␡], [Control]
[80],[<PAD>], [Control]
[81],[<HOP>], [Control]
[82],[<BPH>], [Control]
[83],[<NBH>], [Control]
[84],[<IND>], [Control]
[85],[<NEL>], [Control]
[86],[<SSA>], [Control]
[87],[<ESA>], [Control]
[88],[<HTS>], [Control]
[89],[<HTJ>], [Control]
[8a],[<VTS>], [Control]
[8b],[<PLD>], [Control]
[8c],[<PLU>], [Control]
[8d],[<RI>], [Control]
[8e],[<SS2>], [Control]
[8f],[<SS3>], [Control]
[90],[<DCS>], [Control]
[91],[<PU1>], [Control]
[92],[<PU2>], [Control]
[93],[<STS>], [Control]
[94],[<CCH>], [Control]
[95],[<MW>], [Control]
[96],[<SPA>], [Control]
[97],[<EPA>], [Control]
[98],[<SOS>], [Control]
[99],[<SGC>], [Control]
[9a],[<SCI>], [Control]
[9b],[<CSI>], [Control]
[9c],[<ST>], [Control]
[9d],[<OSC>], [Control]
[9e],[<PM>], [Control]
[9f],[<APC>], [Control]
[a0],[ ], [SpaceSeparator]
[a1],[¡], [OtherPunctuation]
[a2],[¢], [CurrencySymbol]
[a3],[£], [CurrencySymbol]
[a4],[¤], [CurrencySymbol]
[a5],[¥], [CurrencySymbol]
[a6],[¦], [OtherSymbol]
[a7],[§], [OtherPunctuation]
[a8],[¨], [ModifierSymbol]
[a9],[©], [OtherSymbol]
[aa],[ª], [OtherLetter]
[ab],[«], [InitialQuotePunctuation]
[ac],[¬], [MathSymbol]
[ad],[­], [Format]
[ae],[®], [OtherSymbol]
[af],[¯], [ModifierSymbol]
[b0],[°], [OtherSymbol]
[b1],[±], [MathSymbol]
[b2],[²], [OtherNumber]
[b3],[³], [OtherNumber]
[b4],[´], [ModifierSymbol]
[b5],[µ], [LowercaseLetter]
[b6],[¶], [OtherPunctuation]
[b7],[·], [OtherPunctuation]
[b8],[¸], [ModifierSymbol]
[b9],[¹], [OtherNumber]
[ba],[º], [OtherLetter]
[bb],[»], [FinalQuotePunctuation]
[bc],[¼], [OtherNumber]
[bd],[½], [OtherNumber]
[be],[¾], [OtherNumber]
[bf],[¿], [OtherPunctuation]
[c0],[À], [UppercaseLetter]
[c1],[Á], [UppercaseLetter]
[c2],[Â], [UppercaseLetter]
[c3],[Ã], [UppercaseLetter]
[c4],[Ä], [UppercaseLetter]
[c5],[Å], [UppercaseLetter]
[c6],[Æ], [UppercaseLetter]
[c7],[Ç], [UppercaseLetter]
[c8],[È], [UppercaseLetter]
[c9],[É], [UppercaseLetter]
[ca],[Ê], [UppercaseLetter]
[cb],[Ë], [UppercaseLetter]
[cc],[Ì], [UppercaseLetter]
[cd],[Í], [UppercaseLetter]
[ce],[Î], [UppercaseLetter]
[cf],[Ï], [UppercaseLetter]
[d0],[Ð], [UppercaseLetter]
[d1],[Ñ], [UppercaseLetter]
[d2],[Ò], [UppercaseLetter]
[d3],[Ó], [UppercaseLetter]
[d4],[Ô], [UppercaseLetter]
[d5],[Õ], [UppercaseLetter]
[d6],[Ö], [UppercaseLetter]
[d7],[×], [MathSymbol]
[d8],[Ø], [UppercaseLetter]
[d9],[Ù], [UppercaseLetter]
[da],[Ú], [UppercaseLetter]
[db],[Û], [UppercaseLetter]
[dc],[Ü], [UppercaseLetter]
[dd],[Ý], [UppercaseLetter]
[de],[Þ], [UppercaseLetter]
[df],[ß], [LowercaseLetter]
[e0],[à], [LowercaseLetter]
[e1],[á], [LowercaseLetter]
[e2],[â], [LowercaseLetter]
[e3],[ã], [LowercaseLetter]
[e4],[ä], [LowercaseLetter]
[e5],[å], [LowercaseLetter]
[e6],[æ], [LowercaseLetter]
[e7],[ç], [LowercaseLetter]
[e8],[è], [LowercaseLetter]
[e9],[é], [LowercaseLetter]
[ea],[ê], [LowercaseLetter]
[eb],[ë], [LowercaseLetter]
[ec],[ì], [LowercaseLetter]
[ed],[í], [LowercaseLetter]
[ee],[î], [LowercaseLetter]
[ef],[ï], [LowercaseLetter]
[f0],[ð], [LowercaseLetter]
[f1],[ñ], [LowercaseLetter]
[f2],[ò], [LowercaseLetter]
[f3],[ó], [LowercaseLetter]
[f4],[ô], [LowercaseLetter]
[f5],[õ], [LowercaseLetter]
[f6],[ö], [LowercaseLetter]
[f7],[÷], [MathSymbol]
[f8],[ø], [LowercaseLetter]
[f9],[ù], [LowercaseLetter]
[fa],[ú], [LowercaseLetter]
[fb],[û], [LowercaseLetter]
[fc],[ü], [LowercaseLetter]
[fd],[ý], [LowercaseLetter]
[fe],[þ], [LowercaseLetter]
[ff],[ÿ], [LowercaseLetter]

音声出力デバイスによるビープ音出力の違い

qiita.com

PowerShell[Console]::Beep()でビープ音を出そうとした際、自分のPCではBIOSによるビープ音出力ではなく通常の音声デバイスによるビープ音出力が行われる。

そのため、PC本体ではなくその時に使用している音声デバイスからビープ音が出るわけだが、この際に音声出力デバイスの種類・接続方法によってビープ音の出力のされかたが異なるという気付きを得たのでメモしておく。

PC本体内蔵の出力デバイスRealtek(R) Audio)

問題なくビープ音が出力される。

Bluetooth aptX(Mpow M5)

  • およそ750ms以下のビープ音は出力されない。
  • 760msを指定すると一瞬だけ音が聴こえる。
  • ビープ音が出力される前の約750msのあいだはホワイトノイズが聴こえる。
  • 上記の記事のように[Console]::Beep()で500msのビープ音を連続して出力すると、ときどき(25回に1回くらい?)一瞬だけ音が聴こえることがある。
  • 一定時間以下の長さの音は出力されない。

そのため、単に音がズレて聴こえるのではなく、「Bluetoothバイスが無音状態から音声出力を始めようとしたけれど、音を出す前にPC側で出している音が終了してしまう」という挙動に見える。

LIGHTSPEEDLogicool G435 Wireless Gaming Headset)

  • およそ340ms以下のビープ音は出力されない。
  • 350msを指定すると、ホワイトノイズの前触れなしに一瞬だけ音が聴こえる。
  • 340ms以下を指定した場合、一瞬だけホワイトノイズが聴こえる。
  • 上記の記事のように[Console]::Beep()で500msのビープ音を連続して出力すると、最初のドの音は聴こえないが、以降の250msのビープ音は一瞬だけ聴こえる。125msのビープ音は聴こえたり聴こえなかったりする。
  • 一定時間以下の長さの音は出力されない。

そのため、単に音がズレて聴こえるのではなく、「LIGHTSPEEDバイスがスリープ状態から音声出力を始めるのに数百msかかる」「LIGHTSPEEDバイスが音声出力を始めようとしたけれど、音を出す前にPC側で出している音が終了してしまう」「そのため、最初の1音は出力されないが、スリープに入らず連続して音を出せば音が出る」という挙動に見える。

平均的プログラマとなるまでに必要な教育時間

satob.hatenablog.com

このようなスキルレベルの指標を設けたとしよう。では、まったくの素人から、ある仕事に最低限求められるスキルレベル、たとえばレベル13~15あたりまで教育するにはどれくらいの時間が必要なのだろうか?

自分のエピソードとしては、高校一年生のときの部活動が思いだされる。授業が終わったあと、だいたい16時から17時くらいまでの1時間、三年生が先生役になって一年生にC言語の本(そのとき使っていたのは「独習C」)の内容を教えていく。この活動は一学期の終わりまで続くので、だいたい3ヶ月半程度行われる。それだけの期間で、新入部員の多く(体感だけど7~8割かな)はCで再帰呼び出しを使ったクイックソートを書くことができるようになるのだ。

別に新入部員は全員がソフトウェア開発をカリキュラムに含む学科の所属ではないし、そもそもその時期には専門の学科でもC言語の授業はろくすっぽ始まっていない。その高校の偏差値が特別高いというわけでもない*1

上記の例をまとめると、N=1だが以下のような感じになるだろう。

  • 偏差値55くらいの地頭
  • 20日/月としてだいたい70日*2
  • 1日1時間の教育として70時間程度の教育
  • 到達レベルは13~15くらい
  • 到達割合は70~80パーセンタイル

さて、こういったデータを集めた研究があるといいのだが……

*1:今と昔では話が違うだろうし、また学科による違いもある。ググって出てきたサイトによっても数値が違うようだが、最近だと52~53くらいのようだ

*2:実際には春休みの期間やGWがあるからもっと少ない

HTTPメソッドのセマンティクスとビジネスロジックのインピーダンスミスマッチ

Webアプリケーションを実装する際に、各処理の実装のトリガとなるHTTPメソッドは何であるべきか?という話は議論の的になりやすいようだ。たとえばStackOverflowによる以下の議論など。

stackoverflow.com

ここでは、特にエンタープライズアプリケーションの開発で議論のポイントとなりそうな点を備忘録列挙しておく。

  • HTMLのformタグはGETPOSTしかサポートしていない。なので、formタグでapplication/x-www-form-urlencodedを送信する前提のアプリケーションの場合、どうしたってPOSTを使ったうえでパラメタに処理のセマンティクスを含める必要がある*1
  • POSTリクエストはブラウザバック時にリクエスト再送可否を聞くダイアログが表示されるが、GETリクエストではそんなものはない。PRGパターンを実装する際に議論になる点。
  • アプリケーションサーバの前段にHTTPサーバやロードバランサを設ける構成の場合、GETリクエストのクエリストリングがそれらのアクセスログに出力されることになる。クエリストリングが個人情報等を含む場合、業務担当者と運用担当者の情報開示範囲の差を考慮してアクセスログsed等でフィルタする*2ことになるが、ビジネスロジック中の個人情報と思われるパラメタをすべて列挙してフィルタすることは難しい。
  • エンタープライズアプリケーションで実行される処理はHTTPの世界に閉じない。たとえば「帳票を印刷する」という処理はそもそも処理結果がHTTPの世界どころか別の機械(プリンタ)から別のメディア(紙)で出てくる。HTTPのセマンティクスはHTTPのプロトコル上で発生する事象しか定義しない。
  • アプリケーションの開発上、ある処理が「特定のレコードを取得する処理」であるかを客観的・機械的に示すことが難しい。たとえばDBやファイルから読み込みだけ行う処理を「取得処理」と定義すると、レコードの取得時に悲観排他や監査証跡記録を行うアプリケーションではレコードの取得処理が「取得処理」にならないことになってしまう。
  • HTTPのプロトコル上に処理が閉じるがRESTful APIのセマンティクスでは表現しづらい処理というものもあり、たとえば「複数レコードを選択して削除する処理をアトミックに行う」などが挙げられる。
  • 上記に挙げたようにビジネスロジックの内容からそのセマンティクスを読み取るのが難しい、あるいは人による解釈の違いが発生しやすい場合、多機能なアプリケーションでは機能ごとにセマンティクスが異なるというケースが発生しやすくなり、それはアプリケーション自体の開発者にとっても、アプリケーションの提供するAPIを利用する人にとっても落とし穴になりうる。
  • これは個人的な意見なのだが、HTTPは(アプリケーション層のプロトコルではあるが)あくまで通信プロトコルなのだから、ビジネスロジックのセマンティクスは通信レイヤについては不可知であるべきでは? 技術的な向き不向き(たとえばリアルタイム音声通信ならUDPが適するとか)は議論の俎上に載せてもよいが、処理の意味が下層のレイヤに縛られるのはレイヤ分離の観点から見てどうなんだ?というのはちょっと疑問に思っている。