2015年6月30日火曜日

大発見。仕事しながらハニーローストピーナッツを食う方法。

プログラムを書くなんてことを仕事にしている人は、たいがい夜型人間で、真夜中あたりに調子が出てきたりということも多々あると思います。

ちょっと小腹が空いたりして、でもやはりこういう場合、スカした健康食みたいなものではなくて、ジャンクな何かをつまみながら、安いコーヒーか、炭酸飲料、もし許される状況なら軽いアルコールなどを啜りながら無心にコーディングするのが乙なものです。

そんなわけで、私はしばしば「STRIKE EAGLE  ハニーローストピーナッツ」というのを食べながら仕事をすることがあります。これ自体は実はカルディなどのちょっと小洒落た食材店で売ってることが多いのですが、F15ストライクイーグルをパッケージにデザインしてしまう頭の悪そうな感じ(どうせ創業者が元パイロットとかなんではないかと想像)と、軽い蜂蜜風味に塩分控えめとかそういうくだらないことは一切考えない高濃度の塩が、なかなか美味いのです。

ただ、豆が調味料で非常に粉っぽくなっており、食べると指がベタベタになるのでタイピングに支障をきたすのが問題でした。ティッシュ片手に拭きながらやるのですが、粉というのはティッシュでは拭き取りにくく、始末が悪い。

ところが昨日、デスク上を見渡してはたと閃いて試した方法がこれです。

手に塩がつかない!

正方形のポストイットを使ってるのですが、こいつを1枚、半分に折るとちょうどいい感じのスプーンになりました。一度に豆が3〜4粒ほどすくえます。

口に入れる時は紙を舐めないように流し込みます。で、食べ終わったらポストイットは丸めて捨てます。非常に衛生的であり、使い捨て食器の中ではトップクラスに低コストだと思われます。

仕事中以外では、ポストイットが手元にないのでわざわざこうする必要はないのですが、仕事中ならポストイットはたいがいあるので、便利な方法となります。


みなさんも是非、お試しください。

2015年6月25日木曜日

数字を3桁で区切るのが愚かしいというバカバカしい話

金額を書くとき、1,000,000みたいに3桁ずつカンマを打つじゃないですか。

ちょっと作ってたプログラムにユーティリティ関数を用意してやろうと思って、文字列の"1000"を"1,000"に変換するのを作ったのです。で、名前をつけようとして、はて、こういうの何て言うんだろう?と思いまして。

tri-ナントカ、とか、気の利いた単語があるのではと思って検索したら、「日本語は4桁ずつ(万、億、兆・・・)で区切るのに、英語の表記に毒されて3桁で区切るのはわかりにくいし、英語にあこがれて思考停止する愚かな行為だ、的な雰囲気の話がいくつも見当たりました。

検索結果のプレビュー程度しか見てないのでいちいちどこのブログだとか言わないけど、わりと多くの人が思いつくネタのようでぱっと見ていくつもの記事が見当たったので、特定の誰かの意見というよりは、まあある程度一般的な意見(一部ではあるけど稀ではない)ということでいいかなと思います。書いてる本人は目から鱗の有難い話と思っているかどうかは別に知らないけど・・・。

で、思うに、すげえどうでもいいですね。こういう話。どうでもいいから気にしなきゃいいんだけど、あまりにバカバカしくてつい。

数字の書き方なんかでナショナリズムを主張するこたないと思うのです。つうか、そこまで言うなら「10,000ではなく1,0000とすべきだ」ではなく「一万とすべきだ」と言えばいいじゃない。

アラビア数字を使って発展した科学の成果の恩恵に生まれてから死ぬまで24時間365日もれなく与って暮らし、その最たるものであるインターネッツなどで言論人を気取りながら、「日本語がー」とかってのは・・・まあ、昔の酔っ払い頑固親父の薀蓄話みたいで何ともくだらないな、と思いました。ネットなんてやってないで自分の家族か飲み友達にでも語ってりゃいいのに。

