開発段階でエラーを隠すなぁ

前々から思っていたことですが、たまたま以下の記事を見つけたのでこの際書くことに。

[.NET] Re: 例外について (biac の それさえもおそらくは幸せな日々@nifty 2009/8/10)Link

これ、全面的に同意。今やってる仕事である人がやった部分には以下のようなのが至る所に。
public bool f1(MyEnum anEnum)
{
  try
  {
    if(anEnum == MyEnum.Item1) return true else return false;
  }
  catch(Exception)
  {
    /* なにもないよ~ */
  }

  return false;
}
関数1行目がtry。勘弁してよ関数全部例外無視ってorz if文で値比較するだけのどこに例外が出ること恐れてるのよ、むしろ出たときの方が知りたいぞ。

別の先輩の話。Visual BasicにはOption ExplicitLink という機能がありまして、これを指定すると全変数をあらかじめ宣言しないとコンパイル時にエラーを出すというもの。一見面倒くさくなるだけの機能に思えますが、変数名の打ち間違えを未然に防いでくれるLink ので、この辺で悩んだ事のある人には便利な機能のはず。Visual Studioでは新しいVBファイルを作るたびに自動的にこの行を入れてくれる設定があります。ところが彼は「Option Explicitを削除するとコンパイル時のエラーが減るんですよ」と、耳寄り情報のように教えてくれたそうで。

製品としてリリースした後ならともかく、開発時やら説明すれば理解してくれる限定ユーザー向けならば、エラーは恐れずどんどん表示してください。放置すると後で分けの分からない現象に悩んだり、たまたま動いているプログラムで満足しているといいプログラマーにはなれないと思います。お願いします、本当に… (直すこっちが迷惑だorz)

[2010/8/31 追記] 前者「関数1行目がtry」な方が書いたコードを久しぶりに見直したら、以下の部分が orz 意味が無いにも程がある。関数の書き始めはtryが癖になっているらしい。
public void foo()
{
  try
  {
    処理
  }
  catch (Exception e)
  {
    throw e;
  }
}

— posted by mu at 02:44 pm   commentComment [0]  pingTrackBack [0]

Windows server一般ユーザーでタスクスケジューラ

備忘録。

Windows Server 2003やWindows Home Serverで一般ユーザーはタスクスケジューラの使用が制限されてます。使えるようにするには、
%SYSTEMROOT%¥Tasksディレクトリにアクセス権限を与える
通常アクセス権限はエクスプローラからアイコンを右クリック→プロパティでセキュリティタブから行えるのですが、このディレクトリはプロパティを開いてもセキュリティタブがありません。コマンドラインから
CACLS %SYSTEMROOT%¥Tasks /E /G ユーザー名:C
  
これでアクセサリ→システムツール→タスクを開くことができます。
at.exe/schtasks.exeに読み取り・実行権限を与える
これらのコマンドを使用する場合。これらのコマンドは通常%SYSTEMROOT%¥system32ディレクトリにあります。こちらはエクスプローラから右クリック→プロパティ→セキュリティタブで設定可能。

一般ユーザーにはコマンドにも権限を与えないとは、さすがはサーバOSと思ったり。

[参考]

[2010/6/25 追記] Windows Home Server再起動後、タスクスケジューラのサービスがアクセス拒否のエラーを表示して起動せず。要調査。

[2010/6/26 追記] 25日の原因は/Eオプションを忘れて実行しちゃったため、既存のシステムユーザーIDのアクセス権を削除してしまってた。

[2020/3/2 追記] Windows Server 2016ではat.exe/schtasks.exeは一般ユーザーにも実行権限が与えられているようです。代わりに管理者でも権限変更不能でしたが。

— posted by mu at 11:45 pm   commentComment [0]  pingTrackBack [0]

 

N’EXのアナウンス

首都圏には羽田空港と成田空港があります。正式名称はそれぞれ東京国際空港と新東京国際空港なのですが、あまりこちらで呼ぶ人は少ないようで。今回は成田空港の話。JR東日本では成田空港往来専用特急「成田エクスプレス」、通称N'EX (Narita EXpress)を提供しています。NをHやSやTで始まる地名に置き換えるというのをついやりたくなるのは、今回のネタではありませんw

