【Scala】Eitherについて、個人的なまとめ【チラシの裏】
今日、会社の先輩にScalaのEitherについて聞かれた。
今のチームで一番Scalaに触れているのは多分僕だし、Repositoryの返却値をTryなどにくるむのはどうだろうと提案した事が発端になる。
けれども僕はTry(役目としてはEither)のメリットを上げきれなかった。
正直悔しいので、個人的にまとめてみる
チラシのウラっていうのは、自分の考えをまとめるために書きだしたからなので、ひどい乱文だったりする。
【条件】
製品はWebアプリであり、mysqlとredisと連携する。
playframeworkを使用している
【Eitherのメリット】
エラーが起こることを型で表現できる
エラーという副作用を型で表現することで次の受け取り手が適切な処理をかける
参照透過性は、遅延評価が原則ではないScalaでは、設計的な意味合い以外での効能は薄い(?)
【デメリット】というか先輩から突っ込まれて答えられなかった事
メモリ領域を食い尽くすような例外を考えたらすべてEitherでくるまないとダメではないか
すべてくるまないのであれば、どのレベルの例外からくるむべきかの閾値は?
適切な処理の箇所がレイヤ的に上部にあった場合、ひたすらTryで返すことになるのでは ->冗長では
直近思いつく最大のメリットは、やはりそのメソッドの処理の結果として例外なりのエラーが起こるという文脈を型で表現できる事だと思う。
Optionが処理の結果、nullが入る可能性がある事を表現するように、エラーを表現して渡すことで対エラー処理を忘れることなく実行できる
とはいえ、アーキテクチャとして、そのエラーを解釈して処理を分ける部分がかなり上位のコントローラ層にあり、そこでエラーをキャッチしてユーザにエラーレスポンスを返すという仕組みを用意していた場合、いちいちTryでくるんで返すのは無駄では、というのもある。
ただし、その場合、処理の結果として例外が発生する事を型で表現できず、その文脈が欠落する。
チームプロジェクトの場合、前提条件などの制約が入る。自由にしてしまうと、予想外の例外や責務がわかりづらくなり、プロジェクトが拡大するにつれてバグが生まれやすい環境になって、生産性も再生産性も落ちる
だからそこに制約が入る
型とは制約だ。それを言語レベルで担保することにより目に見えない副作用を制限する役割を担保する。
それとは別に、コーディング規約や設計上の制約、つまりはコード外での制約もある。
コードの外で制約を表現すると、プロジェクトのコンテクストが一段階複雑になり、プロジェクトでの経験値が必要になる。
要するに、EitherなどのMonadの最大の恩恵は、型がその経験を担保する事により、コードの世界だけでプロジェクトの設計を把握できるようになることなのではないだろうか。
そのかわり、いちいちMonadでラッピングするため、それを解決する手間がかかる。のかもしれない
でも、Eitherでくるめべき例外の閾値みたいなのは、正直わからないな……外部と接続するところが副作用だからくるむべきというのはなんとなくわかるんだけれど、すごい感覚的な気がする。
PCを新調しました
11/5 01:35 StrageになっているのをStorageに修正
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
表題の通り、PCを新調しました。
学部時代から就職するなりしたら20万という大金をかけてPCを作りたいと考えており、今回その念願がかなったことになります。
当初BTOでPCを注文しようと考えていたのですが、会社の新卒同期に「20万というハイエンドだったら圧倒的に自作のがいい」という提言を受けて、自作に挑戦してみました。
とはいえ、百戦錬磨の彼に「昼飯代で一台組むの手伝って」とお願いしてほとんど彼の出す指示にしたがってロボットの如く組み立てたので、「PC組みました(ドヤァ」なんて偉そうに言えない僕です。
念願かなって手に入れたPCは頭が悪いくらいにハイスペックに仕上がりました。僕はエンジニアであると同時にゲーマーなので、この際、汎用性を残しながらもやばいゲーミングPCを組もうというコンセプトで出来上がりました。
ということで構成
M/B : ASUSTek ATX P8Z77-V PRO
CPU : Intel Core i7 3770K 3.5GHz 8M
RAM : Cetus DCDDR3 8GB * 4
GPU : GeForce 680 2048MB * 2
Power : X7-1200 1200W
Main Storage : v4 SSD 256GB
2nd Storage : Barracuda 7200.14 3.5inch 2TB 7200RPM
OS : Windows 7 SP1
Case : COSMO'S II
Other : USB3.0とか
Monitor : EIZO FS2333
Money : 250k JPY
大体こんな感じです。
GPU二台ぶち込まれているあたりに頭の悪さを感じてくれたらいいと思います。
プログラミングもやるでしょうけれど、メインはやっぱりゲームです。
まだグラフィック関係のベンチマークを試していませんが、とてもグラフィックのパワーを必要とするゲームのグラフィックオプションをすべて最高にしてもカクついたりしません。
最強すぎる。
しばらくPCに困ることはこれで無さそうです。
夢がかなって満足してます。
PHPにおける変数名と関数名の大文字小文字の区別
PHPにおける比較演算子の精度については度々話題になる。特に
==
による比較については散々ネタにされつくされている。この曖昧な比較は、ユーザに手軽にプログラミングを行なって欲しいという想いがあってこそだと好意的に受け取るとしよう。
それはともかく、PHPは文字列を比較する時に、大文字と小文字を区別して比較するのだが、関数名に関しては別である。
<?php function FOO(){ echo "BAR"; } function foo(){ echo "bar"; }
これを実行するとFatalエラーが発行されてPHPが止まる。理由は同じ関数名の二重宣言だ。
ちなみに、変数名はそれぞれ別々になる。
<?php $FOO = "BAR"; $foo = "bar"; echo $FOO;
これは正常にBARと出力されるはずだ
つまり、PHPは、
変数に関しては大文字小文字を区別するが、
関数名に関しては大文字小文字を区別しない。
ちなみにクラス名に関しては関数名と同じく区別しないようだ。
これから分かることは、名称が衝突しそうな汎用的なクラス名や関数名の宣言は、大規模開発だと思わぬタイミングで衝突してひどい目を、後々の誰かが見てしまうハメに陥ることがあるので、くれぐれも注意しよう。
ちなみに変数名や関数名などの名称というのはコードの可読性とダイレクトに関係するので、日頃から気をつけるといいかもしれない。
参考
PHP: 変数 - Manual
PHP: 関数 - Manual
ホントエライ目にあった……
cakePHPによるXSS対策とDRY原則 【結論無し】
先日の記事(cakePHPにおけるXSS対策)で僕は、XSS対策するならコントローラとモデル両方に記載すべきだと書いた。この主張は今でも変えない。
が、これはDRY原則に反している。
実際のメソッドはライブラリに書いてあるとしても、その呼出を両方に書いている事には変わらない。つまり、MVCパラダイムが二重化を強要しているということになる。
前は「まぁ、XSS対策を外すなんてことは考えられないし……」と思っていたが、何かの拍子で外さなくてはいけなくなった時にめんどくさくなったらかなわないし、やはりこの原則を守ることに越したことはないので、何かしら手は無いか考えている。
現段階では、コントローラで処理したデータ($this->Model->save())を、そのままViewに返すのではなく、再びモデルから取り出すというパターンを常に採用する、という案がある。これだとコントローラにXSS対策の関数をかませなくても、モデルにかけば全てオッケーなのだが、これは計算リソースと時間リソースの無駄遣いのため、見送りたい。
逆は先日の記事の通り、パラダイムを裏切った設計になるのでダメだと思う。
さて、何か画期的な解決策はないものだろうか。
cakePHPにおけるXSS対策
cakePHPのModelは、どうやら
$this->Model->query($sql);
という風でなければ、つまり
$this->Model->find();
$this->Model->save();
のような、モデルがORMで提供しているデータアクセスメソッドを使用した場合であれば、SQLインジェクション対策を行なっているらしい。
cakePHP自体が海の物とも山の物ともつかぬ代物なので、こいつがどれくらいの耐久度を持っててどういう潜在的脆弱性があるかわからないが、僕は基本的にcakeに任せてデータアクセスを行なっている。もちろんそのバージョンの脆弱性は検索を行なってもらうとして。
問題は、XSS対策である。
cakePHPは現行2.1.3までだと特にXSS対策をおこなっていない。ここのサニタイズは基本的に自分で行わなければならない。
僕はVendorにhtmlspecialcharsを配列の要素に対しても行なってくれる関数をおいて、
App::import("Vendor","functions");
でインポートして使った。
が、現行のネット情報を見てるとサニタイズはコントローラで行なっているのが殆どだった。
もちろんbeforeFilterを使えばそれは可能だが、きちんとMVCのモデルに則ってやるとしたら、入力ソースをそのまま画面に反復的に出す場合はコントローラ、データソースに記録する場合はモデルで行った方が健全だ。
つまり、アプリケーションによって実装は当たり前のように変わるけれど、基本的に両方ともに実装した方が望ましいだろう。
コントローラであれば、AppControllerのbeforeFilter();、モデルであればAppModelのbeforeSave();に該当するデータをサニタイズするコードを両方書いた方が好ましい。
そうすれば何かしらの事情でhtmlspecialcharsを外さなきゃいけない時も簡単に更新が出来る。コントローラの更新を行なってもモデルの健全性は保たれるし、モデルの更新を行なってもコントローラの健全性は保たれる。
割を食うのは全て外す時で、その時一つの機能、メソッドを2つ実装している事に気づかずハマる可能性はなきにしもあらずだけれど、外部に公開するウェブアプリであればそんなことはまず無いと思うので、大丈夫だろう。
Linux(CentOS 6.2)環境下におけるMySQLのインストール時の注意
まずは魔法の呪文(もとい、魔法管理システム)のyumさんで
sudo yum install mysql-server
sudo yum install mysql-devel
インストール。
そんでもって設定ファイル書き換え。
# character-set
character-set-server=utf8
skip-character-set-client-handshake
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqldump]
default-character-set=utf8
ココらへんを追記した。
(ここを参考にしました:http://weble.org/2011/05/16/sakura-vps-and-centos)
ってことで起動
sudo mysqld start
と思ったら 、エラー吐いてくれやがった。
なんだろうと思ったら、characterがcahracterになってた。
やっちゃったZE☆
しかしここで罠発動。設定ファイルを書き換えても起動しない。初期状態に戻してもダメ。
なんでじゃいと色々試した末にアンインストール
sudo yum remove mysql-server
それでも治らない。再びアンインストールして、今度は
rm -rf /var/lib/mysql
して、再インストール。設定ファイルを書き換えないまま起動
成功!
Windowsでmysqlぶち込んだ経験がある方は知ってると思うけれど、どうやらmysqlは初回起動が失敗したらそのままその設定ファイルは怪しいもんだと判定して参照しない様子。
つまり初回でミスるともうダメということ。(らしい。要検証)
なので、mysqlの設定ファイルの書き換えは慎重に。ちゃんとtypoないか確認してから保存してくださいねー。