だいたい、「実は3桁区切りは英語の表記(thousand, million, billion..)には良くなじむ」みたいな話も書いてあったりするのだけど、実はもクソもないというか、そんなことは並の勉強をした中学生以上なら誰でも知ってるけど当然過ぎるのでイチイチ何かの発見かのように言ったりはしない、という類のことであって・・・。まあ、どうでもいいのですかね。

ちなみに、3桁区切りはthousand separatorと言うとWeblioには出てたけど、それじゃ長いので関数は単に"digit"という名前にしました。あんまり処理内容を表してないのだけど、数字に使うということはわかるだろうし、まあ、ともかく利用場面を考えると短い名前であることが優先だったので。

2015年6月11日木曜日

AWS S3にAWS SDK (Java)でファイルを送る

表題の通り。

SDK自体は、Gradleのbuild.gradleに
 runtime 'com.amazonaws:aws-java-sdk-iam:1.9.39'
 runtime 'com.amazonaws:aws-java-sdk-s3:1.9.40'
と書いて取得。SDK全部なら1行で済むが、1行で済んで楽なのは書いてる人だけで、ほぼ使わない100MB以上のファイルをいちいち取得したりビルドさせたりというのはコンピュータが可哀想と感じます。

ファイル送るのはこんなで出来た。


public void store(File file){
final String accessKey = "XXXXXXXXXXXXXXXX";
final String secretKey = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
AmazonS3 s3 = new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey));
s3.putObject("sampleBucketName", file.getName(), file);
}

ポイントとして、

  1. IAMでユーザーを作って、acceccKeyとsecretKeyを払い出しておく
  2. バケットのアクセス 権限(バケットポリシー)で、ユーザーにアクセス許可しておく(今回は特定バケットを特定ユーザーに許可したかった)
    1. バケットポリシーの編集は、手でやる場合にインデントに全角空白があったりするとJSONパースエラーになる(くだらないが、AWSの画面では空白見えないので一瞬はまった。エディタにコピーした方がいいな)
    2. Principalに、IAMのURIを指定する(複数の場合、{"AWS":["uri 1","uri2"]}。たぶん)

2015年6月4日木曜日

MacBook AirでSafariが起動しない件

数日前から、自分のMacBook AirのSafariがうんともすんとも言わない。

Safari 起動しない とかで検索すると、iOSの話がよく出てきて、設定アプリからリセットしろとか書いてあるが、何せ俺はYosemiteなので。そしてSafariは落ちるとかじゃなくて、そもそもアイコンをクリックしてもぴょんぴょんすらしないので、リセットも出来ない。

困ったなあ、なんて検索していたら

 ~/Library/Preferenecs/com.apple.Safari.plist
 ~/Library/Caches/com.apple.Safari

を削除すればいい的な話を見かけたので、ターミナルを開きrm -rfなんかしてガツっと削除してやった。

するとどうだろう!

やっぱり全然起動しない!

ちなみにゲストユーザでも起動しない。どうしたものか。

と、そこでふとOSを再起動してみたら、治りました。めでたしめでたし。

* ファイル削除前にも再起動はしたけど、それではダメだった。削除→再起動で治ったみたい。

2015年5月29日金曜日

Amazon SESのバウンスをSNSで受けてSQSに渡しアプリで拾うまで

Webアプリを作っていたら、メールサーバがないことに気付いた。以前の会社では誰ぞに「メールサーバはどれを使えばいいですか?」と聞いておけば出来てたのに。

頭来たので適当にSMTPサーバ?今もSedMailとかでいいの?を立てようかと思ったのは一瞬で、スパム対策が進んだ昨今、10年前のように適当にサーバを設置してパカパカ送ってたら問題になるというか止められるだろう、と。

そう思って、Amazon SESを使ってみようと思ったが、バウンスメールを出すと止められるから嫌だと上司に言われた・・・が、SESでなきゃISPに止められたりするのであって結局どこを使うのであってもバウンス対策は必要。