成田空港ではN'EXが停車する駅が「空港第2ビル」と「成田空港」の2つあり、航空会社によって降りる駅が違います。大きなところではJALが空港第2ビル駅下車で、ANAは成田空港駅。降りる駅を間違えても無料シャトルバスで反対側に行けるのですが、慣れてない人は目的の航空会社のカウンターが見つからないなどパニックになりかねません。

そのためN'EXでは空港に近づくとアナウンスが流れます。私は早朝に乗ることが多いのでまともに聞くことなく寝ていることが多いのですが、概ねの内容は
  • 利用する航空会社で降車駅が異なります
  • 第2ターミナルを利用する場合は空港第2ビル駅で降車
  • 第1ターミナルを利用する場合はこのまま乗車し、次の成田空港駅で降車
だったかと。続いて英語のアナウンスが流れるのですが、会社のアメリカ人によると以下のことを言っているらしい。
Passengers getting off at Narita Airport Terminal 2 should get off at Narita Airport Terminal 2 and those going onto Narita Airport stay on the train and get off at Narita Airport.
空港第2ターミナルで降りる予定の乗客は空港第2ターミナル駅で、成田空港に行く予定の乗客はこのまま車内にとどまり成田空港駅で降車してください
そのアメリカ人に言わせると、当たり前のことでアナウンスする意味がないだろうと。うん、東京駅で降りたい人は東京駅で降りてくださいと言っているようなもんだね。私も常々「それよりも自分はどちらで降りればいいのかを教えてよ」と思っていたりします(一応各車両室内の前後に航空会社別降車駅の張り紙はあります)。また第1だろうと第2だろうと成田空港なわけでして、成田空港駅という駅名変えたほうがいいんじゃないかなぁ。

てなわけで考えられた末の文章かもしれませんが、奇妙に思う外国人はいるようです >JR東日本様

— posted by mu at 12:19 pm   commentComment [0]  pingTrackBack [0]

冗長なのは分かってるけど

ぴったり当てはまる例が思いつかないので従業員管理の場合。一人の情報を受け渡すために、以下の構造体を定義したとします。
struct Employee
{
  int SerialNumber;  // 従業員番号
  char* OfficeRoomNumber;  // 会社での部屋番号
  char* Name;  // 氏名
  char* Address;  // 住所
  int Age;  // 年齢
}
会社では一人にひとつの部屋を割り当てるとした場合、SerialNumberとOfficeRoomNumberの両方が従業員に対して一意の情報となれます。ここで従業員を登録するために
void SetEmployee(Employee* anEmployee);
を定義。関数を呼ばれたときには引数の内容をデータベースに記録するというもの。ここまでは良かった。次にデータベースから削除するために、この関数に引数を追加、
void SetEmployee(Employee* anEmployee, int add);
「add==0ならanEmployee->OfficeRoomNumberと合致するものを削除」と仕様書に明記されました。私なら新関数RemoveEmployeeとか定義しそうですが、まぁ決めた人の都合です。

まだここまではOK。ところが後になって、引数anEmployee->SerialNumberだけ正しい情報を入れてadd=0で関数を呼ぶ例が出てきました。どっちも一意な情報なのでデータの削除にはこれだけあれば十分と思ったのでしょうが、呼ばれる方はそういう意図は知りません。当然誤動作します。

余計な情報まで含む構造体を引数として使うと定義が曖昧になり、本来必要な情報を入れずに関数が呼ばれる可能性があります。一人でプログラムを組む場合は事情が理解できているので問題とすら思わないかもしれませんが、チームでプログラムを作るときは面倒でも引数は必要十分にしたほうが良さそうです。

結局関数にさらに引数を追加、
void SetEmployee(int SerialNumber, Employee* anEmployee, int add);
SerialNumberが必要な情報だよと関数の定義レベルで明示するように私のほうで変更。案の定「構造体に入ってる情報をなぜ引数にも入れているのか」と質問が来ました。

