JavaScriptのErrorを少しでも他の言語の例外classのように扱えるようにする

まとめ

エラーを定義する際には ES2015 以降の class 構文で以下のようにする。

class CustomError extends Error {
  get name () {
    return 'CustomError'
  }
}

Error

  • JavaScriptMDN</a>

こうしておくと以下の点で便利。

  • name プロパティ ( ここでは実際には getter だけど、外から見れば同じ ) が console などでの表示名として採用されるので見やすい
  • Error の種類の判別を name プロパティの文字列で行うことができる

動作は以下の runtime で確認済み。

  • Node.js 12
  • Safari 13
  • Firefox 70

※ class field は想定していません。これは TC 39 の stage 3 であり、Node.js については 10 では opt-in で利用できる、8 以前では未対応。Babel などのトランスパイラを通せば利用可能ではあるが、pure Node.js ランタイムの利用を考えると、上の getter で定義するのが素直な形。(12以降を前提にできるならそれでもよい。)

cf. tc39/proposal-class-fields: Orthogonally-informed combination of public and private fields proposals

Rubyの例外処理のベストプラクティス

Ruby の場合、例外は以下のように定義するのがベストプラクティスとされている。

module <Namespace>
  class KlassError < StandardError; end
  class KlassSpecificError < KlassError; end

  class Klass
    ..
    raise KlassSpecificError.new
    ..
  end
end
  • まず StandardError を継承して特定のクラスのベースとなる Error クラスを作る
    • StandardError 以外は基本的に runtime 寄りの error となり low level すぎるので避ける
  • ある名前空間内の Error はすべて上で作成したカスタムエラーを継承して Error クラスを作る

こうしておくと最終的にベースとなるカスタムエラークラスを rescue することで特定の名前空間内で発生するエラーに関してはすべて関連するコード内で責任を持って対応することが可能となる。逆に StandardError など、より抽象度の低いエラーを拾いまくって意図しない動作になってしまうことも避けられる。

この class を利用する側では

begin
rescue KlassSpecificError => e
 ..
end

のようにエラーの class を指定して拾うことができる。

これは require した class が global に影響する、module で namespace を構築し衝突を回避できる、この二点によって実現されている。

require / import時代のJavaScriptのclass名はグローバルではない

Ruby では例外の class 名を決めるだけであらかたやることは終わっているのだが、JavaScript では事情が異なる。正確に CommonJS 以降かどうかは勉強不足で知らないのだけど、少なくとも Node.js では

  • exports したもの以外は外部のコードからは直接参照できない
  • exports したものでも require する側で名前の付け替えは自由に行える

ようになっている。ES2015 以降の import / export も同様で、Error に関しては以下のような挙動になる。

dependency.js ( この中で例外が発生する )

class CustomError extends Error {}

class DependencyClass {
  ..
  throw new CustomError()
  ..
}

module.exports = DependencyKlass

dependent.js ( 読み込んだ DependencyClass のコードの中で発生した例外を catch する )

const DependencyKlass = require('./dependency')

class Dependent {
  ..
  try {
  } catch (e) {
    // ここで CustomError という class 名が分からない
  }
  ..
}

上のコードは CustomError を require していないので catch したエラーの class が CustomError であることは分からない。だから上の Ruby のように構文レベルで catch するエラーを指定することはできない。

JavaScrptでErrorクラスを特定する方法

上の問題に対処する方法としては

  1. Error オブジェクトの中の何らかの情報をもとに普通に if で判別する
  2. Error クラスも require する

がある。

しかし、ちょっとやってみれば分かるが解決策として 2 のすべての例外を exports / require するという方法はさすがに非現実的である。そこで 1 になるわけだが、

name プロパティを定義時の class の名前と同じにしておく

のが最も分かりやすくてリーズナブルなので確実と言えると思う。結論としては冒頭に挙げた以下のコードがいちばんよさそう。

class CustomError extends Error {
  get name () {
    return 'CustomError'
  }
}