バウンス対策ごと丸投げできるメール配信サービスは、今回の自分のようにメールテンプレートに大量の変数を使うような場面ではキツい気がするし。

ということで、SESでバウンス対策だけはある程度やってみるという覚悟を決め、ある程度試してみた作業ログ。


※ 適当にググっていろいろ見た結果を適当に混ぜてやった感じなので、まともに調べてる方は他所を見た方が正確だと思われます。


準備

  1.  送り元になるアドレスを最初に登録して、Verifyしないといけない。(登録アドレスに送られてきたメールをクリックする)
  2.  これでとりあえず登録アドレスから登録アドレス向けにだけメールが送れる。
    1.  このアドレスでは不達のテストとかは不可能。なので、テストアドレスがある。 (ドキュメンテーション Eメール送信のテスト) http://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/mailbox-simulator.html

バウンス 


  1. バウンスはAmazon SNSで受け取る。
  2. SESのコンソールのEmail Addresses、アドレスを選択して上部からView Detailsを選ぶ。さらにNotrificationsを開き、さらにボタンを押すと通知の設定ができる
  3. Topicを作る的リンクが地味にあるのでそれを押してTopicを生成する→SESのリージョンでSNSのTopicが出来てる
    1.  AWSのダッシュボードで別途に作っておいたTopicは選択できなかった。なんぞ?→リージョンが違った。SESのリージョンに合わせないとダメ
  4.  Amazon SNSのダッシュボードに移動、Subscriptionsで、バウンス発生時のアクションを決める。仮にEメールにしてみた。設定したアドレスに購読Verifyメールが来るのでOKする。
  5. bounce@でテストメールを送る(SESコンソールから)
  6. バウンス情報がJSONになってメール来た



が、メールじゃバウンスを処理できない。・・・こともないが、やりにくい。こちらのシステムもずっと動いているわけじゃないので、IMAPで取ってきて「まだ見てないの」を開封してみて・・・というあたりが面倒になりそう。


そこで、Amazon SQSを使う。

Amazon SQSでSNSメッセージを受け取る設定


  1. Amazon SQSで、キューを作る。名前は"SESBounce"とか。
  2. SNSのサブスクリプションにエンドポイントをSQSにしたのを作り、さきほどのキューを指定。
  3. ところがバウンス来ない。
  4. キューのダッシュボードに戻り、作成済みのキューに「キュー操作」ボタンでSNSのサブスクリプションを設定
  5. SESからbounce@にテストメールを送ると、キューに1つタスクがたまった



キューからタスクを取り出さなくてはならない。これはバッチで良い気がする。

Amazon SDKを使う。

「gradle aws sdk」とかググってMavenリポジトリに行き、IDを取得、GradleでSDKをインポート。zipでも100MB超。デカい!

SDKでSQSに接続する


  1. まず、認証情報が必要。AWSコンソールのIAM(Identity and Access Management )を開き、左「ユーザー」メニューで新規ユーザー追加。名前だけ入れる。と生成され、アクセスキーとシークレットキーが出てくる。
  2.  このキーを使ってAPIで接続できるが、作ったユーザーには何の権限もないので接続拒否される。IAMのユーザー設定画面で「ポリシーのアタッチ」をして利用する機能を許可する。
  3. 次のようなコードを書いて実行する。


まあ、センスのないコードだが手順的なものとして・・・。

注意:なぜか、キー"Message"の値のJSONがわざわざエスケープして文字列にしてあるので、一度文字列として取り出してから再度JSONとしてパースしている。その中のJSONはそのままだったりするのに不思議だ。