ちなみに「関数を定義した人」=「仕様書を書いた人」=「SerialNumberだけ正しい情報を入れた人」=「質問してきた人」だったりします。まったく…

以上、今日のお仕事でした。

[2010/6/15 追記] 結局SetEmployee(Employee* newEmployee), RemoveEmployee(int SerialNumber)の2関数体制に変更

— posted by mu at 11:30 am   commentComment [0]  pingTrackBack [0]

PCでmsec時間測定

最初に話を聞いたのはGW前、具体的な内容は伏せるとして要望された内容は

数秒間隔でOn/Offを繰り返すスイッチがあるので、その間隔をパソコンを使ってmsec単位で測定したい。
とあるスポーツに関連するのですが、1/1000秒で時間を計るなんてF1等レーシングカーくらいしか聞いたことないなぁ。使用するスイッチもチャタリングの入りそうなものになりそう。依頼主もその辺の事情は理解してくれていてあまり正確にmsecにこだわらなくて良いとは言ってくれてますが、一応形的にはmsecにしたいところ。またパソコンは持ち運びが容易でないと何かと不便なのでノートPCも考慮に入れる必要があり、拡張ボードもかなり制限される。

ちなみにWindowsが提供するmsec単位の時間関数を使うという答えは残念ながら×。時間関数の精度はともかくとして、Windowsの仕組み上スイッチがOn/Offされた瞬間(もしくはそこから毎回安定した遅延で)時間関数を呼び出すことはかなり難しいから。HDDアクセスが入ったり、CPUの負荷状態が変わってスレッド切り替えに変化が生じると、msec平気でばらつきそうです。

以下検討の過程
カメレオンUSB+ロジアナキット
依頼主が考えていたのはカメレオンUSBLink +ロジアナキットでサンプリングレートをkHzオーダーにして計るというもの。USBでデータ転送するのでノートPCでもOK。 私も最初この方法で調べてたのですが、ひとつ疑問が。「ロジアナキットって、何分も連続してデータ取れるの?」なんか構造を見る限り、ロジアナキットのボード上にあるメモリに書き込んでいって、たまったらUSBで転送。転送中はデータ取得できないんじゃないかと。機能にしては安いとはいえ1万円以上するこの回路、買ってやっぱりだめでしたではお金がもったいない。
サウンドカード
連続データ取得が期待できる。WindowsはそれこそHDDの許す限り録音をやり続けるし、サンプリングレートも44.1kHzあれば十分、ノートPCにだって標準で付いている。世の中にはサウンドカードを利用したオシロスコープLink もある。スイッチのOn/Offを録音信号レベルに置き換えて入力すれば、Windows側はDirectSoundでデータを取り込んでいけばいい。が、これもサウンドカードは低周波をまともな波形で取れないLink という欠点が発覚。チャタリングの素性次第では何とかなるかもしれませんが。
再びカメレオンUSB
今度はカメレオンUSB単体。高速で連続データ取得Link する実例もあるので、できないわけじゃない。ただその場合カメレオンUSBで使われているアルテラ用のプログラムを書く必要があり、そんなの使ったことないorz どうせ勉強しなければいけないなら、PICでもAVRでも変わりないなと。
というわけで、現在ストロベリーリナックスのAVR AT90USB162を使ったボードLink を検討しています。こいつの利点としては
  • 開発環境がCで無料で入手可能
  • CDC(USBをCOMポートに見せかける機能)のサンプルコードLink が入手可能。COMポートなら.NET FrameworkとのつなぎにUnmanaged C++を使わなくても良さそう。
  • このボード単体でUSBからプログラムの書き込み可能。ブートローダ機能で何度でも書き込み可能状態に戻せる。
さぁて、うまくできるかなぁと。

[2010/6/25 追記] 続きLink

— posted by mu at 11:17 pm   commentComment [0]  pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.1567 sec.
prev
2025.9
next
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30