実際にcatchする方法、テストする方法

catch した例外の name プロパティを見て処理を分ける。

try {
  ..
} catch (e) {
  if ( e.name === 'CustomError' ) {
    ..
  } else {
    throw e
  }
}

テストの際はこれで ok.

assert.throws(
  () => {
    throw new CustomError()
  },
  {
    name: 'CustomError'
  }
)

catch 済みの object が渡ってくるので name でテストする。

Promiseと組み合わせる

Promise の中で Error の発生を記述する方法は throw も reject も同じである。 

func () {
  return new Promise((resolve, reject) => {
    throw new CustomError()
  }
}

func () {
  return new Promise((resolve, reject) => {
    reject(new CustomError())
  }
}

も意味は同じになり、

func()
.catch((e) => {
  e.name === 'CustomError' // <- Error object
})

Promise.catche で Error オブジェクトとして取得できる。catch を書かないと

UnhandledPromiseRejectionWarning: CustomError

のように Node.js では Warning になる。

async/awaitと組み合わせる

async func () {
  throw new Error()
}

これを単に

func()

と呼ぶとやはり先ほどと同じように

UnhandledPromiseRejectionWarning: CustomError

と怒られて Promise が返ってきていることが分かる。これを以下のように実行してみてもやはり同じ。

;(async () => {
  await func()
})()

ただし、以下のようにすると例外として拾うことができる。(Node.js 10で確認。)

;(async () => {
  try {
    await func()
  } catch (e) {
    ..
  }
})()

async/await を使うと一度 Promise にはなるが、同期的なプログラムの時と同じように例外を使って制御することができるようになる。

OOoで使えるクロスプラットフォームで安心なベクタ画像はEMF形式

テキスト処理が大好きだけど、ドローツールにもうるさい wtnabe です。

今回は

  • OOo 3.1
  • 他のドローツール

の組み合わせで安心して使える画像形式は EMF だっていう話。

例によって Twitter のログ

2009.11.19

09:53:36 >wtnabe< ドローはあくまでドローであって、ページに文書を流すの
はワープロやレイアウトソフトの仕事だしょ。.ppt や .odp, .odg を完成
「文書」の形式にするセンス分からん。
11:56:45 >wtnabe< OOoで対応してるepsってどういう形式なんだろう。epsっ
てややこしいよね。
15:05:56 >wtnabe< [速報]WinのOOoがMacで作ったepsのプレビューを表示でき
なかっただけで、画像はハマってた。
15:35:16 >wtnabe< OOoのepsプレビューはtiffならWinでもMacでも表示可能。
ただしそのままexportするとプレビュー画質のままになるので注意が必要。
21:42:11 >wtnabe< もしかして昼間の件はepsじゃなくてemfとかなら何ら問題
なかったのかな。今となってはemfの書き出しができるかどうか分からないん
だが。

2009.11.20

11:45:26 <wtnabe> OOoにちゃんとプレビューを表示できるepsを貼付けたら印
刷もプレビュー品質で出たw 意味ねぇwww
11:48:26 <wtnabe> 結局emfで貼って印刷したが、クオリティ低下激しすorz
OOoとんだ食わせもんだ。

まとめ

  • OOo のドローであれば当然そのままのクオリティを維持して印刷できる
  • ドローと言えば eps. しかし eps は PDF export したときにプレビュー画質になってしまう
    • Macだけで閉じていれば eps でも大丈夫だったような気もするけど覚えていない1
    • 当然、Macintosh形式のプレビューは Windows では表示できない
  • 結局ツール、プラットフォームをまたいで広く使える形式でまともにベクタ画像として使えるのはEMFくらいしかない

そして EMF はやはり EPS に比べるとずいぶん汚くなってしまう。

そういうツールなのだ、OOo は。諦めるが吉。

  1. プラットフォームをまたげないと意味がなかったので 

リモートの機械から growl

リモートの機械でちょっと時間の掛かる作業をやらせた場合、それの終了に気付かずに放置になってしまうことがよくある。そういう作業をいくつかやらせようと思うと、ちょっと時間が経ったら終了の確認をして、のくり返しがとにかく邪魔くさいなぁと思っていたんだけど、

remote の機械から growl に通知させられたら便利じゃね?

と思いついた。

これまで Growl はインストールしていただけでほとんど使っていなかったんだけど、開発時のテスト結果の通知に使っている人を見かけたりしていて、かっこいいなぁと思ってはいた。

でも Growl そのものは Un*x サーバにはインストールできない。どうしようかと思ったけど、そういえば Ruby 用のライブラリとかあったなぁと思い出して調べ始めた。notify 用の起動可能なコマンドがあるのがいいなと思って調べたらどうもこれがよい感じ。

RubyForge: ruby-growl: Project Info

インストールすると growl コマンドが入る。そこで

echo "hoge" | growl -H HOSTNAME
growl -H HOSTNAME -m MESSAGE

みたいな感じで remote host にメッセージを送信することができる。ただし Growl 側に network 経由の notify を listen するように設定する必要がある。

うんうん。こりゃ便利だ。

cf. Twitter / wtnabe: @takano32 sudo gem install …

perldoc で日本語出したければ UTF-8 で

結論から言うと

日本語で書いた pod を perldoc で表示したい場合は UTF-8 で書け

ということらしい。

pod2man までは化けずに処理されるんだけど、man 風の仕上げに使う nroff1 も groff も今のところ ascii, latin1, utf8, cp1047 しか対応してないらしく、euc-jp で書いた pod は化け化けで話にならない。

perldoc -t
pod2text

などで取り出すだけに止めておくのが吉。ちなみに、pdoc は独自に処理しているので大丈夫。#coderepos@freenode で質問したら CPAN で出ればいいし、pod で日本語なんか書かねぇよと言われてしまった。まーcoderepos 怖いそんなもんですね。

昔 euc-jp で perldoc で日本語出てたような気がするんだけど、何かが変わったんでしょうなぁ。もうシステムの標準も UTF-8 だし、Perl も 5.8 で encoding 周り変わったし。

  1. *BSDでは groff による emulate 

nadoka の rss_check.rb で RSS 2.0 とか Atom とか

なんかあれだな。解釈に失敗する feed がいくつもあるな。

RSS Check Error (http://feeds.reuters.com/reuters/JPTop News/) -
undefined method `about' for #<RSS::Rss::Channel::Item:0x870b7d4>
RSS Check Error (http://feeds.feedburner.com/reuters/JP
BusinessNews/) - undefined method `about' for
#<RSS::Rss::Channel::Item:0x86d081 4>
RSS Check Error (http://feeds.feedburner.com/reuters/JP WorldNews/) -
undefined method `about' for #<RSS::Rss::Channel::Item:0x83fb7c4>
RSS Check Error (http://www3.nhk.or.jp/topepg/rss/news/
rss20/cat5.xml) - undefined method `about' for
#<RSS::Rss::Channel::Item:0x82654 14>

うーん。RSS 2.0 や Atom には about なんて要素も属性もないよね。その辺の問題かな?

--- lib/rss_check.rb    (リビジョン 188)
+++ lib/rss_check.rb    (作業コピー)
@@ -67,7 +67,7 @@
             et = e_date
           end
           {
-            :about => e.about,
+            :about => e.link,
             :title => e.title,
             :ccode => 'UTF-8'
           }

でイケたっぽい。work around 万歳。

※ TwitterIrcGateway みたいに入ったときにいくつか最近のニュースが見れたら嬉しいけど、それは proxy として使ってなきゃ無理だわな。うーぬ。やっぱり proxy として使えないとダメか? なんか分からんけど繋がらないんだよなぁ。

頭のいい人から受ける刺激はとても楽しい

「みんながちょっとずつ頭がよくなる世界」──「百式」を運営するビジネスマン (ITmedia)

なるほど頭がいい。ビジネスと IT に対してだけだったはずの強い興味がそれ以外の世界観の構築を補完して優れた見識に結びついている感じ。百式は今までまったく読んだことがなかったけど、少し興味が沸いた。

チェーンメールを支える文化と”対応”

イラクで武装グループに殺害された香田さんの動画メールが出回っているそうだ。携帯でも出回っているそうだが、携帯で見れるってことは誰かが再エンコードしたってことだよな。。。

これっていつまでもなくならないんやろなぁ。幸いというか自分の周りにはそんなことするやつは一人もいないからいいんだけど、善意だろうと悪意だろうとチェーンメールはいかん。

こんなことは散々言い古されたことなのだけど、

  • 現在の一般的なメールシステムでは送り主と内容が正しいかどうか証明できない
  • だからオリジナルの情報源を示すだけにしろ

ということだ。見てーやつはオリジナルの海外のサイト行け。(まー今回の問題はそういうことじゃーないんだが。)今回は中学生だから問題になっているが、どの年齢層でも同じことが起きている。もちろん年代によって好奇心が強かったり無神経さが強かったりと、動機は違うんだろうけど。

ただ、携帯が高機能になり、インターネット接続が当たり前になり、おまけにパケット通信が定額になれば1今の PC と同じレベルでセキュリティとプライバシーとモラルの問題に突き当たる。これは当然の話で、携帯さえ持っていれば小学生だろうが退職したお年寄りも例外はない。2Web に関しては携帯各社が公式サイトと認めたところしか閲覧できないという制限を加えることができるが、メールの場合はそうはいかない。今後携帯各社はなんらかの対応を迫られるんじゃないかなぁ。PC と違ってフィルタリングソフトを有料で入れるとか、そんな解決方法が受け入れられるとも思えないし。

しかしこういうのって噂話と基本的に一緒なんだよな。だからどんなに低俗だろうと犯罪性があろうと高尚だろうと噂話レベルと捉えなきゃいけない。なのに”事実らしきもの”を手軽に転送できるというところがややこしい。昔の噂話よりタチが悪い。上に書いたように技術的に各キャリアの方でなんらかの対応を考えるってこともアリかもしれないが、内容の検閲は現実的ではない以上、教育の方でアクションを起こすことも必要だろう。ただこれもかなり難しい。人間の unofficial な部分に属することだから、家庭や友人関係や習い事などの学校外のところが頑張らなきゃいけないだろう。

  1. これらは既にすべて実現されている 

  2. 機能限定端末の生産はどれくらい続くのだろう? 

米SCO、Linux訴訟の標的をエンドユーザーに拡大へ

from CNET Japan

McBrideによると、IBMとの訴訟が終わるのを待たずに、いまエンドユーザーを相手取った訴訟を起こすのは適切な対応だという。著作権をめぐる訴訟は、IBMとの論争ほど複雑ではないため、結論に達するのもずっと早いというのも、こうした動きに出る理由の一つだと同氏は説明した。

そうなんですか?

不正コピーってことですか? だとするとコピー元のコードの著作権が言えないといけないような。でもそれって終わってないような。なんか勘違いしてます? あれー。よく分からんなぁ。

ぽちっとした

と言っても iBook G4 ではない。

OKI MINI KEYBOARD Pro 日本語 89KEY

Space Saver の動きの固さに手が疲れるのでたまらくなくなって買った。お値段はまったく同じツクリで PS/2 ポートを利用する Plathome Mini Keyboard III より2000円ほど安い8千円。ぷらっとホームは送料が1000円でちと高いが、キーボードの通販なんてそんなにやってないのでそのまま Buy Now ってしまった。

しかし入荷予定は 12月中旬ということで、まだ1ヶ月ほど先である。それまではこの Space Saver で耐えなければいけないと思うと少し気が滅入る。めがねと言いキーボードと言い、どうして俺の評価したものは扱いに時間が掛かるのか。

About

例によって個人のなんちゃらです