static void testQue(){
final String accessKey = "XXXXXXXXXXXXXXX";
final String secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
AmazonSQSClient sqsc = new AmazonSQSClient(new BasicAWSCredentials(accessKey, secretKey));
//ReceiveするとSQS上のメッセージがデフォルト30秒、他からロックされる
//SQSのコンソールで確認できるキューのURL
ReceiveMessageResult receiveMessage = sqsc.receiveMessage("https://sqs.us-east-1.amazonaws.com/yyyyyyyyyyyyy/SESBounce");
receiveMessage.getMessages().forEach((msg)->{
System.out.println("=======================================");
String body = msg.getBody();
JSON json = JSON.of(body);
System.out.println("Bounced:");
try{
JSON message = JSON.of(json.getPlainString("Message"));
for(JSON bnc : message.getJSON("bounce").getJSONs("bouncedRecipients")){
System.out.println("emailAddress : " + bnc.getString("emailAddress"));
System.out.println("status : " + bnc.getString("status"));
System.out.println("diagnosticCode : " + bnc.getString("diagnosticCode"));
}
//message.getJSONs("bouncedRecipients").forEach((bnc)->System.out.println(bnc.getString("emailAddress")));
}catch(Exception ig){
ig.printStackTrace();
}
System.out.println("=======================================");
});
}

実行したらコンソールにバウンスしたアドレスと理由が出た。ここまでくれば、後はこれをリストにしておいてメール送らないようにすればいいのだろう、と。


AWSってなんだか面白い気もしてきた。

Webアプリケーションからのメール送信につかうMTA

MTA?というかメール送信サービスというか。メルマガシステムが作りたい、というわけではないが、普通にメール送信もあるWebアプリケーションを作りたいので、何かが必要だし、いきなり送れなくなるとかは困る。かつ、メール送信自体が要件というわけでもないので手間も知恵もコストもかけたくない。

で、どうしたらいいのかと考えている。


サーバ立てる云々じゃなくGmailを使うというのはお手軽。だが、本来、普通に使うためのアカウントなので・・・

  • Gmailのアカウントは、 1アカウントで1日500件までしか送れないらしい
    • メッセージ数ではなく宛先数。CCに500件入れたりしたら1発でアウトということ
  • 年間6000円で、特定のアカウントに対して上限を2000件に引き上げ可能

ソースは↓
http://d.hatena.ne.jp/mitaina/20100205/1265366858



Amazon EC2にサーバを立てるという手がある。が、

  • ISPのスパム対策に引っかからないためには、ただSMTPサーバを置けばいいというものではない
    • おもにDNS関連を含む各種設定が必要(DNSにも)
    • バウンスメール対策をしておかないといけない
こういうことは、俺のようにコンピュータが苦手な人間にはつらい。


そこで、Amazon SESを使うという手がある。が、
  • DKIM設定をしないと、メールに「amazonses経由」 と出てくる
    • Amazon Route53を使っていれば簡単らしい
  • バウンスが多かったりすると、Amazonに止められる


メールが500件/日に達するほどでもないなら、Gmailでいい気がする。なにせ簡単。つうか開発的なことは何もない(送信処理を作る以外は)。

EC2はハードルが高い。なにせ俺はかつてネットワークスペシャリストの資格を受験して落ちたほどの男だ。DNSと聞いただけで震えがくる。

Amazon SESは、バウンスのせいで止められるのが心配。しかし、よく考えるに、バウンスを出してばっかりいたら止められるのはどこでも一緒だし、その対策を講じないというのではさながらスパマーなわけだ。

だとすると、やはりAmazon SESを使うのが良い気がしてきた。

2015年4月3日金曜日

オブジェクト指向におけるモデリングのアンチパターン

「このXXXは、YYYとしても使える」というようなのを作らない。


・・・こうネガティブなコンテキストで書くと、誰だってそんなことしないと言うだろうし、俺だってそう思ってるわけですが、いざコーディングしている時にふと、「おお!このオブジェクト(プロパティ、変数、なんでも)を使ってこんなこともできるのでは!まさに一石二鳥!」とか思ってノリノリになってたりするものです。少なくとも私はそうです。

が、一人二役とか一石二鳥とか考えるということは、すでに異なる2種類の何かがあるのが明解なのだから、それらはやはり別に設計しておくべきなんだと思います。たとえ、その時点の簡単な実装では同じに見えるオブジェクトでも、いずれは別の役割と振る舞いを持つんだろうと。